001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.query.processor;
022:
023: import com.db4o.foundation.*;
024: import com.db4o.internal.*;
025: import com.db4o.reflect.*;
026:
027: /**
028: * Placeholder for a constraint, only necessary to attach children
029: * to the query graph.
030: *
031: * Added upon a call to Query#descend(), if there is no
032: * other place to hook up a new constraint.
033: *
034: * @exclude
035: */
036: public class QConPath extends QConClass {
037:
038: public QConPath() {
039:
040: }
041:
042: QConPath(Transaction a_trans, QCon a_parent, QField a_field) {
043: super (a_trans, a_parent, a_field, null);
044: if (a_field != null) {
045: i_yapClass = a_field.getYapClass();
046: }
047: }
048:
049: public boolean canLoadByIndex() {
050: return false;
051: }
052:
053: boolean evaluate(QCandidate a_candidate) {
054: if (!a_candidate.fieldIsAvailable()) {
055: visitOnNull(a_candidate.getRoot());
056: }
057: return true;
058: }
059:
060: void evaluateSelf() {
061: // do nothing
062: }
063:
064: boolean isNullConstraint() {
065: return !hasChildren();
066: }
067:
068: QConClass shareParentForClass(ReflectClass a_class,
069: boolean[] removeExisting) {
070: if (i_parent == null) {
071: return null;
072: }
073: if (!i_field.canHold(a_class)) {
074: return null;
075: }
076: QConClass newConstraint = new QConClass(i_trans, i_parent,
077: i_field, a_class);
078: morph(removeExisting, newConstraint, a_class);
079: return newConstraint;
080: }
081:
082: QCon shareParent(Object a_object, boolean[] removeExisting) {
083: if (i_parent == null) {
084: return null;
085: }
086: Object obj = i_field.coerce(a_object);
087: if (obj == No4.INSTANCE) {
088: QCon falseConstraint = new QConUnconditional(i_trans, false);
089: morph(removeExisting, falseConstraint,
090: reflectClassForObject(obj));
091: return falseConstraint;
092: }
093: QConObject newConstraint = new QConObject(i_trans, i_parent,
094: i_field, obj);
095: morph(removeExisting, newConstraint, reflectClassForObject(obj));
096: return newConstraint;
097: }
098:
099: private ReflectClass reflectClassForObject(Object obj) {
100: return i_trans.reflector().forObject(obj);
101: }
102:
103: // Our QConPath objects are just placeholders to fields,
104: // so the parents are reachable.
105: // If we find a "real" constraint, we throw the QPath
106: // out and replace it with the other constraint.
107: private void morph(boolean[] removeExisting, QCon newConstraint,
108: ReflectClass claxx) {
109: boolean mayMorph = true;
110: if (claxx != null) {
111: ClassMetadata yc = i_trans.container()
112: .produceClassMetadata(claxx);
113: if (yc != null) {
114: Iterator4 i = iterateChildren();
115: while (i.moveNext()) {
116: QField qf = ((QCon) i.current()).getField();
117: if (!yc.hasField(i_trans.container(), qf.i_name)) {
118: mayMorph = false;
119: break;
120: }
121: }
122: }
123: }
124:
125: // }
126:
127: if (mayMorph) {
128: Iterator4 j = iterateChildren();
129: while (j.moveNext()) {
130: newConstraint.addConstraint((QCon) j.current());
131: }
132: if (hasJoins()) {
133: Iterator4 k = iterateJoins();
134: while (k.moveNext()) {
135: QConJoin qcj = (QConJoin) k.current();
136: qcj.exchangeConstraint(this , newConstraint);
137: newConstraint.addJoin(qcj);
138: }
139: }
140: i_parent.exchangeConstraint(this , newConstraint);
141: removeExisting[0] = true;
142:
143: } else {
144: i_parent.addConstraint(newConstraint);
145: }
146: }
147:
148: final boolean visitSelfOnNull() {
149: return false;
150: }
151:
152: public String toString() {
153: if (!Debug4.prettyToStrings) {
154: return super .toString();
155: }
156: return "QConPath " + super.toString();
157: }
158:
159: }
|