KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > QCon


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.*;
25 import com.db4o.query.*;
26 import com.db4o.reflect.*;
27 import com.db4o.types.*;
28
29 /**
30  * Base class for all constraints on queries.
31  *
32  * @exclude
33  */

34 public abstract class QCon implements Constraint, Visitor4, Unversioned {
35     
36     //Used for query debug only.
37
static final IDGenerator idGenerator = new IDGenerator();
38
39     // our candidate object tree
40
transient QCandidates i_candidates;
41
42     // collection of QCandidates to collect children elements and to
43
// execute children. For convenience we hold them in the constraint,
44
// so we can do collection and execution in two steps
45
public Collection4 i_childrenCandidates;
46
47     // all subconstraints
48
public List4 _children;
49
50     // for evaluation
51
public QE i_evaluator = QE.DEFAULT;
52
53     // ID handling for fast find of QConstraint objects in
54
// pending OR evaluations
55
public int i_id;
56
57     // ANDs and ORs on this constraint
58
public Collection4 i_joins;
59
60     // positive indicates ascending, negative indicates descending
61
// value indicates ID supplied by ID generator.
62
// lower IDs are applied first
63
public int i_orderID = 0;
64
65     // the parent of this constraint or null, if this is a root
66
public QCon i_parent;
67
68     // prevents circular calls on removal
69
public boolean i_removed = false;
70
71     // our transaction to get a stream object anywhere
72
transient Transaction i_trans;
73
74     public QCon() {
75         // C/S only
76
}
77
78     QCon(Transaction a_trans) {
79         i_id = idGenerator.next();
80         i_trans = a_trans;
81     }
82
83     QCon addConstraint(QCon a_child) {
84         _children = new List4(_children, a_child);
85         return a_child;
86     }
87     
88     public Transaction transaction() {
89         return i_trans;
90     }
91
92     void addJoin(QConJoin a_join) {
93         if (i_joins == null) {
94             i_joins = new Collection4();
95         }
96         i_joins.add(a_join);
97     }
98
99     QCon addSharedConstraint(QField a_field, Object JavaDoc a_object) {
100         QConObject newConstraint = new QConObject(i_trans, this, a_field, a_object);
101         addConstraint(newConstraint);
102         return newConstraint;
103     }
104
105     public Constraint and(Constraint andWith) {
106         synchronized (streamLock()) {
107             return join(andWith, true);
108         }
109     }
110
111     void applyOrdering() {
112         if (i_orderID != 0) {
113             QCon root = getRoot();
114             root.i_candidates.applyOrdering(i_candidates.i_ordered, i_orderID);
115         }
116     }
117
118     boolean attach(final QQuery query, final String JavaDoc a_field) {
119         
120         final QCon qcon = this;
121         
122         YapClass yc = getYapClass();
123         final boolean[] foundField = { false };
124         forEachChildField(a_field, new Visitor4() {
125             public void visit(Object JavaDoc obj) {
126                 foundField[0] = true;
127                 query.addConstraint((QCon) obj);
128             }
129         });
130         
131         if (foundField[0]) {
132             return true;
133         }
134         
135         QField qf = null;
136         
137         if (yc == null || yc.holdsAnyClass()) {
138             
139             final int[] count = { 0 };
140             final YapField[] yfs = { null };
141             
142             i_trans.stream().classCollection().attachQueryNode(a_field, new Visitor4() {
143                 public void visit(Object JavaDoc obj) {
144                     yfs[0] = (YapField) ((Object JavaDoc[]) obj)[1];
145                     count[0]++;
146                 }
147             });
148             
149             if (count[0] == 0) {
150                 return false;
151             }
152             
153             if (count[0] == 1) {
154                 qf = yfs[0].qField(i_trans);
155             } else {
156                 qf = new QField(i_trans, a_field, null, 0, 0);
157             }
158             
159         } else {
160             if(yc.configInstantiates()) {
161                 i_trans.stream().i_handlers._diagnosticProcessor.descendIntoTranslator(yc, a_field);
162             }
163             YapField yf = yc.getYapField(a_field);
164             if (yf != null) {
165                 qf = yf.qField(i_trans);
166             }
167             if (qf == null) {
168                 qf = new QField(i_trans, a_field, null, 0, 0);
169             }
170         }
171         
172         QConPath qcp = new QConPath(i_trans, qcon, qf);
173         query.addConstraint(qcp);
174         qcon.addConstraint(qcp);
175         return true;
176     }
177     
178     public boolean canBeIndexLeaf(){
179         return false;
180     }
181
182     public boolean canLoadByIndex(){
183         // virtual
184
return false;
185     }
186
187     void checkLastJoinRemoved() {
188         if (i_joins.size() == 0) {
189             i_joins = null;
190         }
191     }
192
193     void collect(QCandidates a_candidates) {
194         // virtual
195
}
196
197     public Constraint contains() {
198         throw notSupported();
199     }
200
201     void createCandidates(Collection4 a_candidateCollection) {
202         Iterator4 j = a_candidateCollection.iterator();
203         while (j.moveNext()) {
204             QCandidates candidates = (QCandidates) j.current();
205             if (candidates.tryAddConstraint(this)) {
206                 i_candidates = candidates;
207                 return;
208             }
209         }
210         i_candidates = new QCandidates(i_trans, getYapClass(), getField());
211         i_candidates.addConstraint(this);
212         a_candidateCollection.add(i_candidates);
213     }
214
215     void doNotInclude(QCandidate a_root) {
216         if(DTrace.enabled){
217             DTrace.DONOTINCLUDE.log(i_id);
218         }
219         if (Debug.queries) {
220             System.out.println("QCon.doNotInclude " + i_id /*+ " " + getYapClass()*/
221             );
222         }
223         if (i_parent != null) {
224             i_parent.visit1(a_root, this, false);
225         } else {
226             a_root.doNotInclude();
227         }
228     }
229
230     public Constraint equal() {
231         throw notSupported();
232     }
233
234     boolean evaluate(QCandidate a_candidate) {
235         throw Exceptions4.virtualException();
236     }
237
238     void evaluateChildren() {
239         Iterator4 i = i_childrenCandidates.iterator();
240         while (i.moveNext()) {
241             ((QCandidates) i.current()).evaluate();
242         }
243     }
244
245     void evaluateCollectChildren() {
246         if(DTrace.enabled){
247             DTrace.COLLECT_CHILDREN.log(i_id);
248         }
249         Iterator4 i = i_childrenCandidates.iterator();
250         while (i.moveNext()) {
251             ((QCandidates) i.current()).collect(i_candidates);
252         }
253     }
254
255     void evaluateCreateChildrenCandidates() {
256         i_childrenCandidates = new Collection4();
257         Iterator4 i = iterateChildren();
258         while(i.moveNext()){
259             ((QCon)i.current()).createCandidates(i_childrenCandidates);
260         }
261     }
262
263     void evaluateEvaluations() {
264         Iterator4 i = iterateChildren();
265         while(i.moveNext()){
266             ((QCon)i.current()).evaluateEvaluationsExec(i_candidates, true);
267         }
268     }
269
270     void evaluateEvaluationsExec(QCandidates a_candidates, boolean rereadObject) {
271         // virtual
272
}
273
274     void evaluateSelf() {
275         i_candidates.filter(this);
276     }
277
278     void evaluateSimpleChildren() {
279         
280         // TODO: sort the constraints for YapFields first,
281
// so we stay with the same YapField
282

283         if(_children == null) {
284             return;
285         }
286         
287         Iterator4 i = iterateChildren();
288         while(i.moveNext()){
289             QCon qcon = (QCon)i.current();
290             i_candidates.setCurrentConstraint(qcon);
291             qcon.setCandidates(i_candidates);
292             qcon.evaluateSimpleExec(i_candidates);
293             qcon.applyOrdering();
294         }
295         i_candidates.setCurrentConstraint(null);
296     }
297
298     void evaluateSimpleExec(QCandidates a_candidates) {
299         // virtual
300
}
301
302     void exchangeConstraint(QCon a_exchange, QCon a_with) {
303         List4 previous = null;
304         List4 current = _children;
305         while (current != null) {
306             if (current._element == a_exchange) {
307                 if (previous == null) {
308                     _children = current._next;
309                 } else {
310                     previous._next = current._next;
311                 }
312             }
313             previous = current;
314             current = current._next;
315         }
316         
317         _children = new List4(_children, a_with);
318     }
319
320     void forEachChildField(final String JavaDoc name, final Visitor4 visitor) {
321         Iterator4 i = iterateChildren();
322         while(i.moveNext()){
323             Object JavaDoc obj = i.current();
324             if (obj instanceof QConObject) {
325                 if (((QConObject) obj).i_field.i_name.equals(name)) {
326                     visitor.visit(obj);
327                 }
328             }
329         }
330     }
331
332     public QField getField() {
333         return null;
334     }
335
336     public Object JavaDoc getObject() {
337         throw notSupported();
338     }
339
340     QCon getRoot() {
341         if (i_parent != null) {
342             return i_parent.getRoot();
343         }
344         return this;
345     }
346
347     QCon produceTopLevelJoin() {
348         if(! hasJoins()){
349             return this;
350         }
351         Iterator4 i = iterateJoins();
352         if (i_joins.size() == 1) {
353             i.moveNext();
354             return ((QCon) i.current()).produceTopLevelJoin();
355         }
356         Collection4 col = new Collection4();
357         while (i.moveNext()) {
358             col.ensure(((QCon) i.current()).produceTopLevelJoin());
359         }
360         i = col.iterator();
361         i.moveNext();
362         QCon qcon = (QCon) i.current();
363         if (col.size() == 1) {
364             return qcon;
365         }
366         while (i.moveNext()) {
367             qcon = (QCon) qcon.and((Constraint) i.current());
368         }
369         return qcon;
370     }
371
372     YapClass getYapClass() {
373         return null;
374     }
375
376     public Constraint greater() {
377         throw notSupported();
378     }
379     
380     public boolean hasChildren(){
381         return _children != null;
382     }
383     
384     public boolean hasParent() {
385         return i_parent != null;
386     }
387     
388     public QCon parent() {
389         return i_parent;
390     }
391     
392     public boolean hasOrJoins(){
393         Collection4 lookedAt = new Collection4();
394         return hasOrJoins(lookedAt);
395     }
396     
397     boolean hasOrJoins(Collection4 lookedAt){
398         if(lookedAt.containsByIdentity(this)){
399             return false;
400         }
401         lookedAt.add(this);
402         if(i_joins == null){
403             return false;
404         }
405         Iterator4 i = iterateJoins();
406         while(i.moveNext()){
407             QConJoin join = (QConJoin)i.current();
408             if(join.isOr()){
409                 return true;
410             }
411             if(join.hasOrJoins(lookedAt)){
412                 return true;
413             }
414         }
415         return false;
416     }
417     
418     public boolean hasOrJoinWith(QConObject y) {
419         Iterator4 i = iterateJoins();
420         while(i.moveNext()){
421             QConJoin join = (QConJoin)i.current();
422             if(join.isOr()){
423                 if (y == join.getOtherConstraint(this)) {
424                     return true;
425                 }
426             }
427         }
428         return false;
429     }
430     
431     public boolean hasJoins(){
432         if(i_joins == null){
433             return false;
434         }
435         return i_joins.size() > 0;
436     }
437
438     boolean hasObjectInParentPath(Object JavaDoc obj) {
439         if (i_parent != null) {
440             return i_parent.hasObjectInParentPath(obj);
441         }
442         return false;
443     }
444
445     public Constraint identity() {
446         throw notSupported();
447     }
448
449     public int identityID() {
450         return 0;
451     }
452     
453     boolean isNot() {
454         return i_evaluator instanceof QENot;
455     }
456
457     boolean isNullConstraint() {
458         return false;
459     }
460     
461     Iterator4 iterateJoins(){
462         if(i_joins == null){
463             return Iterator4Impl.EMPTY;
464         }
465         return i_joins.iterator();
466     }
467     
468     public Iterator4 iterateChildren(){
469         if(_children == null){
470             return Iterator4Impl.EMPTY;
471         }
472         return new Iterator4Impl(_children);
473     }
474     
475     Constraint join(Constraint a_with, boolean a_and) {
476         if (!(a_with instanceof QCon) /*|| a_with == this*/
477             ) {
478
479             // TODO: one of our STOr test cases somehow carries
480
// the same constraint twice. This may be a result
481
// of a funny AND. Check!
482

483             return null;
484         }
485         if (a_with == this) {
486             return this;
487         }
488         return join1((QCon) a_with, a_and);
489     }
490
491     Constraint join1(QCon a_with, boolean a_and) {
492
493         if (a_with instanceof QConstraints) {
494             int j = 0;
495             Collection4 joinHooks = new Collection4();
496             Constraint[] constraints = ((QConstraints) a_with).toArray();
497             for (j = 0; j < constraints.length; j++) {
498                 joinHooks.ensure(((QCon) constraints[j]).joinHook());
499             }
500             Constraint[] joins = new Constraint[joinHooks.size()];
501             j = 0;
502             Iterator4 i = joinHooks.iterator();
503             while (i.moveNext()) {
504                 joins[j++] = join((Constraint) i.current(), a_and);
505             }
506             return new QConstraints(i_trans, joins);
507         }
508
509         QCon myHook = joinHook();
510         QCon otherHook = a_with.joinHook();
511         if (myHook == otherHook) {
512             // You might like to check out, what happens, if you
513
// remove this line. It seems to open a bug in an
514
// StOr testcase.
515
return myHook;
516         }
517
518         QConJoin cj = new QConJoin(i_trans, myHook, otherHook, a_and);
519         myHook.addJoin(cj);
520         otherHook.addJoin(cj);
521         return cj;
522     }
523
524     QCon joinHook() {
525         return produceTopLevelJoin();
526     }
527
528     public Constraint like() {
529         throw notSupported();
530     }
531
532     public Constraint startsWith(boolean caseSensitive) {
533         throw notSupported();
534     }
535
536     public Constraint endsWith(boolean caseSensitive) {
537         throw notSupported();
538     }
539
540     void log(String JavaDoc indent) {
541         if (Debug.queries) {
542
543             final String JavaDoc childIndent = " " + indent;
544             String JavaDoc name = getClass().getName();
545             int pos = name.lastIndexOf(".") + 1;
546             name = name.substring(pos);
547             System.out.println(indent + name + " " + logObject() + " " + i_id);
548             // System.out.println(indent + "JOINS");
549
if (hasJoins()) {
550                 Iterator4 i = iterateJoins();
551                 while (i.moveNext()) {
552                     QCon join = (QCon) i.current();
553                     // joins += join.i_id + " ";
554
join.log(childIndent);
555                 }
556             }
557             // System.out.println(joins);
558
// System.out.println(indent + getClass().getName() + " " + i_id + " " + i_debugField + " " + joins );
559
// System.out.println(indent + "CONSTRAINTS");
560

561             if(_children != null){
562                 Iterator4 i = new Iterator4Impl(_children);
563                 while(i.moveNext()){
564                     ((QCon)i.current()).log(childIndent);
565                 }
566             }
567         }
568     }
569
570     String JavaDoc logObject() {
571         return "";
572     }
573
574     void marshall() {
575         Iterator4 i = iterateChildren();
576         while(i.moveNext()){
577             ((QCon)i.current()).marshall();
578         }
579     }
580
581     public Constraint not() {
582         synchronized (streamLock()) {
583             if (!(i_evaluator instanceof QENot)) {
584                 i_evaluator = new QENot(i_evaluator);
585             }
586             return this;
587         }
588     }
589
590     private RuntimeException JavaDoc notSupported() {
591         return new RuntimeException JavaDoc("Not supported.");
592     }
593     
594     public boolean onSameFieldAs(QCon other){
595         return false;
596     }
597
598     public Constraint or(Constraint orWith) {
599         synchronized (streamLock()) {
600             return join(orWith, false);
601         }
602     }
603
604     boolean remove() {
605         if (!i_removed) {
606             i_removed = true;
607             removeChildrenJoins();
608             return true;
609         }
610         return false;
611     }
612
613     void removeChildrenJoins() {
614         if (! hasJoins()) {
615             return;
616         }
617         Iterator4 i = iterateJoins();
618         while(i.moveNext()){
619             QConJoin qcj = (QConJoin) i.current();
620             if (qcj.removeForParent(this)) {
621                 i_joins.remove(qcj);
622             }
623         }
624         checkLastJoinRemoved();
625     }
626
627     void removeJoin(QConJoin a_join) {
628         i_joins.remove(a_join);
629         checkLastJoinRemoved();
630     }
631
632     void removeNot() {
633         if (isNot()) {
634             i_evaluator = ((QENot) i_evaluator).i_evaluator;
635         }
636     }
637
638     public void setCandidates(QCandidates a_candidates) {
639         i_candidates = a_candidates;
640     }
641
642     void setOrdering(int a_ordering) {
643         i_orderID = a_ordering;
644     }
645
646     void setParent(QCon a_newParent) {
647         i_parent = a_newParent;
648     }
649
650     QCon shareParent(Object JavaDoc a_object, boolean[] removeExisting) {
651         // virtual
652
return null;
653     }
654
655     QConClass shareParentForClass(ReflectClass a_class, boolean[] removeExisting) {
656         // virtual
657
return null;
658     }
659
660     public Constraint smaller() {
661         throw notSupported();
662     }
663
664     protected Object JavaDoc streamLock() {
665         return i_trans.stream().i_lock;
666     }
667
668     boolean supportsOrdering() {
669         return false;
670     }
671
672     void unmarshall(final Transaction a_trans) {
673         if (i_trans != null) {
674             return;
675         }
676         i_trans = a_trans;
677         unmarshallParent(a_trans);
678         unmarshallJoins(a_trans);
679         unmarshallChildren(a_trans);
680     }
681
682     private void unmarshallParent(final Transaction a_trans) {
683         if (i_parent != null) {
684             i_parent.unmarshall(a_trans);
685         }
686     }
687
688     private void unmarshallChildren(final Transaction a_trans) {
689         Iterator4 i = iterateChildren();
690         while(i.moveNext()){
691             ((QCon)i.current()).unmarshall(a_trans);
692         }
693     }
694
695     private void unmarshallJoins(final Transaction a_trans) {
696         if (hasJoins()) {
697             Iterator4 i = iterateJoins();
698             while (i.moveNext()) {
699                 ((QCon) i.current()).unmarshall(a_trans);
700             }
701         }
702     }
703
704     public void visit(Object JavaDoc obj) {
705         QCandidate qc = (QCandidate) obj;
706         visit1(qc.getRoot(), this, evaluate(qc));
707     }
708
709     void visit(QCandidate a_root, boolean res) {
710         visit1(a_root, this, i_evaluator.not(res));
711     }
712
713     void visit1(QCandidate a_root, QCon a_reason, boolean res) {
714
715         // The a_reason parameter makes it eays to distinguish
716
// between calls from above (a_reason == this) and below.
717

718         if (hasJoins()) {
719             // this should probably be on the Join
720
Iterator4 i = iterateJoins();
721             while (i.moveNext()) {
722                 a_root.evaluate(new QPending((QConJoin) i.current(), this, res));
723             }
724         } else {
725             if (!res) {
726                 doNotInclude(a_root);
727             }
728         }
729     }
730
731     final void visitOnNull(final QCandidate a_root) {
732
733         // TODO: It may be more efficient to rule out
734
// all possible keepOnNull issues when starting
735
// evaluation.
736

737         if (Debug.queries) {
738             System.out.println("QCon.visitOnNull " + i_id);
739         }
740         
741         Iterator4 i = iterateChildren();
742         while(i.moveNext()){
743             ((QCon)i.current()).visitOnNull(a_root);
744         }
745
746         if (visitSelfOnNull()) {
747             visit(a_root, isNullConstraint());
748         }
749
750     }
751
752     boolean visitSelfOnNull() {
753         return true;
754     }
755
756     public QE evaluator() {
757         return i_evaluator;
758     }
759
760     public boolean requiresSort() {
761         if (i_orderID != 0) {
762             return true;
763         }
764         Iterator4 i = iterateChildren();
765         while(i.moveNext()){
766             if(((QCon)i.current()).requiresSort()){
767                 return true;
768             }
769         }
770         return false;
771     }
772 }
773
Popular Tags