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