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