001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.dao.orm;
016    
017    import com.liferay.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.security.RandomUtil;
022    import com.liferay.portal.kernel.util.OrderByComparator;
023    import com.liferay.portal.kernel.util.UnmodifiableList;
024    
025    import java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    /**
031     * @author Brian Wing Shun Chan
032     */
033    public class QueryUtil {
034    
035            public static final int ALL_POS = -1;
036    
037            public static Comparable<?>[] getPrevAndNext(
038                    Query query, int count, OrderByComparator obc,
039                    Comparable<?> comparable) {
040    
041                    int pos = count;
042                    int boundary = 0;
043    
044                    Comparable<?>[] array = new Comparable[3];
045    
046                    DB db = DBFactoryUtil.getDB();
047    
048                    if (!db.isSupportsScrollableResults()) {
049                            if (_log.isWarnEnabled()) {
050                                    _log.warn("Database does not support scrollable results");
051                            }
052    
053                            return array;
054                    }
055    
056                    ScrollableResults sr = query.scroll();
057    
058                    if (sr.first()) {
059                            while (true) {
060                                    Object obj = sr.get(0);
061    
062                                    if (obj == null) {
063                                            if (_log.isWarnEnabled()) {
064                                                    _log.warn("Object is null");
065                                            }
066    
067                                            break;
068                                    }
069    
070                                    Comparable<?> curComparable = (Comparable<?>)obj;
071    
072                                    int value = obc.compare(comparable, curComparable);
073    
074                                    if (_log.isDebugEnabled()) {
075                                            _log.debug("Comparison result is " + value);
076                                    }
077    
078                                    if (value == 0) {
079                                            if (!comparable.equals(curComparable)) {
080                                                    break;
081                                            }
082    
083                                            array[1] = curComparable;
084    
085                                            if (sr.previous()) {
086                                                    array[0] = (Comparable<?>)sr.get(0);
087                                            }
088    
089                                            sr.next();
090    
091                                            if (sr.next()) {
092                                                    array[2] = (Comparable<?>)sr.get(0);
093                                            }
094    
095                                            break;
096                                    }
097    
098                                    if (pos == 1) {
099                                            break;
100                                    }
101    
102                                    pos = (int)Math.ceil(pos / 2.0);
103    
104                                    int scrollPos = pos;
105    
106                                    if (value < 0) {
107                                            scrollPos = scrollPos * -1;
108                                    }
109    
110                                    boundary += scrollPos;
111    
112                                    if (boundary < 0) {
113                                            scrollPos = scrollPos + (boundary * -1) + 1;
114    
115                                            boundary = 0;
116                                    }
117    
118                                    if (boundary > count) {
119                                            scrollPos = scrollPos - (boundary - count);
120    
121                                            boundary = scrollPos;
122                                    }
123    
124                                    if (_log.isDebugEnabled()) {
125                                            _log.debug("Scroll " + scrollPos);
126                                    }
127    
128                                    if (!sr.scroll(scrollPos)) {
129                                            if (value < 0) {
130                                                    if (!sr.next()) {
131                                                            break;
132                                                    }
133                                            }
134                                            else {
135                                                    if (!sr.previous()) {
136                                                            break;
137                                                    }
138                                            }
139                                    }
140                            }
141                    }
142    
143                    return array;
144            }
145    
146            public static Iterator<?> iterate(
147                    Query query, Dialect dialect, int start, int end) {
148    
149                    return iterate(query, dialect, start, end, true);
150            }
151    
152            public static Iterator<?> iterate(
153                    Query query, Dialect dialect, int start, int end,
154                    boolean unmodifiable) {
155    
156                    return list(query, dialect, start, end).iterator();
157            }
158    
159            public static List<?> list(
160                    Query query, Dialect dialect, int start, int end) {
161    
162                    return list(query, dialect, start, end, true);
163            }
164    
165            public static List<?> list(
166                    Query query, Dialect dialect, int start, int end,
167                    boolean unmodifiable) {
168    
169                    if ((start == ALL_POS) && (end == ALL_POS)) {
170                            return query.list(unmodifiable);
171                    }
172    
173                    if (start < 0) {
174                            start = 0;
175                    }
176    
177                    if (end < start) {
178                            end = start;
179                    }
180    
181                    if (start == end) {
182                            if (unmodifiable) {
183                                    return Collections.emptyList();
184                            }
185                            else {
186                                    return new ArrayList<Object>();
187                            }
188                    }
189    
190                    if (dialect.supportsLimit()) {
191                            query.setMaxResults(end - start);
192                            query.setFirstResult(start);
193    
194                            return query.list(unmodifiable);
195                    }
196    
197                    List<Object> list = new ArrayList<Object>();
198    
199                    DB db = DBFactoryUtil.getDB();
200    
201                    if (!db.isSupportsScrollableResults()) {
202                            if (_log.isWarnEnabled()) {
203                                    _log.warn("Database does not support scrollable results");
204                            }
205    
206                            return list;
207                    }
208    
209                    ScrollableResults sr = query.scroll();
210    
211                    if (sr.first() && sr.scroll(start)) {
212                            for (int i = start; i < end; i++) {
213                                    Object[] array = sr.get();
214    
215                                    if (array.length == 1) {
216                                            list.add(array[0]);
217                                    }
218                                    else {
219                                            list.add(array);
220                                    }
221    
222                                    if (!sr.next()) {
223                                            break;
224                                    }
225                            }
226                    }
227    
228                    if (unmodifiable) {
229                            return new UnmodifiableList<Object>(list);
230                    }
231                    else {
232                            return list;
233                    }
234            }
235    
236            public static List<?> randomList(
237                    Query query, Dialect dialect, int total, int num) {
238    
239                    return randomList(query, dialect, total, num, true);
240            }
241    
242            public static List<?> randomList(
243                    Query query, Dialect dialect, int total, int num,
244                    boolean unmodifiable) {
245    
246                    if ((total == 0) || (num == 0)) {
247                            return new ArrayList<Object>();
248                    }
249    
250                    if (num >= total) {
251                            return list(query, dialect, ALL_POS, ALL_POS, true);
252                    }
253    
254                    int[] scrollIds = RandomUtil.nextInts(total, num);
255    
256                    List<Object> list = new ArrayList<Object>();
257    
258                    DB db = DBFactoryUtil.getDB();
259    
260                    if (!db.isSupportsScrollableResults()) {
261                            if (_log.isWarnEnabled()) {
262                                    _log.warn("Database does not support scrollable results");
263                            }
264    
265                            return list;
266                    }
267    
268                    ScrollableResults sr = query.scroll();
269    
270                    for (int i = 0; i < scrollIds.length; i++) {
271                            if (sr.scroll(scrollIds[i])) {
272                                    Object[] array = sr.get();
273    
274                                    if (array.length == 1) {
275                                            list.add(array[0]);
276                                    }
277                                    else {
278                                            list.add(array);
279                                    }
280    
281                                    sr.first();
282                            }
283                    }
284    
285                    if (unmodifiable) {
286                            return new UnmodifiableList<Object>(list);
287                    }
288                    else {
289                            return list;
290                    }
291            }
292    
293            private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
294    
295    }