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.ejb.query;
012:
013: import com.versant.core.metadata.FieldMetaData;
014: import com.versant.core.metadata.ClassMetaData;
015:
016: /**
017: * Dot separated list of identifiers.
018: */
019: public class PathNode extends Node {
020:
021: public static final int WHERE = 1;
022: public static final int SELECT = 2;
023: public static final int GROUP_BY = 3;
024: public static final int ORDER_BY = 4;
025: public static final int AGGREGATE = 5;
026: public static final int CONSTRUCTOR = 6;
027: public static final int JOIN = 7;
028: public static final int COLLECTION_MEMBER = 8;
029:
030: private String[] list = new String[4];
031: private int size;
032: private int parentType;
033:
034: private NavBase navBase;
035: private FieldMetaData fmd;
036:
037: /**
038: * Create with given parent type (SELECT, GROUP_BY etc).
039: */
040: public PathNode(int parentType) {
041: this .parentType = parentType;
042: }
043:
044: /**
045: * Is this node under a SELECT, GROUP_BY etc.
046: */
047: public int getParentType() {
048: return parentType;
049: }
050:
051: public void add(String identifier) {
052: if (size == list.length) {
053: String[] a = new String[list.length + 4];
054: System.arraycopy(list, 0, a, 0, list.length);
055: list = a;
056: }
057: list[size++] = identifier;
058: }
059:
060: public String get(int i) {
061: if (i >= size) {
062: throw new ArrayIndexOutOfBoundsException(i + " >= " + size);
063: }
064: return list[i];
065: }
066:
067: public int size() {
068: return size;
069: }
070:
071: public Object arrive(NodeVisitor v, Object msg) {
072: return v.arrivePathNode(this , msg);
073: }
074:
075: public String getParentTypeString() {
076: switch (parentType) {
077: case WHERE:
078: return "WHERE";
079: case SELECT:
080: return "SELECT";
081: case GROUP_BY:
082: return "GROUP_BY";
083: case ORDER_BY:
084: return "ORDER_BY";
085: case AGGREGATE:
086: return "AGGREGATE";
087: case CONSTRUCTOR:
088: return "CONSTRUCTOR";
089: case JOIN:
090: return "JOIN";
091: case COLLECTION_MEMBER:
092: return "COLLECTION_MEMBER";
093: }
094: return "<? parentType " + parentType + " ?>";
095: }
096:
097: public String toStringImp() {
098: if (size == 0) {
099: return "<? no identifiers in PathExpression?>";
100: }
101: StringBuffer s = new StringBuffer();
102: s.append(list[0]);
103: for (int i = 1; i < size; i++) {
104: s.append('.');
105: s.append(list[i]);
106: }
107: if (fmd != null) {
108: s.append('%');
109: s.append(fmd.getQName());
110: } else if (navBase != null) {
111: s.append('%');
112: s.append(navBase.getNavClassMetaData().qname);
113: }
114: return s.toString();
115: }
116:
117: /**
118: * Get the identification variable or last field navigated to get to our
119: * field. If getFmd() is null then we have no simple field and this path is
120: * returning the identification variable or object field on its own.
121: */
122: public NavBase getNavBase() {
123: return navBase;
124: }
125:
126: /**
127: * If this path ends in a field then this is it. It will be a field
128: * of getNavBase().getNavClassMetaData().
129: */
130: public FieldMetaData getFmd() {
131: return fmd;
132: }
133:
134: public void resolve(ResolveContext rc) {
135: if (size == 1) { // identification var on its own
136: String name = get(0);
137: navBase = rc.checkIdVarExists(name, this );
138: } else { // field value
139: navBase = rc.resolveJoinPath(this , false, false, size - 1);
140: ClassMetaData cmd = navBase.getNavClassMetaData();
141: String name = get(size - 1);
142: fmd = cmd.getFieldMetaData(name);
143: if (fmd == null) {
144: throw rc.createUserException("No such field '" + name
145: + "' on " + cmd.qname, this);
146: }
147: }
148: }
149:
150: }
|