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