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