001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo;
012:
013: import com.versant.core.common.Debug;
014:
015: import java.util.*;
016:
017: import com.versant.core.common.BindingSupportImpl;
018: import com.versant.core.jdo.query.mem.BCodeQuery;
019: import com.versant.core.jdo.query.mem.BCodeSorter;
020: import com.versant.core.jdo.VersantPersistenceManagerImp;
021: import com.versant.core.jdo.query.mem.BCodeSorter;
022: import com.versant.core.jdo.query.mem.BCodeQuery;
023:
024: /**
025: * Results of an in memory query.
026: */
027: public class MemoryQueryResult extends QueryResultBase {
028:
029: private final List internalList = new ArrayList();
030: private boolean closed;
031: private final List operIters = new ArrayList();
032: boolean toSort = false;
033: private BCodeQuery bCodeQuery = null;
034: private final Class candidateClass;
035: private final boolean checkExtentSubClasses;
036:
037: public MemoryQueryResult(PMProxy sm, QueryDetails queryDetails,
038: Collection col, Object[] params) {
039: checkExtentSubClasses = queryDetails.includeSubClasses();
040: this .candidateClass = queryDetails.getCandidateClass();
041: createDynamicQuery(sm.getRealPM(), queryDetails, params);
042:
043: filter(col, internalList, params, sm);
044: int n = internalList.size();
045: for (int i = n - 1; i >= 0; i--) {
046: internalList.set(i, sm.getObjectById(internalList.get(i),
047: false));
048: }
049: Collections.reverse(internalList);
050: }
051:
052: public MemoryQueryResult() {
053: candidateClass = null;
054: checkExtentSubClasses = false;
055: }
056:
057: public void filter(Collection toFilter, List results,
058: Object[] params, PMProxy pm) {
059: // long start = System.currentTimeMillis();
060: results.clear();
061: PCStateMan pcStateObject = null;
062: for (Iterator iterator = toFilter.iterator(); iterator
063: .hasNext();) {
064: pcStateObject = (PCStateMan) iterator.next();
065: if (checkType(pcStateObject)
066: && checkFilter(pcStateObject, params)) {
067: results.add(pcStateObject.oid);
068: }
069: }
070: if (toSort) {
071: sort(results, pm);
072: }
073: // if (Debug.DEBUG) {
074: // Debug.out.println("Time for filter = " + (System.currentTimeMillis() - start));
075: // }
076: }
077:
078: private void sort(List list, PMProxy pm) {
079: if (list == null || list.isEmpty()) {
080: return;
081: }
082: BCodeSorter bCodeSorter = new BCodeSorter();
083: bCodeSorter.sort(list, pm, bCodeQuery);
084: }
085:
086: /**
087: * Check if the type is valid. This will check that the class is of the right type and if it is a
088: * sub class if allowed.
089: *
090: * @param pcStateObject
091: */
092: public final boolean checkType(PCStateMan pcStateObject) {
093: if (checkExtentSubClasses) {
094: return candidateClass.isAssignableFrom(pcStateObject.pc
095: .getClass());
096: } else {
097: return pcStateObject.pc.getClass() == candidateClass;
098: }
099: }
100:
101: /**
102: * Check if the instance is valid according to the filter.
103: *
104: * @param pcStateObject
105: */
106: public final boolean checkFilter(PCStateMan pcStateObject,
107: Object[] params) {
108: if (pcStateObject.isDeleted(null))
109: return false;
110: try {
111: boolean result = bCodeQuery.exec(
112: pcStateObject.queryStateWrapper, params);
113: return result;
114: } catch (Exception e) {
115: if (Debug.DEBUG) {
116: e.printStackTrace(Debug.OUT);
117: }
118: return false;
119: }
120: }
121:
122: private void createDynamicQuery(VersantPersistenceManagerImp sm,
123: QueryDetails queryParams, Object[] params) {
124:
125: bCodeQuery = sm.getMemQueryCompiler().compile(queryParams,
126: params);
127:
128: toSort = isOrdered(queryParams);
129: }
130:
131: private final boolean isOrdered(QueryDetails queryParams) {
132: return queryParams.getOrdering() != null;
133: }
134:
135: public int size() {
136: return internalList.size();
137: }
138:
139: public boolean isEmpty() {
140: return internalList.isEmpty();
141: }
142:
143: public boolean contains(Object o) {
144: return internalList.contains(o);
145: }
146:
147: public Object[] toArray() {
148: return internalList.toArray();
149: }
150:
151: public Object[] toArray(Object a[]) {
152: return internalList.toArray(a);
153: }
154:
155: public boolean containsAll(Collection c) {
156: return internalList.containsAll(c);
157: }
158:
159: public Object get(int index) {
160: return internalList.get(index);
161: }
162:
163: public int indexOf(Object o) {
164: return internalList.indexOf(o);
165: }
166:
167: public int lastIndexOf(Object o) {
168: return internalList.lastIndexOf(o);
169: }
170:
171: public Iterator iterator() {
172: Iterator iter = new InternalIter(internalList.listIterator());
173: operIters.add(iter);
174: return iter;
175: }
176:
177: public Iterator createInternalIter() {
178: return iterator();
179: }
180:
181: public Iterator createInternalIterNoFlush() {
182: return iterator();
183: }
184:
185: public ListIterator listIterator() {
186: ListIterator iter = new InternalIter(internalList
187: .listIterator());
188: operIters.add(iter);
189: return iter;
190: }
191:
192: public ListIterator listIterator(int index) {
193: ListIterator iter = new InternalIter(internalList
194: .listIterator(index));
195: operIters.add(iter);
196: return iter;
197: }
198:
199: public List subList(int fromIndex, int toIndex) {
200: throw BindingSupportImpl.getInstance().unsupported("");
201: }
202:
203: public void close() {
204: closed = true;
205: for (int i = 0; i < operIters.size(); i++) {
206: ((InternalIter) operIters.get(i)).wrapperIter = null;
207: }
208: internalList.clear();
209: operIters.clear();
210: }
211:
212: public void setParams(Object[] params) {
213: }
214:
215: public class InternalIter implements ListIterator {
216:
217: private ListIterator wrapperIter;
218:
219: public InternalIter(ListIterator wrapperIter) {
220: this .wrapperIter = wrapperIter;
221: }
222:
223: public boolean hasNext() {
224: if (closed) {
225: return false;
226: }
227: return wrapperIter.hasNext();
228: }
229:
230: public Object next() {
231: if (closed) {
232: throw BindingSupportImpl.getInstance()
233: .noSuchElement("");
234: }
235: return wrapperIter.next();
236: }
237:
238: public boolean hasPrevious() {
239: if (closed) {
240: return false;
241: }
242: return wrapperIter.hasPrevious();
243: }
244:
245: public Object previous() {
246: if (closed) {
247: throw BindingSupportImpl.getInstance()
248: .noSuchElement("");
249: }
250: return wrapperIter.previous();
251: }
252:
253: public int nextIndex() {
254: if (closed) {
255: return -1;
256: }
257: return wrapperIter.nextIndex();
258: }
259:
260: public int previousIndex() {
261: if (closed) {
262: return -1;
263: }
264: return wrapperIter.previousIndex();
265: }
266:
267: public void remove() {
268: throw BindingSupportImpl.getInstance().invalidOperation(
269: "Modification is not allowed");
270: }
271:
272: public void set(Object o) {
273: throw BindingSupportImpl.getInstance().invalidOperation(
274: "Modification is not allowed");
275: }
276:
277: public void add(Object o) {
278: throw BindingSupportImpl.getInstance().invalidOperation(
279: "Modification is not allowed");
280: }
281: }
282: }
|