001: /*
002: * Copyright 2004-2007 Gary Bentley
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may
005: * not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015: package org.josql.internal;
016:
017: import java.util.List;
018: import java.util.ArrayList;
019: import java.util.Comparator;
020: import java.util.Map;
021: import java.util.HashMap;
022:
023: import org.josql.expressions.Expression;
024:
025: import org.josql.Query;
026: import org.josql.QueryResults;
027:
028: public class GroupByExpressionComparator implements Comparator {
029:
030: private List items = new ArrayList();
031: private Query q = null;
032: private int size = 0;
033: private int count = 0;
034: private Exception exp = null;
035: private Object nullObj = new Object();
036:
037: private Map cache = new HashMap();
038: private boolean caching = false;
039:
040: public GroupByExpressionComparator(Query q, boolean caching) {
041:
042: this .q = q;
043: this .caching = caching;
044:
045: }
046:
047: public int getCount() {
048:
049: return this .count;
050:
051: }
052:
053: public boolean equals(Object o) {
054:
055: throw new UnsupportedOperationException(
056: "Not supported for instances of: "
057: + this .getClass().getName());
058:
059: }
060:
061: public boolean isCaching() {
062:
063: return this .caching;
064:
065: }
066:
067: public void setCaching(boolean b) {
068:
069: this .caching = b;
070:
071: }
072:
073: public void clearCache() {
074:
075: this .cache.clear();
076:
077: }
078:
079: public int ci(Object o1, Object o2) throws Exception {
080:
081: List lo1 = (List) o1;
082: List lo2 = (List) o2;
083:
084: QueryResults qr = this .q.getQueryResults();
085:
086: for (int i = 0; i < this .size; i++) {
087:
088: Item it = (Item) this .items.get(i);
089:
090: // The "current object" here will be a list, it is also the "key"
091: // to the group by results.
092: this .q
093: .setAllObjects((List) qr.getGroupByResults().get(
094: lo1));
095:
096: this .q.setCurrentGroupByObjects(this .q.getAllObjects());
097:
098: // Also, setup the save values.
099: this .q.setSaveValues((Map) qr.getGroupBySaveValues(lo1));
100:
101: this .q.setCurrentObject(o1);
102:
103: Object eo1 = null;
104:
105: if (it.exp != null) {
106:
107: eo1 = it.exp.getValue(o1, this .q);
108:
109: } else {
110:
111: eo1 = lo1.get(it.ind);
112:
113: }
114:
115: this .q
116: .setAllObjects((List) qr.getGroupByResults().get(
117: lo2));
118:
119: // Also, setup the save values.
120: this .q.setSaveValues((Map) qr.getGroupBySaveValues(lo2));
121:
122: this .q.setCurrentObject(o2);
123:
124: Object eo2 = null;
125:
126: if (it.exp != null) {
127:
128: eo2 = it.exp.getValue(o2, this .q);
129:
130: } else {
131:
132: eo2 = lo2.get(it.ind);
133:
134: }
135:
136: // Compare them...
137: int c = Utilities.compare(eo1, eo2);
138:
139: if (c == 0) {
140:
141: // Go to the next...
142: continue;
143:
144: }
145:
146: // For speed reasons, 1 is used here rather than the constant.
147: if (it.dir == 1) {
148:
149: c = -1 * c;
150:
151: }
152:
153: return c;
154:
155: }
156:
157: return 0;
158:
159: }
160:
161: public int cic(Object o1, Object o2) throws Exception {
162:
163: this .count++;
164:
165: Map co = null;
166: boolean get = true;
167: Item it = null;
168: Object eo1 = null;
169: Object eo2 = null;
170:
171: QueryResults qr = this .q.getQueryResults();
172: List lo1 = (List) o1;
173: List lo2 = (List) o2;
174:
175: for (int i = 0; i < this .size; i++) {
176:
177: it = (Item) this .items.get(i);
178:
179: eo1 = null;
180:
181: get = true;
182:
183: co = (Map) cache.get(o1);
184:
185: if (co == null) {
186:
187: co = new HashMap(this .size);
188:
189: cache.put(o1, co);
190:
191: get = false;
192:
193: }
194:
195: if (get) {
196:
197: eo1 = co.get(it);
198:
199: if (eo1 == this .nullObj) {
200:
201: eo1 = null;
202:
203: }
204:
205: }
206:
207: if (eo1 == null) {
208:
209: this .q.setAllObjects((List) qr.getGroupByResults().get(
210: lo1));
211:
212: // Also, setup the save values.
213: this .q
214: .setSaveValues((Map) qr
215: .getGroupBySaveValues(lo1));
216:
217: this .q.setCurrentObject(o1);
218:
219: if (it.exp != null) {
220:
221: eo1 = it.exp.getValue(o1, this .q);
222:
223: } else {
224:
225: eo1 = lo1.get(it.ind - 1);
226:
227: }
228:
229: co.put(it, eo1);
230:
231: }
232:
233: get = true;
234:
235: eo2 = null;
236:
237: co = (Map) cache.get(o2);
238:
239: if (co == null) {
240:
241: co = new HashMap(this .size);
242:
243: cache.put(o2, co);
244:
245: get = false;
246:
247: }
248:
249: if (get) {
250:
251: eo2 = co.get(it);
252:
253: }
254:
255: if (eo2 == null) {
256:
257: this .q.setAllObjects((List) qr.getGroupByResults().get(
258: lo2));
259:
260: // Also, setup the save values.
261: this .q
262: .setSaveValues((Map) qr
263: .getGroupBySaveValues(lo2));
264:
265: this .q.setCurrentObject(o2);
266:
267: if (it.exp != null) {
268:
269: eo2 = it.exp.getValue(o2, this .q);
270:
271: } else {
272:
273: eo2 = lo2.get(it.ind - 1);
274:
275: }
276:
277: co.put(it, eo2);
278:
279: }
280:
281: // Compare them...
282: int c = Utilities.compare(eo1, eo2);
283:
284: if (c == 0) {
285:
286: // Go to the next...
287: continue;
288:
289: }
290:
291: // For speed reasons, 1 is used here rather than the constant.
292: if (it.dir == 1) {
293:
294: c = -1 * c;
295:
296: }
297:
298: return c;
299:
300: }
301:
302: return 0;
303:
304: }
305:
306: public int compare(Object o1, Object o2) {
307:
308: try {
309:
310: if (this .caching) {
311:
312: return this .cic(o1, o2);
313:
314: } else {
315:
316: return this .ci(o1, o2);
317:
318: }
319:
320: } catch (Exception e) {
321:
322: this .exp = e;
323:
324: return 0;
325:
326: }
327:
328: }
329:
330: public Exception getException() {
331:
332: return this .exp;
333:
334: }
335:
336: public void addSortItem(Expression exp, int ind, int dir) {
337:
338: Item it = new Item();
339: it.dir = dir;
340: it.ind = ind;
341: it.exp = exp;
342:
343: this .items.add(it);
344:
345: this .size = this .items.size();
346:
347: }
348:
349: private class Item {
350:
351: public int dir = 0;
352: public int ind = 0;
353: public Expression exp = null;
354:
355: }
356:
357: }
|