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 List<?> list(boolean copy, boolean unmodifiable)
126 throws ORMException {
127
128 try {
129 List<?> list = sessionImpl.list(
130 queryString, positionalParameterMap, namedParameterMap,
131 strictName, firstResult, maxResults, flushModeType,
132 lockModeType, sqlQuery, entityClass);
133
134 if ((entityClass == null) && !list.isEmpty()) {
135 list = _transformList(list);
136 }
137
138 if (unmodifiable) {
139 list = new UnmodifiableList<Object>(list);
140 }
141 else if (copy) {
142 list = ListUtil.copy(list);
143 }
144
145 return list;
146 }
147 catch (Exception e) {
148 throw ExceptionTranslator.translate(e);
149 }
150 }
151
152 @Override
153 public Object uniqueResult() throws ORMException {
154 try {
155 Object object = sessionImpl.uniqueResult(
156 queryString, positionalParameterMap, namedParameterMap,
157 strictName, firstResult, maxResults, flushModeType,
158 lockModeType, sqlQuery, entityClass);
159
160 if (object instanceof Collection<?>) {
161 Collection<Object> collection = (Collection<Object>)object;
162
163 if (collection.size() == 1) {
164 object = collection.iterator().next();
165 }
166 }
167
168 if (_scalars.size() == 1) {
169 object = _transformType(object, _scalarTypes.get(0));
170 }
171
172 return object;
173 }
174 catch (Exception e) {
175 throw ExceptionTranslator.translate(e);
176 }
177 }
178
179 private String[] _getColumns(Class<?> entityClass) throws Exception {
180 String[] columns = _entityColumns.get(entityClass);
181
182 if (columns != null) {
183 return columns;
184 }
185
186 Field field = entityClass.getField("TABLE_COLUMNS");
187
188 Object[][] tableColumns = (Object[][])field.get(null);
189
190 columns = new String[tableColumns.length];
191
192 int i = 0;
193
194 for (Object[] row : tableColumns) {
195 String name = (String)row[0];
196
197 columns[i++] = StringUtil.toUpperCase(name);
198 }
199
200 _entityColumns.put(entityClass, columns);
201
202 return columns;
203 }
204
205 private List<?> _transformList(List<?> list) throws Exception {
206 if (!_scalars.isEmpty()) {
207 Collections.sort(_scalars);
208
209 if (list.get(0) instanceof Collection<?>) {
210 List<Object> newList = new ArrayList<Object>();
211
212 for (Collection<Object> collection :
213 (List<Collection<Object>>)list) {
214
215 Object[] array = collection.toArray();
216
217 if (_scalars.size() > 1) {
218 Object[] values = new Object[_scalars.size()];
219
220 for (int i = 0; i < _scalars.size(); i++) {
221 values[i] = array[_scalars.get(i)];
222 }
223
224 newList.add(values);
225 }
226 else {
227 newList.add(array[_scalars.get(0)]);
228 }
229 }
230
231 list = newList;
232 }
233 else if (list.get(0) instanceof Object[]) {
234 List<Object> newList = new ArrayList<Object>();
235
236 for (Object[] array : (List<Object[]>)list) {
237 if (_scalars.size() > 1) {
238 Object[] values = new Object[_scalars.size()];
239
240 for (int i = 0; i < _scalars.size(); i++) {
241 values[i] = array[_scalars.get(i)];
242 }
243
244 newList.add(values);
245 }
246 else {
247 newList.add(array[_scalars.get(0)]);
248 }
249 }
250
251 list = newList;
252 }
253 else if (_scalars.size() == 1) {
254 List<Object> newList = new ArrayList<Object>();
255
256 for (Object value : list) {
257 value = _transformType(value, _scalarTypes.get(0));
258
259 newList.add(value);
260 }
261
262 list = newList;
263 }
264 }
265 else if (list.get(0) instanceof Collection<?>) {
266 List<Object> newList = new ArrayList<Object>();
267
268 for (Collection<Object> collection :
269 (List<Collection<Object>>)list) {
270
271 if (collection.size() == 1) {
272 newList.add(collection.iterator().next());
273 }
274 else {
275 newList.add(collection.toArray());
276 }
277 }
278
279 list = newList;
280 }
281
282 return list;
283 }
284
285 private Object _transformType(Object object, Type type) {
286 Object result = object;
287
288 if (type.equals(Type.LONG)) {
289 if (object instanceof Integer) {
290 result = new Long((((Integer)object).longValue()));
291 }
292 }
293 else if (type.equals(Type.STRING)) {
294 result = object.toString();
295 }
296 else {
297 throw new UnsupportedOperationException(
298 "Type conversion from " + object.getClass().getName() + " to " +
299 type + " is not supported");
300 }
301
302 return result;
303 }
304
305 private static Map<Class<?>, String[]> _entityColumns =
306 new ConcurrentHashMap<Class<?>, String[]>();
307
308 private List<Integer> _scalars = new ArrayList<Integer>();
309 private List<Type> _scalarTypes = new ArrayList<Type>();
310
311 }