1
14
15 package com.liferay.portal.dao.orm.jpa;
16
17 import com.liferay.portal.kernel.dao.orm.ORMException;
18 import com.liferay.portal.kernel.dao.orm.SQLQuery;
19 import com.liferay.portal.kernel.dao.orm.Type;
20 import com.liferay.portal.kernel.util.ListUtil;
21 import com.liferay.portal.kernel.util.StringBundler;
22 import com.liferay.portal.kernel.util.StringPool;
23 import com.liferay.portal.kernel.util.UnmodifiableList;
24
25 import java.lang.reflect.Field;
26
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.regex.Pattern;
34
35
41 public class SQLQueryImpl extends QueryImpl implements SQLQuery {
42
43 public SQLQueryImpl(SessionImpl sessionImpl, String queryString) {
44 super(sessionImpl, queryString);
45
46 sqlQuery = true;
47 }
48
49 public SQLQuery addEntity(String alias, Class<?> entityClass) {
50 String columnAliases = null;
51
52 try {
53 String[] columnNames = _getColumns(entityClass);
54
55 if (columnNames.length == 0) {
56 columnAliases = StringPool.BLANK;
57 }
58 else {
59 StringBundler sb = new StringBundler(
60 columnNames.length * 4 - 1);
61
62 int i = 0;
63
64 for (String column : columnNames) {
65 sb.append(alias);
66 sb.append(StringPool.PERIOD);
67 sb.append(column);
68
69 if ((i + 1) < columnNames.length) {
70 sb.append(StringPool.COMMA_AND_SPACE);
71 }
72
73 i++;
74 }
75
76 columnAliases = sb.toString();
77 }
78 }
79 catch (Exception e) {
80 throw new ORMException(e.getMessage());
81 }
82
83 String escapedAlias = Pattern.quote("{" + alias + ".*}");
84
85 queryString = queryString.replaceAll(escapedAlias, columnAliases);
86
87 this.entityClass = entityClass;
88
89 return this;
90 }
91
92 public SQLQuery addScalar(String columnAlias, Type type) {
93 columnAlias = columnAlias.toLowerCase();
94
95 String q = queryString.toLowerCase();
96
97 int fromIndex = q.indexOf("from");
98
99 if (fromIndex == -1) {
100 return this;
101 }
102
103 String selectExpression = q.substring(0, fromIndex);
104
105 String[] selectTokens = selectExpression.split(StringPool.COMMA);
106
107 for (int pos = 0; pos < selectTokens.length; pos++) {
108 String s = selectTokens[pos];
109
110 if (s.indexOf(columnAlias) != -1) {
111 _scalars.add(pos);
112
113 _scalarTypes.add(type);
114 }
115 }
116
117 return this;
118 }
119
120 public List<?> list(boolean unmodifiable) throws ORMException {
121 try {
122 List<?> list = sessionImpl.list(
123 queryString, parameterMap, firstResult, maxResults,
124 flushModeType, sqlQuery, entityClass);
125
126 if ((entityClass == null) && !list.isEmpty()) {
127 list = _transformList(list);
128 }
129
130 if (unmodifiable) {
131 return new UnmodifiableList<Object>(list);
132 }
133 else {
134 return ListUtil.copy(list);
135 }
136 }
137 catch (Exception e) {
138 throw ExceptionTranslator.translate(e);
139 }
140 }
141
142 public Object uniqueResult() throws ORMException {
143 try {
144 Object object = sessionImpl.uniqueResult(
145 queryString, parameterMap, firstResult, maxResults,
146 flushModeType, sqlQuery, entityClass);
147
148 if (object instanceof Collection<?>) {
149 Collection<Object> collection = (Collection<Object>)object;
150
151 if (collection.size() == 1) {
152 object = collection.iterator().next();
153 }
154 }
155
156 if (_scalars.size() == 1) {
157 object = _transformType(object, _scalarTypes.get(0));
158 }
159
160 return object;
161 }
162 catch (Exception e) {
163 throw ExceptionTranslator.translate(e);
164 }
165 }
166
167 private String[] _getColumns(Class<?> entityClass) throws Exception {
168 String[] columns = _entityColumns.get(entityClass);
169
170 if (columns != null) {
171 return columns;
172 }
173
174 Field field = entityClass.getField("TABLE_COLUMNS");
175
176 Object[][] tableColumns = (Object[][])field.get(null);
177
178 columns = new String[tableColumns.length];
179
180 int i = 0;
181
182 for (Object[] row : tableColumns) {
183 String name = (String)row[0];
184
185 columns[i++] = name.toUpperCase();
186 }
187
188 _entityColumns.put(entityClass, columns);
189
190 return columns;
191 }
192
193 private List<?> _transformList(List<?> list) throws Exception {
194 if (!_scalars.isEmpty()) {
195 Collections.sort(_scalars);
196
197 if (list.get(0) instanceof Collection<?>) {
198 List<Object> newList = new ArrayList<Object>();
199
200 for (Collection<Object> collection :
201 (List<Collection<Object>>)list) {
202
203 Object[] array = collection.toArray();
204
205 if (_scalars.size() > 1) {
206 Object[] values = new Object[_scalars.size()];
207
208 for (int i = 0; i < _scalars.size(); i++) {
209 values[i] = array[_scalars.get(i)];
210 }
211
212 newList.add(values);
213 }
214 else {
215 newList.add(array[_scalars.get(0)]);
216 }
217 }
218
219 list = newList;
220 }
221 else if (list.get(0) instanceof Object[]) {
222 List<Object> newList = new ArrayList<Object>();
223
224 for (Object[] array : (List<Object[]>)list) {
225 if (_scalars.size() > 1) {
226 Object[] values = new Object[_scalars.size()];
227
228 for (int i = 0; i < _scalars.size(); i++) {
229 values[i] = array[_scalars.get(i)];
230 }
231
232 newList.add(values);
233 }
234 else {
235 newList.add(array[_scalars.get(0)]);
236 }
237 }
238
239 list = newList;
240 }
241 else if ((_scalars.size() == 1)) {
242 List<Object> newList = new ArrayList<Object>();
243
244 for (Object value : list) {
245 value = _transformType(value, _scalarTypes.get(0));
246
247 newList.add(value);
248 }
249
250 list = newList;
251 }
252 }
253 else if (list.get(0) instanceof Collection<?>) {
254 List<Object> newList = new ArrayList<Object>();
255
256 for (Collection<Object> collection :
257 (List<Collection<Object>>)list) {
258
259 if (collection.size() == 1) {
260 newList.add(collection.iterator().next());
261 }
262 else {
263 newList.add(collection.toArray());
264 }
265 }
266
267 list = newList;
268 }
269
270 return list;
271 }
272
273 private Object _transformType(Object object, Type type) {
274 Object result = object;
275
276 if (type.equals(Type.LONG)) {
277 if (object instanceof Integer) {
278 result = new Long((((Integer)object).longValue()));
279 }
280 }
281 else if (type.equals(Type.STRING)) {
282 result = object.toString();
283 }
284 else {
285 throw new UnsupportedOperationException(
286 "Type conversion from " + object.getClass().getName() + " to " +
287 type + " is not supported");
288 }
289
290 return result;
291 }
292
293 private static Map<Class<?>, String[]> _entityColumns =
294 new ConcurrentHashMap<Class<?>, String[]>();
295
296 private List<Integer> _scalars = new ArrayList<Integer>();
297 private List<Type> _scalarTypes = new ArrayList<Type>();
298
299 }