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.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  public class QueryUtil {
41  
42      public static final int ALL_POS = -1;
43  
44      public static Iterator<?> iterate(
45          Query query, Dialect dialect, int start, int end) {
46  
47          return iterate(query, dialect, start, end, true);
48      }
49  
50      public static Iterator<?> iterate(
51          Query query, Dialect dialect, int start, int end,
52          boolean unmodifiable) {
53  
54          return list(query, dialect, start, end).iterator();
55      }
56  
57      public static List<?> list(
58          Query query, Dialect dialect, int start, int end) {
59  
60          return list(query, dialect, start, end, true);
61      }
62  
63      public static List<?> list(
64          Query query, Dialect dialect, int start, int end,
65          boolean unmodifiable) {
66  
67          if ((start == ALL_POS) && (end == ALL_POS)) {
68              return query.list(unmodifiable);
69          }
70          else {
71              if (dialect.supportsLimit()) {
72                  query.setMaxResults(end - start);
73                  query.setFirstResult(start);
74  
75                  return query.list(unmodifiable);
76              }
77              else {
78                  List<Object> list = new ArrayList<Object>();
79  
80                  ScrollableResults sr = query.scroll();
81  
82                  if (sr.first() && sr.scroll(start)) {
83                      for (int i = start; i < end; i++) {
84                          Object obj = sr.get(0);
85  
86                          list.add(obj);
87  
88                          if (!sr.next()) {
89                              break;
90                          }
91                      }
92                  }
93  
94                  if (unmodifiable) {
95                      return new UnmodifiableList<Object>(list);
96                  }
97                  else {
98                      return list;
99                  }
100             }
101         }
102     }
103 
104     public static List<?> randomList(
105         Query query, Dialect dialect, int total, int num) {
106 
107         return randomList(query, dialect, total, num, true);
108     }
109 
110     public static List<?> randomList(
111         Query query, Dialect dialect, int total, int num,
112         boolean unmodifiable) {
113 
114         if ((total == 0) || (num == 0)) {
115             return new ArrayList<Object>();
116         }
117 
118         if (num >= total) {
119             return list(query, dialect, ALL_POS, ALL_POS, true);
120         }
121 
122         int[] scrollIds = Randomizer.getInstance().nextInt(total, num);
123 
124         List<Object> list = new ArrayList<Object>();
125 
126         ScrollableResults sr = query.scroll();
127 
128         for (int i = 0; i < scrollIds.length; i++) {
129             if (sr.scroll(scrollIds[i])) {
130                 Object obj = sr.get(0);
131 
132                 list.add(obj);
133 
134                 sr.first();
135             }
136         }
137 
138         if (unmodifiable) {
139             return new UnmodifiableList<Object>(list);
140         }
141         else {
142             return list;
143         }
144     }
145 
146     public static Comparable<?>[] getPrevAndNext(
147         Query query, int count, OrderByComparator obc,
148         Comparable<?> comparable) {
149 
150         int pos = count;
151         int boundary = 0;
152 
153         Comparable<?>[] array = new Comparable[3];
154 
155         ScrollableResults sr = query.scroll();
156 
157         if (sr.first()) {
158             while (true) {
159                 Object obj = sr.get(0);
160 
161                 if (obj == null) {
162                     if (_log.isWarnEnabled()) {
163                         _log.warn("Object is null");
164                     }
165 
166                     break;
167                 }
168 
169                 Comparable<?> curComparable = (Comparable<?>)obj;
170 
171                 int value = obc.compare(comparable, curComparable);
172 
173                 if (_log.isDebugEnabled()) {
174                     _log.debug("Comparison result is " + value);
175                 }
176 
177                 if (value == 0) {
178                     if (!comparable.equals(curComparable)) {
179                         break;
180                     }
181 
182                     array[1] = curComparable;
183 
184                     if (sr.previous()) {
185                         array[0] = (Comparable<?>)sr.get(0);
186                     }
187 
188                     sr.next();
189 
190                     if (sr.next()) {
191                         array[2] = (Comparable<?>)sr.get(0);
192                     }
193 
194                     break;
195                 }
196 
197                 if (pos == 1) {
198                     break;
199                 }
200 
201                 pos = (int)Math.ceil(pos / 2.0);
202 
203                 int scrollPos = pos;
204 
205                 if (value < 0) {
206                     scrollPos = scrollPos * -1;
207                 }
208 
209                 boundary += scrollPos;
210 
211                 if (boundary < 0) {
212                     scrollPos = scrollPos + (boundary * -1) + 1;
213 
214                     boundary = 0;
215                 }
216 
217                 if (boundary > count) {
218                     scrollPos = scrollPos - (boundary - count);
219 
220                     boundary = scrollPos;
221                 }
222 
223                 if (_log.isDebugEnabled()) {
224                     _log.debug("Scroll " + scrollPos);
225                 }
226 
227                 if (!sr.scroll(scrollPos)) {
228                     if (value < 0) {
229                         if (!sr.next()) {
230                             break;
231                         }
232                     }
233                     else {
234                         if (!sr.previous()) {
235                             break;
236                         }
237                     }
238                 }
239             }
240         }
241 
242         return array;
243     }
244 
245     private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
246 
247 }