001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S. Chassande-Barrioz
025: *
026: */package org.objectweb.speedo.query.jdo.parser;
027:
028: import org.objectweb.medor.api.Field;
029: import org.objectweb.medor.api.MedorException;
030: import org.objectweb.medor.query.api.QueryTree;
031: import org.objectweb.speedo.query.lib.SpeedoQueryHelper;
032: import org.objectweb.util.monolog.api.Logger;
033:
034: import java.util.Map;
035: import java.util.Stack;
036: import java.util.StringTokenizer;
037:
038: /**
039: * Base class with visitor utility class and default implementation of
040: * visit methods
041: */
042: public class SpeedoQLAbstractVisitor extends SpeedoQueryHelper
043: implements SpeedoQLVisitor {
044:
045: public final static String[] METHODS_OPERATOR = { "matches", //0
046: "startsWith", //1
047: "endsWith", //2
048: "equals", //3
049: "equalsIgnoreCase", //4
050: "toUpperCase", //5
051: "toLowerCase", //6
052: "length", //7
053: "substring", //8
054: "contains", //9
055: "isEmpty" //10
056: };
057: public final static int MATCHES_OPERATOR = 0;
058: public final static int STARTS_WITH_OPERATOR = 1;
059: public final static int ENDS_WITH_OPERATOR = 2;
060: public final static int EQUALS_OPERATOR = 3;
061: public final static int EQUALS_IGNORE_CASE_OPERATOR = 4;
062: public final static int TO_UPPER_OPERATOR = 5;
063: public final static int TO_LOWER_OPERATOR = 6;
064: public final static int LENGTH_OPERATOR = 7;
065: public final static int SUBSTRING_OPERATOR = 8;
066: public final static int CONTAINS_OPERATOR = 9;
067: public final static int IS_EMPTY_OPERATOR = 10;
068:
069: public final static Byte STR_OPERAND_SUBSTRING = new Byte((byte) 0);
070: public final static Byte BEGIN_OPERAND_SUBSTRING = new Byte(
071: (byte) 1);
072: public final static Byte LENGTH_OPERAND_SUBSTRING = new Byte(
073: (byte) 2);
074:
075: /**
076: * params is an hashtable to store the parameters.
077: * key: name of the parameter
078: * value: a BasicFieldOperand
079: */
080: protected Map params = null;
081:
082: /**
083: * vars is an hashtable to store the variables.
084: * key: name of the variable
085: * value: the PType of the variable (from the declaration)
086: */
087: protected Map vars = null;
088:
089: /**
090: * int value to define the type of the IdValue object
091: * UNDEFINED : in case we don't know (default)
092: * JORM_NAME : jorm name (end point of the recursivity)
093: * NAVIGATION : the object is field to a field ...
094: * CONTAINS_IN : the id is a variable and used in a contains method
095: * CONTAINS_MEMBEROF : the id is a parameter and used in a contains method
096: */
097: public final static int UNDEFINED = 0;
098: public final static int EXTENT = 1;
099: public final static int NAVIGATION = 2;
100: public final static int IN_COLLECTION = 3;
101: public final static int MEMBEROF = 4;
102: public final static int IS_EMPTY = 5;
103: public final static int IS_NOT_EMPTY = 6;
104:
105: public final static String operationToString(int oc) {
106: switch (oc) {
107: case EXTENT:
108: return "EXTENT";
109: case NAVIGATION:
110: return "NAVIGATION";
111: case IN_COLLECTION:
112: return "IN_COLLECTION";
113: case MEMBEROF:
114: return "MEMBEROF";
115: case IS_EMPTY:
116: return "IS_EMPTY";
117: case IS_NOT_EMPTY:
118: return "IS_NOT_EMPTY";
119: case UNDEFINED:
120: default:
121: return "UNDEFINED";
122: }
123: }
124:
125: public String lastName;
126:
127: /**
128: * Runtime Exception used to wrap exceptions thrown in visit methods
129: */
130: protected class VisitorException extends RuntimeException {
131: Exception nestedException;
132:
133: VisitorException(Exception nestedException) {
134: this .nestedException = nestedException;
135: }
136:
137: Exception getNestedException() {
138: return nestedException;
139: }
140: }
141:
142: /**
143: *
144: */
145: protected String[] splitEndPath(String path, String prefix) {
146: String end = path.substring(prefix.length());
147:
148: StringTokenizer st = new StringTokenizer(end, ".");
149: String[] ret = new String[st.countTokens() + 1];
150: ret[0] = prefix;
151: for (int i = 1; i < ret.length; i++) {
152: ret[i] = st.nextToken();
153: }
154: return ret;
155: }
156:
157: protected String getEndString(String total) {
158: return total.substring(total.lastIndexOf('.') + 1, total
159: .length());
160: }
161:
162: /**
163: * return the JormField for a given path
164: * @param path the path of the JormField to return
165: * @param ids the map of (id,QueryTree)pairs;
166: * @throws org.objectweb.speedo.query.parser.ParseException if identification variable not found.
167: * @throws org.objectweb.medor.api.MedorException if corresponding fielc does not exist
168: */
169: protected Field getMedorFieldFromPath(String path, Map ids)
170: throws MedorException, ParseException {
171: String[] paths = splitPath(path);
172: QueryTree qt = (QueryTree) ids.get(paths[0]);
173:
174: if (paths.length > 2)
175: throw new Error("recursive path not implemented: " + path);
176: if (qt == null) {
177: throw new ParseException(
178: "Undeclared identification variable " + paths[0]
179: + " in path " + path);
180: }
181: return qt.getTupleStructure().getField(path);
182: }
183:
184: public String alias2fullname(String alias) {
185: int it = alias.indexOf("this.");
186: if (it == -1)
187: return alias;
188: else {
189: return curClass + "." + alias.substring(5, alias.length());
190: }
191: }
192:
193: public String buildStringwithout(String[] ss, int toforget,
194: String sep) {
195: StringBuffer sb = new StringBuffer();
196: String s = "";
197: for (int i = 0; i < ss.length; i++) {
198: if (i != toforget) {
199: sb.append(s);
200: s = sep;
201: sb.append(ss[i]);
202: }
203: }
204: return sb.toString();
205: }
206:
207: public String withoutThis(String aname) {
208: int it = aname.indexOf("this.");
209: if (it == -1)
210: return aname;
211: else {
212: return aname.substring(5, aname.length());
213: }
214: }
215:
216: public int isMethodOperator(String str) {
217: for (int i = METHODS_OPERATOR.length - 1; i >= 0; i--) {
218: if (METHODS_OPERATOR[i].equals(str)) {
219: return i;
220: }
221: }
222: return -1;
223: }
224:
225: /**
226: * ********************* VISITOR METHODS ***********************************
227: */
228:
229: /**
230: * Visit method to call from constructor.
231: * Child node visitors get a <code>java.util.Stack</code> as data parameter.
232: * @throws java.lang.Exception any nested exception thrown from other visit method
233: */
234: public Object visit(SimpleNode node) throws Exception {
235: return visit(node, new Stack());
236: }
237:
238: /**
239: * Generic visit method that traverses all child nodes
240: */
241: public Object visit(SimpleNode node, Object data) {
242: return node.childrenAccept(this , data);
243: }
244:
245: public Object visit(ASTSpeedoPrimary node, Object data) {
246: return null;
247: }
248:
249: public Object visit(ASTSpeedoQL node, Object data) {
250: return null;
251: }
252:
253: public Object visit(ASTPrimary node, Object data) {
254: return null;
255: }
256:
257: public Object visit(ASTRelationalExpression node, Object data) {
258: return null;
259: }
260:
261: public Object visit(ASTAdditiveExpression node, Object data) {
262: return null;
263: }
264:
265: public Object visit(ASTUnaryExpression node, Object data) {
266: return null;
267: }
268:
269: public Object visit(ASTCastExpression node, Object data) {
270: return null;
271: }
272:
273: public Object visit(ASTArgumentList node, Object data) {
274: return null;
275: }
276:
277: public Object visit(ASTLiteral node, Object data) {
278: return null;
279: }
280:
281: public Object visit(ASTType node, Object data) {
282: return null;
283: }
284:
285: public Object visit(ASTQualifiedName node, Object data) {
286: return null;
287: }
288:
289: /**
290: * ********************* SETTER METHODS ************************************
291: */
292: public void setParams(Map params) {
293: this .params = params;
294: }
295:
296: public void setVars(Map vars) {
297: this .vars = vars;
298: }
299:
300: public void setCurrentClass(String curClass) {
301: this.curClass = curClass;
302: }
303:
304: }
|