KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > QCandidates


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

21 package com.db4o;
22
23 import com.db4o.foundation.*;
24 import com.db4o.inside.classindex.*;
25 import com.db4o.inside.diagnostic.DiagnosticProcessor;
26 import com.db4o.inside.fieldindex.*;
27 import com.db4o.inside.marshall.*;
28
29 /**
30  * Holds the tree of {@link QCandidate} objects and the list of {@link QCon} during query evaluation.
31  * The query work (adding and removing nodes) happens here.
32  * Candidates during query evaluation. {@link QCandidate} objects are stored in i_root
33  *
34  * @exclude
35  */

36 public final class QCandidates implements Visitor4 {
37
38     // Transaction necessary as reference to stream
39
public final Transaction i_trans;
40
41     // root of the QCandidate tree
42
public Tree i_root;
43
44     // collection of all constraints
45
private List4 i_constraints;
46
47     // possible class information
48
YapClass i_yapClass;
49
50     // possible field information
51
private QField i_field;
52
53     // current executing constraint, only set where needed
54
QCon i_currentConstraint;
55
56     // QOrder tree
57
Tree i_ordered;
58
59     //
60
private int i_orderID;
61     
62     private IDGenerator _idGenerator;
63
64     QCandidates(Transaction a_trans, YapClass a_yapClass, QField a_field) {
65         i_trans = a_trans;
66         i_yapClass = a_yapClass;
67         i_field = a_field;
68    
69         if (a_field == null
70                 || a_field.i_yapField == null
71                 || !(a_field.i_yapField.getHandler() instanceof YapClass)
72         ) {
73             return;
74         }
75
76         YapClass yc = (YapClass) a_field.i_yapField.getHandler();
77         if (i_yapClass == null) {
78             i_yapClass = yc;
79         } else {
80             yc = i_yapClass.getHigherOrCommonHierarchy(yc);
81             if (yc != null) {
82                 i_yapClass = yc;
83             }
84         }
85     }
86
87     public QCandidate addByIdentity(QCandidate candidate) {
88         i_root = Tree.add(i_root, candidate);
89         if(candidate._size == 0){
90             
91             // This means that the candidate was already present
92
// and QCandidate does not allow duplicates.
93

94             // In this case QCandidate#isDuplicateOf will have
95
// placed the existing QCandidate in the i_root
96
// variable of the new candidate. We return it here:
97

98             return candidate.getRoot();
99         
100         }
101         return candidate;
102     }
103
104     void addConstraint(QCon a_constraint) {
105         i_constraints = new List4(i_constraints, a_constraint);
106     }
107
108     void addOrder(QOrder a_order) {
109         i_ordered = Tree.add(i_ordered, a_order);
110     }
111
112     void applyOrdering(Tree a_ordered, int a_orderID) {
113         if (a_ordered == null || i_root == null) {
114             return;
115         }
116         if (a_orderID > 0) {
117             a_orderID = -a_orderID;
118         }
119         final boolean major = (a_orderID - i_orderID) < 0;
120         if (major) {
121             i_orderID = a_orderID;
122         }
123         
124         final int[] placement = { 0 };
125         // Step 1: Clear possible old ordering criteria
126
// and store old order.
127
i_root.traverse(new Visitor4() {
128             public void visit(Object JavaDoc a_object) {
129                 ((QCandidate) a_object).hintOrder(0, major);
130                 ((QCandidate) a_object).hintOrder(placement[0]++, !major);
131             }
132         });
133         
134         // Step 2: Set new ordering criteria
135
placement[0] = 1;
136         a_ordered.traverse(new Visitor4() {
137             public void visit(Object JavaDoc a_object) {
138                 QOrder qo = (QOrder) a_object;
139                 QCandidate candidate = qo._candidate.getRoot();
140                 candidate.hintOrder(placement[0]++, major);
141             }
142         });
143         
144         // Step 3: We need to put them all into a collection,
145
// so we can safely remove the old tree joins
146
final Collection4 col = new Collection4();
147         i_root.traverse(new Visitor4() {
148             public void visit(Object JavaDoc a_object) {
149                 QCandidate candidate = (QCandidate) a_object;
150                 col.add(candidate);
151             }
152         });
153         
154         // Step 4: Add them to our tree again.
155
Tree newTree = null;
156         Iterator4 i = col.iterator();
157         while(i.moveNext()){
158             QCandidate candidate = (QCandidate) i.current();
159             candidate._preceding = null;
160             candidate._subsequent = null;
161             candidate._size = 1;
162             newTree = Tree.add(newTree, candidate);
163         }
164         
165         i_root = newTree;
166     }
167
168     void collect(final QCandidates a_candidates) {
169         Iterator4 i = iterateConstraints();
170         while(i.moveNext()){
171             QCon qCon = (QCon)i.current();
172             setCurrentConstraint(qCon);
173             qCon.collect(a_candidates);
174         }
175         setCurrentConstraint(null);
176     }
177
178     void execute() {
179         if(DTrace.enabled){
180             DTrace.QUERY_PROCESS.log();
181         }
182         final FieldIndexProcessorResult result = processFieldIndexes();
183         if(result.foundIndex()){
184             i_root = result.toQCandidate(this);
185         }else{
186             loadFromClassIndex();
187         }
188         evaluate();
189     }
190     
191     public Iterator4 executeSnapshot(Collection4 executionPath){
192         IntIterator4 indexIterator = new IntIterator4Adaptor(iterateIndex(processFieldIndexes()));
193         Tree idRoot = TreeInt.addAll(null, indexIterator);
194         Iterator4 snapshotIterator = new TreeKeyIterator(idRoot);
195         Iterator4 singleObjectQueryIterator = singleObjectSodaProcessor(snapshotIterator);
196         return mapIdsToExecutionPath(singleObjectQueryIterator, executionPath);
197     }
198     
199     private Iterator4 singleObjectSodaProcessor(Iterator4 indexIterator){
200         return new MappingIterator(indexIterator) {
201             protected Object JavaDoc map(Object JavaDoc current) {
202                 int id = ((Integer JavaDoc)current).intValue();
203                 QCandidate candidate = new QCandidate(QCandidates.this, null, id, true);
204                 i_root = candidate;
205                 evaluate();
206                 if(! candidate.include()){
207                     return MappingIterator.SKIP;
208                 }
209                 return current;
210             }
211         };
212     }
213     
214     public Iterator4 executeLazy(Collection4 executionPath){
215         Iterator4 indexIterator = iterateIndex(processFieldIndexes());
216         Iterator4 singleObjectQueryIterator = singleObjectSodaProcessor(indexIterator);
217         return mapIdsToExecutionPath(singleObjectQueryIterator, executionPath);
218     }
219     
220     private Iterator4 iterateIndex (FieldIndexProcessorResult result ){
221         if(result.noMatch()){
222             return Iterator4Impl.EMPTY;
223         }
224         if(result.foundIndex()){
225             return result.iterateIDs();
226         }
227         if(i_yapClass.isPrimitive()){
228             return Iterator4Impl.EMPTY;
229         }
230         return BTreeClassIndexStrategy.iterate(i_yapClass, i_trans);
231     }
232
233     private Iterator4 mapIdsToExecutionPath(Iterator4 singleObjectQueryIterator, Collection4 executionPath) {
234         
235         if(executionPath == null){
236             return singleObjectQueryIterator;
237         }
238         
239         Iterator4 res = singleObjectQueryIterator;
240         
241         Iterator4 executionPathIterator = executionPath.iterator();
242         while(executionPathIterator.moveNext()){
243             
244             final String JavaDoc fieldName = (String JavaDoc) executionPathIterator.current();
245             
246             Iterator4 mapIdToFieldIdsIterator = new MappingIterator(res){
247                 
248                 protected Object JavaDoc map(Object JavaDoc current) {
249                     int id = ((Integer JavaDoc)current).intValue();
250                     YapWriter reader = stream().readWriterByID(i_trans, id);
251                     if (reader == null) {
252                         return MappingIterator.SKIP;
253                     }
254                         
255                     ObjectHeader oh = new ObjectHeader(stream(), reader);
256                     
257                     Tree idTree = oh.yapClass().collectFieldIDs(
258                             oh._marshallerFamily,
259                             oh._headerAttributes,
260                             null,
261                             reader,
262                             fieldName);
263
264                     return new TreeKeyIterator(idTree);
265                 }
266                 
267             };
268             
269             res = new CompositeIterator4(mapIdToFieldIdsIterator);
270             
271         }
272         return res;
273     }
274     
275     public YapStream stream() {
276         return i_trans.stream();
277     }
278
279     public int classIndexEntryCount() {
280         return i_yapClass.indexEntryCount(i_trans);
281     }
282
283     private FieldIndexProcessorResult processFieldIndexes() {
284         if(i_constraints == null){
285             return FieldIndexProcessorResult.NO_INDEX_FOUND;
286         }
287         return new FieldIndexProcessor(this).run();
288     }
289
290     void evaluate() {
291         
292         if (i_constraints == null) {
293             return;
294         }
295         
296         Iterator4 i = iterateConstraints();
297         while(i.moveNext()){
298             QCon qCon = (QCon)i.current();
299             qCon.setCandidates(this);
300             qCon.evaluateSelf();
301         }
302         
303         i = iterateConstraints();
304         while(i.moveNext()){
305             ((QCon)i.current()).evaluateSimpleChildren();
306         }
307         
308         i = iterateConstraints();
309         while(i.moveNext()){
310             ((QCon)i.current()).evaluateEvaluations();
311         }
312         
313         i = iterateConstraints();
314         while(i.moveNext()){
315             ((QCon)i.current()).evaluateCreateChildrenCandidates();
316         }
317         
318         i = iterateConstraints();
319         while(i.moveNext()){
320             ((QCon)i.current()).evaluateCollectChildren();
321         }
322         
323         i = iterateConstraints();
324         while(i.moveNext()){
325             ((QCon)i.current()).evaluateChildren();
326         }
327     }
328
329     boolean isEmpty() {
330         final boolean[] ret = new boolean[] { true };
331         traverse(new Visitor4() {
332             public void visit(Object JavaDoc obj) {
333                 if (((QCandidate) obj)._include) {
334                     ret[0] = false;
335                 }
336             }
337         });
338         return ret[0];
339     }
340
341     boolean filter(Visitor4 a_host) {
342         if (i_root != null) {
343             i_root.traverse(a_host);
344             i_root = i_root.filter(new Predicate4() {
345                 public boolean match(Object JavaDoc a_candidate) {
346                     return ((QCandidate) a_candidate)._include;
347                 }
348             });
349         }
350
351         return i_root != null;
352     }
353     
354     int generateCandidateId(){
355         if(_idGenerator == null){
356             _idGenerator = new IDGenerator();
357         }
358         return - _idGenerator.next();
359     }
360     
361     public Iterator4 iterateConstraints(){
362         if(i_constraints == null){
363             return Iterator4Impl.EMPTY;
364         }
365         return new Iterator4Impl(i_constraints);
366     }
367     
368     final static class TreeIntBuilder {
369         public TreeInt tree;
370         
371         public void add(TreeInt node) {
372             tree = (TreeInt)Tree.add(tree, node);
373         }
374     }
375
376     void loadFromClassIndex() {
377         if (!isEmpty()) {
378             return;
379         }
380         
381         final TreeIntBuilder result = new TreeIntBuilder();
382         final ClassIndexStrategy index = i_yapClass.index();
383         index.traverseAll(i_trans, new Visitor4() {
384             public void visit(Object JavaDoc obj) {
385                 result.add(new QCandidate(QCandidates.this, null, ((Integer JavaDoc)obj).intValue(), true));
386             }
387         });
388     
389         i_root = result.tree;
390         
391         DiagnosticProcessor dp = i_trans.stream().i_handlers._diagnosticProcessor;
392         if (dp.enabled()){
393             dp.loadedFromClassIndex(i_yapClass);
394         }
395         
396     }
397
398     void setCurrentConstraint(QCon a_constraint) {
399         i_currentConstraint = a_constraint;
400     }
401
402     void traverse(Visitor4 a_visitor) {
403         if(i_root != null){
404             i_root.traverse(a_visitor);
405         }
406     }
407
408     boolean tryAddConstraint(QCon a_constraint) {
409
410         if (i_field != null) {
411             QField qf = a_constraint.getField();
412             if (qf != null) {
413                 if (i_field.i_name != qf.i_name) {
414                     return false;
415                 }
416             }
417         }
418
419         if (i_yapClass == null || a_constraint.isNullConstraint()) {
420             addConstraint(a_constraint);
421             return true;
422         }
423         YapClass yc = a_constraint.getYapClass();
424         if (yc != null) {
425             yc = i_yapClass.getHigherOrCommonHierarchy(yc);
426             if (yc != null) {
427                 i_yapClass = yc;
428                 addConstraint(a_constraint);
429                 return true;
430             }
431         }
432         return false;
433     }
434
435     public void visit(Object JavaDoc a_tree) {
436         final QCandidate parent = (QCandidate) a_tree;
437         if (parent.createChild(this)) {
438             return;
439         }
440         
441         // No object found.
442
// All children constraints are necessarily false.
443
// Check immediately.
444
Iterator4 i = iterateConstraints();
445         while(i.moveNext()){
446             ((QCon)i.current()).visitOnNull(parent.getRoot());
447         }
448             
449     }
450 }
451
Popular Tags