1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.kernel.dao.orm;
21  
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.util.OrderByComparator;
25  import com.liferay.portal.kernel.util.Randomizer;
26  import com.liferay.portal.kernel.util.UnmodifiableList;
27  
28  import java.util.ArrayList;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  /**
33   * <a href="QueryUtil.java.html"><b><i>View Source</i></b></a>
34   *
35   * @author Brian Wing Shun Chan
36   *
37   */
38  public class QueryUtil {
39  
40      public static final int ALL_POS = -1;
41  
42      public static Iterator<?> iterate(
43          Query query, Dialect dialect, int start, int end) {
44  
45          return iterate(query, dialect, start, end, true);
46      }
47  
48      public static Iterator<?> iterate(
49          Query query, Dialect dialect, int start, int end,
50          boolean unmodifiable) {
51  
52          return list(query, dialect, start, end).iterator();
53      }
54  
55      public static List<?> list(
56          Query query, Dialect dialect, int start, int end) {
57  
58          return list(query, dialect, start, end, true);
59      }
60  
61      public static List<?> list(
62          Query query, Dialect dialect, int start, int end,
63          boolean unmodifiable) {
64  
65          if ((start == ALL_POS) && (end == ALL_POS)) {
66              return query.list(unmodifiable);
67          }
68          else {
69              if (dialect.supportsLimit()) {
70                  query.setMaxResults(end - start);
71                  query.setFirstResult(start);
72  
73                  return query.list(unmodifiable);
74              }
75              else {
76                  List<Object> list = new ArrayList<Object>();
77  
78                  ScrollableResults sr = query.scroll();
79  
80                  if (sr.first() && sr.scroll(start)) {
81                      for (int i = start; i < end; i++) {
82                          Object obj = sr.get(0);
83  
84                          list.add(obj);
85  
86                          if (!sr.next()) {
87                              break;
88                          }
89                      }
90                  }
91  
92                  if (unmodifiable) {
93                      return new UnmodifiableList(list);
94                  }
95                  else {
96                      return list;
97                  }
98              }
99          }
100     }
101 
102     public static List<?> randomList(
103         Query query, Dialect dialect, int total, int num) {
104 
105         return randomList(query, dialect, total, num, true);
106     }
107 
108     public static List<?> randomList(
109         Query query, Dialect dialect, int total, int num,
110         boolean unmodifiable) {
111 
112         if ((total == 0) || (num == 0)) {
113             return new ArrayList<Object>();
114         }
115 
116         if (num >= total) {
117             return list(query, dialect, ALL_POS, ALL_POS, true);
118         }
119 
120         int[] scrollIds = Randomizer.getInstance().nextInt(total, num);
121 
122         List<Object> list = new ArrayList<Object>();
123 
124         ScrollableResults sr = query.scroll();
125 
126         for (int i = 0; i < scrollIds.length; i++) {
127             if (sr.scroll(scrollIds[i])) {
128                 Object obj = sr.get(0);
129 
130                 list.add(obj);
131 
132                 sr.first();
133             }
134         }
135 
136         if (unmodifiable) {
137             return new UnmodifiableList(list);
138         }
139         else {
140             return list;
141         }
142     }
143 
144     public static Comparable<?>[] getPrevAndNext(
145         Query query, int count, OrderByComparator obc,
146         Comparable<?> comparable) {
147 
148         int pos = count;
149         int boundary = 0;
150 
151         Comparable<?>[] array = new Comparable[3];
152 
153         ScrollableResults sr = query.scroll();
154 
155         if (sr.first()) {
156             while (true) {
157                 Object obj = sr.get(0);
158 
159                 if (obj == null) {
160                     if (_log.isWarnEnabled()) {
161                         _log.warn("Object is null");
162                     }
163 
164                     break;
165                 }
166 
167                 Comparable<?> curComparable = (Comparable<?>)obj;
168 
169                 int value = obc.compare(comparable, curComparable);
170 
171                 if (_log.isDebugEnabled()) {
172                     _log.debug("Comparison result is " + value);
173                 }
174 
175                 if (value == 0) {
176                     if (!comparable.equals(curComparable)) {
177                         break;
178                     }
179 
180                     array[1] = curComparable;
181 
182                     if (sr.previous()) {
183                         array[0] = (Comparable<?>)sr.get(0);
184                     }
185 
186                     sr.next();
187 
188                     if (sr.next()) {
189                         array[2] = (Comparable<?>)sr.get(0);
190                     }
191 
192                     break;
193                 }
194 
195                 if (pos == 1) {
196                     break;
197                 }
198 
199                 pos = (int)Math.ceil(pos / 2.0);
200 
201                 int scrollPos = pos;
202 
203                 if (value < 0) {
204                     scrollPos = scrollPos * -1;
205                 }
206 
207                 boundary += scrollPos;
208 
209                 if (boundary < 0) {
210                     scrollPos = scrollPos + (boundary * -1) + 1;
211 
212                     boundary = 0;
213                 }
214 
215                 if (boundary > count) {
216                     scrollPos = scrollPos - (boundary - count);
217 
218                     boundary = scrollPos;
219                 }
220 
221                 if (_log.isDebugEnabled()) {
222                     _log.debug("Scroll " + scrollPos);
223                 }
224 
225                 if (!sr.scroll(scrollPos)) {
226                     if (value < 0) {
227                         if (!sr.next()) {
228                             break;
229                         }
230                     }
231                     else {
232                         if (!sr.previous()) {
233                             break;
234                         }
235                     }
236                 }
237             }
238         }
239 
240         return array;
241     }
242 
243     private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
244 
245 }