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