1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.kernel.dao.orm;
16  
17  import com.liferay.portal.kernel.dao.db.DB;
18  import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.OrderByComparator;
22  import com.liferay.portal.kernel.util.Randomizer;
23  import com.liferay.portal.kernel.util.UnmodifiableList;
24  
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  /**
30   * <a href="QueryUtil.java.html"><b><i>View Source</i></b></a>
31   *
32   * @author Brian Wing Shun Chan
33   */
34  public class QueryUtil {
35  
36      public static final int ALL_POS = -1;
37  
38      public static Iterator<?> iterate(
39          Query query, Dialect dialect, int start, int end) {
40  
41          return iterate(query, dialect, start, end, true);
42      }
43  
44      public static Iterator<?> iterate(
45          Query query, Dialect dialect, int start, int end,
46          boolean unmodifiable) {
47  
48          return list(query, dialect, start, end).iterator();
49      }
50  
51      public static List<?> list(
52          Query query, Dialect dialect, int start, int end) {
53  
54          return list(query, dialect, start, end, true);
55      }
56  
57      public static List<?> list(
58          Query query, Dialect dialect, int start, int end,
59          boolean unmodifiable) {
60  
61          if ((start == ALL_POS) && (end == ALL_POS)) {
62              return query.list(unmodifiable);
63          }
64          else {
65              if (dialect.supportsLimit()) {
66                  query.setMaxResults(end - start);
67                  query.setFirstResult(start);
68  
69                  return query.list(unmodifiable);
70              }
71              else {
72                  List<Object> list = new ArrayList<Object>();
73  
74                  DB db = DBFactoryUtil.getDB();
75  
76                  if (!db.isSupportsScrollableResults()) {
77                      if (_log.isWarnEnabled()) {
78                          _log.warn(
79                              "Database does not support scrollable results");
80                      }
81  
82                      return list;
83                  }
84  
85                  ScrollableResults sr = query.scroll();
86  
87                  if (sr.first() && sr.scroll(start)) {
88                      for (int i = start; i < end; i++) {
89                          Object[] array = sr.get();
90  
91                          if (array.length == 1) {
92                              list.add(array[0]);
93                          }
94                          else {
95                              list.add(array);
96                          }
97  
98                          if (!sr.next()) {
99                              break;
100                         }
101                     }
102                 }
103 
104                 if (unmodifiable) {
105                     return new UnmodifiableList<Object>(list);
106                 }
107                 else {
108                     return list;
109                 }
110             }
111         }
112     }
113 
114     public static List<?> randomList(
115         Query query, Dialect dialect, int total, int num) {
116 
117         return randomList(query, dialect, total, num, true);
118     }
119 
120     public static List<?> randomList(
121         Query query, Dialect dialect, int total, int num,
122         boolean unmodifiable) {
123 
124         if ((total == 0) || (num == 0)) {
125             return new ArrayList<Object>();
126         }
127 
128         if (num >= total) {
129             return list(query, dialect, ALL_POS, ALL_POS, true);
130         }
131 
132         int[] scrollIds = Randomizer.getInstance().nextInt(total, num);
133 
134         List<Object> list = new ArrayList<Object>();
135 
136         DB db = DBFactoryUtil.getDB();
137 
138         if (!db.isSupportsScrollableResults()) {
139             if (_log.isWarnEnabled()) {
140                 _log.warn("Database does not support scrollable results");
141             }
142 
143             return list;
144         }
145 
146         ScrollableResults sr = query.scroll();
147 
148         for (int i = 0; i < scrollIds.length; i++) {
149             if (sr.scroll(scrollIds[i])) {
150                 Object[] array = sr.get();
151 
152                 if (array.length == 1) {
153                     list.add(array[0]);
154                 }
155                 else {
156                     list.add(array);
157                 }
158 
159                 sr.first();
160             }
161         }
162 
163         if (unmodifiable) {
164             return new UnmodifiableList<Object>(list);
165         }
166         else {
167             return list;
168         }
169     }
170 
171     public static Comparable<?>[] getPrevAndNext(
172         Query query, int count, OrderByComparator obc,
173         Comparable<?> comparable) {
174 
175         int pos = count;
176         int boundary = 0;
177 
178         Comparable<?>[] array = new Comparable[3];
179 
180         DB db = DBFactoryUtil.getDB();
181 
182         if (!db.isSupportsScrollableResults()) {
183             if (_log.isWarnEnabled()) {
184                 _log.warn("Database does not support scrollable results");
185             }
186 
187             return array;
188         }
189 
190         ScrollableResults sr = query.scroll();
191 
192         if (sr.first()) {
193             while (true) {
194                 Object obj = sr.get(0);
195 
196                 if (obj == null) {
197                     if (_log.isWarnEnabled()) {
198                         _log.warn("Object is null");
199                     }
200 
201                     break;
202                 }
203 
204                 Comparable<?> curComparable = (Comparable<?>)obj;
205 
206                 int value = obc.compare(comparable, curComparable);
207 
208                 if (_log.isDebugEnabled()) {
209                     _log.debug("Comparison result is " + value);
210                 }
211 
212                 if (value == 0) {
213                     if (!comparable.equals(curComparable)) {
214                         break;
215                     }
216 
217                     array[1] = curComparable;
218 
219                     if (sr.previous()) {
220                         array[0] = (Comparable<?>)sr.get(0);
221                     }
222 
223                     sr.next();
224 
225                     if (sr.next()) {
226                         array[2] = (Comparable<?>)sr.get(0);
227                     }
228 
229                     break;
230                 }
231 
232                 if (pos == 1) {
233                     break;
234                 }
235 
236                 pos = (int)Math.ceil(pos / 2.0);
237 
238                 int scrollPos = pos;
239 
240                 if (value < 0) {
241                     scrollPos = scrollPos * -1;
242                 }
243 
244                 boundary += scrollPos;
245 
246                 if (boundary < 0) {
247                     scrollPos = scrollPos + (boundary * -1) + 1;
248 
249                     boundary = 0;
250                 }
251 
252                 if (boundary > count) {
253                     scrollPos = scrollPos - (boundary - count);
254 
255                     boundary = scrollPos;
256                 }
257 
258                 if (_log.isDebugEnabled()) {
259                     _log.debug("Scroll " + scrollPos);
260                 }
261 
262                 if (!sr.scroll(scrollPos)) {
263                     if (value < 0) {
264                         if (!sr.next()) {
265                             break;
266                         }
267                     }
268                     else {
269                         if (!sr.previous()) {
270                             break;
271                         }
272                     }
273                 }
274             }
275         }
276 
277         return array;
278     }
279 
280     private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
281 
282 }