1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.OrderByComparator;
28  import com.liferay.portal.kernel.util.Randomizer;
29  import com.liferay.portal.kernel.util.UnmodifiableList;
30  
31  import java.util.ArrayList;
32  import java.util.Iterator;
33  import java.util.List;
34  
35  /**
36   * <a href="QueryUtil.java.html"><b><i>View Source</i></b></a>
37   *
38   * @author Brian Wing Shun Chan
39   *
40   */
41  public class QueryUtil {
42  
43      public static final int ALL_POS = -1;
44  
45      public static Iterator<?> iterate(
46          Query query, Dialect dialect, int start, int end) {
47  
48          return iterate(query, dialect, start, end, true);
49      }
50  
51      public static Iterator<?> iterate(
52          Query query, Dialect dialect, int start, int end,
53          boolean unmodifiable) {
54  
55          return list(query, dialect, start, end).iterator();
56      }
57  
58      public static List<?> list(
59          Query query, Dialect dialect, int start, int end) {
60  
61          return list(query, dialect, start, end, true);
62      }
63  
64      public static List<?> list(
65          Query query, Dialect dialect, int start, int end,
66          boolean unmodifiable) {
67  
68          if ((start == ALL_POS) && (end == ALL_POS)) {
69              return query.list(unmodifiable);
70          }
71          else {
72              if (dialect.supportsLimit()) {
73                  query.setMaxResults(end - start);
74                  query.setFirstResult(start);
75  
76                  return query.list(unmodifiable);
77              }
78              else {
79                  List<Object> list = new ArrayList<Object>();
80  
81                  ScrollableResults sr = query.scroll();
82  
83                  if (sr.first() && sr.scroll(start)) {
84                      for (int i = start; i < end; i++) {
85                          Object obj = sr.get(0);
86  
87                          list.add(obj);
88  
89                          if (!sr.next()) {
90                              break;
91                          }
92                      }
93                  }
94  
95                  if (unmodifiable) {
96                      return new UnmodifiableList(list);
97                  }
98                  else {
99                      return list;
100                 }
101             }
102         }
103     }
104 
105     public static List<?> randomList(
106         Query query, Dialect dialect, int total, int num) {
107 
108         return randomList(query, dialect, total, num, true);
109     }
110 
111     public static List<?> randomList(
112         Query query, Dialect dialect, int total, int num,
113         boolean unmodifiable) {
114 
115         if ((total == 0) || (num == 0)) {
116             return new ArrayList<Object>();
117         }
118 
119         if (num >= total) {
120             return list(query, dialect, ALL_POS, ALL_POS, true);
121         }
122 
123         int[] scrollIds = Randomizer.getInstance().nextInt(total, num);
124 
125         List<Object> list = new ArrayList<Object>();
126 
127         ScrollableResults sr = query.scroll();
128 
129         for (int i = 0; i < scrollIds.length; i++) {
130             if (sr.scroll(scrollIds[i])) {
131                 Object obj = sr.get(0);
132 
133                 list.add(obj);
134 
135                 sr.first();
136             }
137         }
138 
139         if (unmodifiable) {
140             return new UnmodifiableList(list);
141         }
142         else {
143             return list;
144         }
145     }
146 
147     public static Comparable<?>[] getPrevAndNext(
148         Query query, int count, OrderByComparator obc,
149         Comparable<?> comparable) {
150 
151         int pos = count;
152         int boundary = 0;
153 
154         Comparable<?>[] array = new Comparable[3];
155 
156         ScrollableResults sr = query.scroll();
157 
158         if (sr.first()) {
159             while (true) {
160                 Object obj = sr.get(0);
161 
162                 if (obj == null) {
163                     if (_log.isWarnEnabled()) {
164                         _log.warn("Object is null");
165                     }
166 
167                     break;
168                 }
169 
170                 Comparable<?> curComparable = (Comparable<?>)obj;
171 
172                 int value = obc.compare(comparable, curComparable);
173 
174                 if (_log.isDebugEnabled()) {
175                     _log.debug("Comparison result is " + value);
176                 }
177 
178                 if (value == 0) {
179                     if (!comparable.equals(curComparable)) {
180                         break;
181                     }
182 
183                     array[1] = curComparable;
184 
185                     if (sr.previous()) {
186                         array[0] = (Comparable<?>)sr.get(0);
187                     }
188 
189                     sr.next();
190 
191                     if (sr.next()) {
192                         array[2] = (Comparable<?>)sr.get(0);
193                     }
194 
195                     break;
196                 }
197 
198                 if (pos == 1) {
199                     break;
200                 }
201 
202                 pos = (int)Math.ceil(pos / 2.0);
203 
204                 int scrollPos = pos;
205 
206                 if (value < 0) {
207                     scrollPos = scrollPos * -1;
208                 }
209 
210                 boundary += scrollPos;
211 
212                 if (boundary < 0) {
213                     scrollPos = scrollPos + (boundary * -1) + 1;
214 
215                     boundary = 0;
216                 }
217 
218                 if (boundary > count) {
219                     scrollPos = scrollPos - (boundary - count);
220 
221                     boundary = scrollPos;
222                 }
223 
224                 if (_log.isDebugEnabled()) {
225                     _log.debug("Scroll " + scrollPos);
226                 }
227 
228                 if (!sr.scroll(scrollPos)) {
229                     if (value < 0) {
230                         if (!sr.next()) {
231                             break;
232                         }
233                     }
234                     else {
235                         if (!sr.previous()) {
236                             break;
237                         }
238                     }
239                 }
240             }
241         }
242 
243         return array;
244     }
245 
246     private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
247 
248 }