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.FieldMetaData;
014: import com.versant.core.metadata.ClassMetaData;
015: import com.versant.core.common.Debug;
016:
017: import com.versant.core.common.BindingSupportImpl;
018:
019: /**
020: * This node is created when the value of a field is required as part
021: * of an expression.
022: */
023: public class FieldNode extends LeafNode {
024:
025: public String lexeme;
026: /**
027: * The field whose value is required.
028: */
029: public FieldMetaData fmd;
030: /**
031: * If true then the field is on the candidate instance being tested
032: * (e.g. this.field).
033: */
034: public boolean useCandidateExtent;
035:
036: public boolean resolved;
037:
038: public FieldNode() {
039: }
040:
041: public FieldNode(Node parent, String lexeme) {
042: this .parent = parent;
043: this .lexeme = lexeme;
044: }
045:
046: public Object accept(NodeVisitor visitor, Object[] results) {
047: return visitor.visitFieldNode(this , results);
048: }
049:
050: public String toString() {
051: return super .toString() + " "
052: + (fmd != null ? fmd.toString() : lexeme) + " asValue "
053: + asValue;
054: }
055:
056: /**
057: * Resolve field refs and so on relative to the compiler. This must
058: * recursively resolve any child nodes.
059: */
060: public void resolve(QueryParser comp, ClassMetaData cmd,
061: boolean ordering) {
062: if (Debug.DEBUG)
063: System.out.println("### FieldNode.resolve " + this );
064: final boolean fnn = parent instanceof FieldNavNode;
065: if (!ordering) {
066: if (!resolved && !fnn) {
067: VarNode v = comp.findVar(lexeme);
068: Node rep;
069: if (v != null) {
070: // if we are the first child of a MethodNode (i.e. the
071: // instance the method is being invoked on) and have not
072: // been bound then we are an unbound variable
073: if (!v.bound
074: && ((parent instanceof BinaryNode) || (parent instanceof MethodNode && parent.childList == this ))) {
075: v.insertVarBindingNode(parent);
076: } else {
077: v.bound = true;
078: if (Debug.DEBUG) {
079: System.out.println("### bound " + this );
080: }
081: }
082: if (v.parent != null)
083: rep = new VarNodeProxy(v);
084: else
085: rep = v;
086: } else {
087: rep = v;
088: }
089: if (rep == null) {
090: ParamNode p = comp.findParam(lexeme);
091: if (p != null && p.parent != null)
092: rep = new ParamNodeProxy(p);
093: else
094: rep = p;
095: }
096: if (rep == null && lexeme.equals("this")) {
097: rep = new ReservedFieldNode(
098: ReservedFieldNode.TYPE_THIS, "this");
099: rep.resolve(comp, cmd, false);
100: }
101: if (rep != null) {
102: parent.replaceChild(this , rep);
103: return;
104: }
105: }
106: }
107:
108: fmd = cmd.getFieldMetaData(lexeme);
109:
110: if (fmd == null) {
111: if (parent instanceof FieldNavNode) {
112: FieldNavNode fNN = (FieldNavNode) parent;
113: if (fNN.embedded) {
114: FieldMetaData[] fmds = cmd.fields;
115: for (int i = 0; i < fmds.length; i++) {
116: FieldMetaData fieldMetaData = fmds[i];
117: if (fieldMetaData.name.equals(fNN.fmd.name
118: + "/" + lexeme)) {
119: fmd = fieldMetaData;
120: break;
121: }
122: }
123: }
124: }
125: }
126:
127: if (fmd == null) {
128: //assume that this is an aliased column name
129: parent.replaceChild(this , new AsValueNode(lexeme));
130: return;
131: }
132: if (fmd == null) {
133: String msg;
134: if (fnn) {
135: msg = "Field '" + lexeme + "' not found on "
136: + cmd.qname;
137: } else {
138: msg = "Identifier '" + lexeme
139: + "' is not a parameter, "
140: + "variable or field of " + cmd.qname;
141: }
142: throw BindingSupportImpl.getInstance().runtime(msg);
143: }
144:
145: /**
146: * Update the cmd for multi-Table inheritance
147: */
148: if (fmd.classMetaData != cmd) {
149: cmd = fmd.classMetaData;
150: }
151: }
152:
153: public Field visit(MemVisitor visitor, Object obj) {
154: return visitor.visitFieldNode(this , obj);
155: }
156:
157: public Object arrive(NodeVisitor v, Object msg) {
158: return v.arriveFieldNode(this, msg);
159: }
160:
161: }
|