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.query;
012:
013: import com.versant.core.metadata.ClassMetaData;
014: import com.versant.core.common.Debug;
015: import com.versant.core.common.CmdBitSet;
016:
017: import com.versant.core.common.BindingSupportImpl;
018:
019: /**
020: * A node in the parse tree for the query.
021: */
022: public abstract class Node {
023:
024: /**
025: * Our parent node (null if this is the root node).
026: */
027: public Node parent;
028: /**
029: * This makes it easy to form linked lists of nodes. This is
030: * faster and uses less memory than arrays of nodes.
031: */
032: public Node next;
033: /**
034: * Linked list of children formed using their next fields.
035: */
036: public Node childList;
037:
038: public String asValue;
039:
040: public Node() {
041: }
042:
043: public String toString() {
044: return toStr();
045: }
046:
047: private String toStr() {
048: String n = getClass().getName();
049: int i = n.lastIndexOf('.');
050: if (i >= 0)
051: n = n.substring(i + 1);
052: return n + "@"
053: + Integer.toHexString(System.identityHashCode(this ));
054: }
055:
056: /**
057: * Dump debugging info to System.out.
058: */
059: public void dump(String indent) {
060: dumpThis(indent);
061: indent = indent + " ";
062: for (Node c = childList; c != null; c = c.next)
063: c.dump(indent);
064: }
065:
066: /**
067: * Dump without children.
068: */
069: protected void dumpThis(String indent) {
070: Debug.OUT.println(indent + this + " parent "
071: + (parent == null ? "(null)" : parent.toStr()));
072: }
073:
074: /**
075: * Dump as a list.
076: */
077: public void dumpList() {
078: dumpThis("");
079: for (Node c = next; c != null; c = c.next)
080: c.dumpThis(" -> ");
081: }
082:
083: /**
084: * Resolve field refs and so on relative to the compiler. This must
085: * recursively resolve any child nodes.
086: */
087: public void resolve(QueryParser comp, ClassMetaData cmd,
088: boolean ordering) {
089: if (Debug.DEBUG)
090: System.out.println("### Node.resolve " + this );
091: for (Node c = childList; c != null; c = c.next)
092: c.resolve(comp, cmd, ordering);
093: }
094:
095: /**
096: * Set the parent link on all our children.
097: */
098: public void setParentOnChildren() {
099: for (Node c = childList; c != null; c = c.next)
100: c.parent = this ;
101: }
102:
103: /**
104: * Replace one node with another.
105: */
106: public void replaceChild(Node old, Node nw) {
107: if (childList == old) {
108: nw.next = childList.next;
109: childList = nw;
110: nw.parent = this ;
111: return;
112: }
113: for (Node c = childList;;) {
114: Node next = c.next;
115: if (next == old) {
116: nw.next = next.next;
117: c.next = nw;
118: nw.parent = this ;
119: return;
120: }
121: if (next == null)
122: break;
123: c = next;
124: }
125: throw BindingSupportImpl.getInstance().internal(
126: "no such Node: " + old);
127: }
128:
129: /**
130: * Insert one node (nw) before another (pos).
131: */
132: public void insertChildBefore(Node pos, Node nw) {
133: if (childList == pos) {
134: nw.next = pos;
135: childList = nw;
136: nw.parent = this ;
137: return;
138: }
139: for (Node c = childList;;) {
140: Node next = c.next;
141: if (next == pos) {
142: nw.next = pos;
143: c.next = nw;
144: nw.parent = this ;
145: return;
146: }
147: if (next == null)
148: break;
149: c = next;
150: }
151: throw BindingSupportImpl.getInstance().internal(
152: "no such Node: " + pos);
153: }
154:
155: /**
156: * Simplify this node tree as much as possible.
157: */
158: public final void normalize() {
159: normalizeImp();
160: if (Debug.DEBUG)
161: checkIntegrity();
162: }
163:
164: /**
165: * Simplify this node tree as much as possible.
166: */
167: protected void normalizeImp() {
168: for (Node c = childList; c != null; c = c.next) {
169: c.normalizeImp();
170: }
171: }
172:
173: /**
174: * Abstract method to force all nodes to implement visitor pattern
175: */
176: public abstract Field visit(MemVisitor visitor, Object obj);
177:
178: public Object accept(NodeVisitor visitor, Object[] results) {
179: throw BindingSupportImpl.getInstance().internal(
180: "Not supported for node " + this .getClass().getName());
181: }
182:
183: /**
184: * Implement this in nodes to udpate the ClassMetaData depency of the graph.
185: * This is used for query eviction.
186: *
187: * @param bitSet
188: */
189: public void updateEvictionDependency(CmdBitSet bitSet) {
190: }
191:
192: /**
193: * Check the integrity of this node. This is used during debugging to
194: * check that all the pointers work out. Currently it just makes sure
195: * that all our children list us as their parents.
196: */
197: public void checkIntegrity() {
198: for (Node i = childList; i != null; i = i.next) {
199: if (i.parent != this ) {
200: throw new IllegalStateException(
201: "Bad child node parent reference:\n"
202: + "Parent: " + this + "\n" + "Child: "
203: + i);
204: }
205: }
206: for (Node i = childList; i != null; i = i.next)
207: i.checkIntegrity();
208: }
209:
210: /**
211: * Invoke v's arriveXXX method for the node.
212: */
213: public abstract Object arrive(NodeVisitor v, Object msg);
214:
215: }
|