001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.util.OrderByComparator;
022    import com.liferay.portal.kernel.util.Randomizer;
023    import com.liferay.portal.kernel.util.UnmodifiableList;
024    
025    import java.util.ArrayList;
026    import java.util.Iterator;
027    import java.util.List;
028    
029    /**
030     * @author Brian Wing Shun Chan
031     */
032    public class QueryUtil {
033    
034            public static final int ALL_POS = -1;
035    
036            public static Iterator<?> iterate(
037                    Query query, Dialect dialect, int start, int end) {
038    
039                    return iterate(query, dialect, start, end, true);
040            }
041    
042            public static Iterator<?> iterate(
043                    Query query, Dialect dialect, int start, int end,
044                    boolean unmodifiable) {
045    
046                    return list(query, dialect, start, end).iterator();
047            }
048    
049            public static List<?> list(
050                    Query query, Dialect dialect, int start, int end) {
051    
052                    return list(query, dialect, start, end, true);
053            }
054    
055            public static List<?> list(
056                    Query query, Dialect dialect, int start, int end,
057                    boolean unmodifiable) {
058    
059                    if ((start == ALL_POS) && (end == ALL_POS)) {
060                            return query.list(unmodifiable);
061                    }
062                    else {
063                            if (dialect.supportsLimit()) {
064                                    query.setMaxResults(end - start);
065                                    query.setFirstResult(start);
066    
067                                    return query.list(unmodifiable);
068                            }
069                            else {
070                                    List<Object> list = new ArrayList<Object>();
071    
072                                    DB db = DBFactoryUtil.getDB();
073    
074                                    if (!db.isSupportsScrollableResults()) {
075                                            if (_log.isWarnEnabled()) {
076                                                    _log.warn(
077                                                            "Database does not support scrollable results");
078                                            }
079    
080                                            return list;
081                                    }
082    
083                                    ScrollableResults sr = query.scroll();
084    
085                                    if (sr.first() && sr.scroll(start)) {
086                                            for (int i = start; i < end; i++) {
087                                                    Object[] array = sr.get();
088    
089                                                    if (array.length == 1) {
090                                                            list.add(array[0]);
091                                                    }
092                                                    else {
093                                                            list.add(array);
094                                                    }
095    
096                                                    if (!sr.next()) {
097                                                            break;
098                                                    }
099                                            }
100                                    }
101    
102                                    if (unmodifiable) {
103                                            return new UnmodifiableList<Object>(list);
104                                    }
105                                    else {
106                                            return list;
107                                    }
108                            }
109                    }
110            }
111    
112            public static List<?> randomList(
113                    Query query, Dialect dialect, int total, int num) {
114    
115                    return randomList(query, dialect, total, num, true);
116            }
117    
118            public static List<?> randomList(
119                    Query query, Dialect dialect, int total, int num,
120                    boolean unmodifiable) {
121    
122                    if ((total == 0) || (num == 0)) {
123                            return new ArrayList<Object>();
124                    }
125    
126                    if (num >= total) {
127                            return list(query, dialect, ALL_POS, ALL_POS, true);
128                    }
129    
130                    int[] scrollIds = Randomizer.getInstance().nextInt(total, num);
131    
132                    List<Object> list = new ArrayList<Object>();
133    
134                    DB db = DBFactoryUtil.getDB();
135    
136                    if (!db.isSupportsScrollableResults()) {
137                            if (_log.isWarnEnabled()) {
138                                    _log.warn("Database does not support scrollable results");
139                            }
140    
141                            return list;
142                    }
143    
144                    ScrollableResults sr = query.scroll();
145    
146                    for (int i = 0; i < scrollIds.length; i++) {
147                            if (sr.scroll(scrollIds[i])) {
148                                    Object[] array = sr.get();
149    
150                                    if (array.length == 1) {
151                                            list.add(array[0]);
152                                    }
153                                    else {
154                                            list.add(array);
155                                    }
156    
157                                    sr.first();
158                            }
159                    }
160    
161                    if (unmodifiable) {
162                            return new UnmodifiableList<Object>(list);
163                    }
164                    else {
165                            return list;
166                    }
167            }
168    
169            public static Comparable<?>[] getPrevAndNext(
170                    Query query, int count, OrderByComparator obc,
171                    Comparable<?> comparable) {
172    
173                    int pos = count;
174                    int boundary = 0;
175    
176                    Comparable<?>[] array = new Comparable[3];
177    
178                    DB db = DBFactoryUtil.getDB();
179    
180                    if (!db.isSupportsScrollableResults()) {
181                            if (_log.isWarnEnabled()) {
182                                    _log.warn("Database does not support scrollable results");
183                            }
184    
185                            return array;
186                    }
187    
188                    ScrollableResults sr = query.scroll();
189    
190                    if (sr.first()) {
191                            while (true) {
192                                    Object obj = sr.get(0);
193    
194                                    if (obj == null) {
195                                            if (_log.isWarnEnabled()) {
196                                                    _log.warn("Object is null");
197                                            }
198    
199                                            break;
200                                    }
201    
202                                    Comparable<?> curComparable = (Comparable<?>)obj;
203    
204                                    int value = obc.compare(comparable, curComparable);
205    
206                                    if (_log.isDebugEnabled()) {
207                                            _log.debug("Comparison result is " + value);
208                                    }
209    
210                                    if (value == 0) {
211                                            if (!comparable.equals(curComparable)) {
212                                                    break;
213                                            }
214    
215                                            array[1] = curComparable;
216    
217                                            if (sr.previous()) {
218                                                    array[0] = (Comparable<?>)sr.get(0);
219                                            }
220    
221                                            sr.next();
222    
223                                            if (sr.next()) {
224                                                    array[2] = (Comparable<?>)sr.get(0);
225                                            }
226    
227                                            break;
228                                    }
229    
230                                    if (pos == 1) {
231                                            break;
232                                    }
233    
234                                    pos = (int)Math.ceil(pos / 2.0);
235    
236                                    int scrollPos = pos;
237    
238                                    if (value < 0) {
239                                            scrollPos = scrollPos * -1;
240                                    }
241    
242                                    boundary += scrollPos;
243    
244                                    if (boundary < 0) {
245                                            scrollPos = scrollPos + (boundary * -1) + 1;
246    
247                                            boundary = 0;
248                                    }
249    
250                                    if (boundary > count) {
251                                            scrollPos = scrollPos - (boundary - count);
252    
253                                            boundary = scrollPos;
254                                    }
255    
256                                    if (_log.isDebugEnabled()) {
257                                            _log.debug("Scroll " + scrollPos);
258                                    }
259    
260                                    if (!sr.scroll(scrollPos)) {
261                                            if (value < 0) {
262                                                    if (!sr.next()) {
263                                                            break;
264                                                    }
265                                            }
266                                            else {
267                                                    if (!sr.previous()) {
268                                                            break;
269                                                    }
270                                            }
271                                    }
272                            }
273                    }
274    
275                    return array;
276            }
277    
278            private static Log _log = LogFactoryUtil.getLog(QueryUtil.class);
279    
280    }