001
014
015 package com.liferay.portal.dao.orm.jpa;
016
017 import com.liferay.portal.kernel.dao.orm.ORMException;
018 import com.liferay.portal.kernel.dao.orm.SQLQuery;
019 import com.liferay.portal.kernel.dao.orm.Type;
020 import com.liferay.portal.kernel.util.ListUtil;
021 import com.liferay.portal.kernel.util.StringBundler;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.UnmodifiableList;
024
025 import java.lang.reflect.Field;
026
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Collections;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.concurrent.ConcurrentHashMap;
033 import java.util.regex.Pattern;
034
035
040 public class SQLQueryImpl extends QueryImpl implements SQLQuery {
041
042 public SQLQueryImpl(
043 SessionImpl sessionImpl, String queryString, boolean strictName) {
044
045 super(sessionImpl, queryString, strictName);
046
047 sqlQuery = true;
048 }
049
050 public SQLQuery addEntity(String alias, Class<?> entityClass) {
051 String columnAliases = null;
052
053 try {
054 String[] columnNames = _getColumns(entityClass);
055
056 if (columnNames.length == 0) {
057 columnAliases = StringPool.BLANK;
058 }
059 else {
060 StringBundler sb = new StringBundler(
061 columnNames.length * 4 - 1);
062
063 int i = 0;
064
065 for (String column : columnNames) {
066 sb.append(alias);
067 sb.append(StringPool.PERIOD);
068 sb.append(column);
069
070 if ((i + 1) < columnNames.length) {
071 sb.append(StringPool.COMMA_AND_SPACE);
072 }
073
074 i++;
075 }
076
077 columnAliases = sb.toString();
078 }
079 }
080 catch (Exception e) {
081 throw new ORMException(e.getMessage());
082 }
083
084 String escapedAlias = Pattern.quote("{" + alias + ".*}");
085
086 queryString = queryString.replaceAll(escapedAlias, columnAliases);
087
088 this.entityClass = entityClass;
089
090 return this;
091 }
092
093 public SQLQuery addScalar(String columnAlias, Type type) {
094 columnAlias = columnAlias.toLowerCase();
095
096 String q = queryString.toLowerCase();
097
098 int fromIndex = q.indexOf("from");
099
100 if (fromIndex == -1) {
101 return this;
102 }
103
104 String selectExpression = q.substring(0, fromIndex);
105
106 String[] selectTokens = selectExpression.split(StringPool.COMMA);
107
108 for (int pos = 0; pos < selectTokens.length; pos++) {
109 String s = selectTokens[pos];
110
111 if (s.indexOf(columnAlias) != -1) {
112 _scalars.add(pos);
113
114 _scalarTypes.add(type);
115 }
116 }
117
118 return this;
119 }
120
121 @Override
122 public List<?> list(boolean copy, boolean unmodifiable)
123 throws ORMException {
124
125 try {
126 List<?> list = sessionImpl.list(
127 queryString, positionalParameterMap, namedParameterMap,
128 strictName, firstResult, maxResults, flushModeType,
129 lockModeType, sqlQuery, entityClass);
130
131 if ((entityClass == null) && !list.isEmpty()) {
132 list = _transformList(list);
133 }
134
135 if (unmodifiable) {
136 list = new UnmodifiableList<Object>(list);
137 }
138 else if (copy) {
139 list = ListUtil.copy(list);
140 }
141
142 return list;
143 }
144 catch (Exception e) {
145 throw ExceptionTranslator.translate(e);
146 }
147 }
148
149 @Override
150 public Object uniqueResult() throws ORMException {
151 try {
152 Object object = sessionImpl.uniqueResult(
153 queryString, positionalParameterMap, namedParameterMap,
154 strictName, firstResult, maxResults, flushModeType,
155 lockModeType, sqlQuery, entityClass);
156
157 if (object instanceof Collection<?>) {
158 Collection<Object> collection = (Collection<Object>)object;
159
160 if (collection.size() == 1) {
161 object = collection.iterator().next();
162 }
163 }
164
165 if (_scalars.size() == 1) {
166 object = _transformType(object, _scalarTypes.get(0));
167 }
168
169 return object;
170 }
171 catch (Exception e) {
172 throw ExceptionTranslator.translate(e);
173 }
174 }
175
176 private String[] _getColumns(Class<?> entityClass) throws Exception {
177 String[] columns = _entityColumns.get(entityClass);
178
179 if (columns != null) {
180 return columns;
181 }
182
183 Field field = entityClass.getField("TABLE_COLUMNS");
184
185 Object[][] tableColumns = (Object[][])field.get(null);
186
187 columns = new String[tableColumns.length];
188
189 int i = 0;
190
191 for (Object[] row : tableColumns) {
192 String name = (String)row[0];
193
194 columns[i++] = name.toUpperCase();
195 }
196
197 _entityColumns.put(entityClass, columns);
198
199 return columns;
200 }
201
202 private List<?> _transformList(List<?> list) throws Exception {
203 if (!_scalars.isEmpty()) {
204 Collections.sort(_scalars);
205
206 if (list.get(0) instanceof Collection<?>) {
207 List<Object> newList = new ArrayList<Object>();
208
209 for (Collection<Object> collection :
210 (List<Collection<Object>>)list) {
211
212 Object[] array = collection.toArray();
213
214 if (_scalars.size() > 1) {
215 Object[] values = new Object[_scalars.size()];
216
217 for (int i = 0; i < _scalars.size(); i++) {
218 values[i] = array[_scalars.get(i)];
219 }
220
221 newList.add(values);
222 }
223 else {
224 newList.add(array[_scalars.get(0)]);
225 }
226 }
227
228 list = newList;
229 }
230 else if (list.get(0) instanceof Object[]) {
231 List<Object> newList = new ArrayList<Object>();
232
233 for (Object[] array : (List<Object[]>)list) {
234 if (_scalars.size() > 1) {
235 Object[] values = new Object[_scalars.size()];
236
237 for (int i = 0; i < _scalars.size(); i++) {
238 values[i] = array[_scalars.get(i)];
239 }
240
241 newList.add(values);
242 }
243 else {
244 newList.add(array[_scalars.get(0)]);
245 }
246 }
247
248 list = newList;
249 }
250 else if ((_scalars.size() == 1)) {
251 List<Object> newList = new ArrayList<Object>();
252
253 for (Object value : list) {
254 value = _transformType(value, _scalarTypes.get(0));
255
256 newList.add(value);
257 }
258
259 list = newList;
260 }
261 }
262 else if (list.get(0) instanceof Collection<?>) {
263 List<Object> newList = new ArrayList<Object>();
264
265 for (Collection<Object> collection :
266 (List<Collection<Object>>)list) {
267
268 if (collection.size() == 1) {
269 newList.add(collection.iterator().next());
270 }
271 else {
272 newList.add(collection.toArray());
273 }
274 }
275
276 list = newList;
277 }
278
279 return list;
280 }
281
282 private Object _transformType(Object object, Type type) {
283 Object result = object;
284
285 if (type.equals(Type.LONG)) {
286 if (object instanceof Integer) {
287 result = new Long((((Integer)object).longValue()));
288 }
289 }
290 else if (type.equals(Type.STRING)) {
291 result = object.toString();
292 }
293 else {
294 throw new UnsupportedOperationException(
295 "Type conversion from " + object.getClass().getName() + " to " +
296 type + " is not supported");
297 }
298
299 return result;
300 }
301
302 private static Map<Class<?>, String[]> _entityColumns =
303 new ConcurrentHashMap<Class<?>, String[]>();
304
305 private List<Integer> _scalars = new ArrayList<Integer>();
306 private List<Type> _scalarTypes = new ArrayList<Type>();
307
308 }