001: /*
002: * Copyright 2002 (C) TJDO.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the TJDO License version 1.0.
006: * See the terms of the TJDO License in the documentation provided with this software.
007: *
008: * $Id: SQLExpression.java,v 1.2 2003/08/11 16:01:52 pierreg0 Exp $
009: */
010:
011: package com.triactive.jdo.store;
012:
013: import java.lang.reflect.InvocationTargetException;
014: import java.lang.reflect.Method;
015: import java.util.Iterator;
016: import java.util.List;
017: import javax.jdo.JDOException;
018: import javax.jdo.JDOUserException;
019:
020: abstract class SQLExpression {
021: protected static class Operator {
022: protected final String sql;
023: protected final int precedence;
024:
025: public Operator(String sql, int precedence) {
026: this .sql = sql;
027: this .precedence = precedence;
028: }
029:
030: public String toString() {
031: return sql;
032: }
033: }
034:
035: protected static class MonadicOperator extends Operator {
036: public MonadicOperator(String sql, int precedence) {
037: super (sql, precedence);
038: }
039:
040: public boolean isHigherThan(Operator op) {
041: if (op == null)
042: return false;
043: else
044: return precedence > op.precedence;
045: }
046: }
047:
048: protected static class DyadicOperator extends Operator {
049: private final boolean isAssociative;
050:
051: public DyadicOperator(String sql, int precedence,
052: boolean isAssociative) {
053: super (" " + sql + " ", precedence);
054: this .isAssociative = isAssociative;
055: }
056:
057: public boolean isHigherThanLeftSide(Operator op) {
058: if (op == null)
059: return false;
060: else
061: return precedence > op.precedence;
062: }
063:
064: public boolean isHigherThanRightSide(Operator op) {
065: if (op == null)
066: return false;
067: else if (precedence == op.precedence)
068: return !isAssociative;
069: else
070: return precedence > op.precedence;
071: }
072: }
073:
074: protected static final DyadicOperator OP_OR = new DyadicOperator(
075: "OR", 0, true);
076: protected static final DyadicOperator OP_AND = new DyadicOperator(
077: "AND", 1, true);
078: protected static final MonadicOperator OP_NOT = new MonadicOperator(
079: "NOT ", 2);
080: protected static final DyadicOperator OP_EQ = new DyadicOperator(
081: "=", 3, false);
082: protected static final DyadicOperator OP_NOTEQ = new DyadicOperator(
083: "<>", 3, false);
084: protected static final DyadicOperator OP_LT = new DyadicOperator(
085: "<", 3, false);
086: protected static final DyadicOperator OP_LTEQ = new DyadicOperator(
087: "<=", 3, false);
088: protected static final DyadicOperator OP_GT = new DyadicOperator(
089: ">", 3, false);
090: protected static final DyadicOperator OP_GTEQ = new DyadicOperator(
091: ">=", 3, false);
092: protected static final DyadicOperator OP_LIKE = new DyadicOperator(
093: "LIKE", 3, false);
094: protected static final DyadicOperator OP_BETWEEN = new DyadicOperator(
095: "BETWEEN", 3, false);
096: protected static final DyadicOperator OP_IS = new DyadicOperator(
097: "IS", 3, false);
098: protected static final DyadicOperator OP_ISNOT = new DyadicOperator(
099: "IS NOT", 3, false);
100: protected static final DyadicOperator OP_IN = new DyadicOperator(
101: "IN", 3, false);
102: protected static final DyadicOperator OP_ADD = new DyadicOperator(
103: "+", 4, true);
104: protected static final DyadicOperator OP_SUB = new DyadicOperator(
105: "-", 4, false);
106: protected static final DyadicOperator OP_CONCAT = new DyadicOperator(
107: "||", 4, true);
108: protected static final DyadicOperator OP_MUL = new DyadicOperator(
109: "*", 5, true);
110: protected static final DyadicOperator OP_DIV = new DyadicOperator(
111: "/", 5, false);
112: protected static final MonadicOperator OP_NEG = new MonadicOperator(
113: "-", 6);
114:
115: protected final QueryStatement qs;
116: protected final StatementText st = new StatementText();
117: protected Operator lowestOperator = null;
118:
119: protected SQLExpression(QueryStatement qs) {
120: this .qs = qs;
121: }
122:
123: protected SQLExpression(QueryStatement qs,
124: QueryStatement.QueryColumn qsc) {
125: this (qs);
126: st.append(qsc);
127: }
128:
129: protected SQLExpression(String functionName, List args) {
130: st.append(functionName).append('(');
131:
132: Iterator i = args.iterator();
133: SQLExpression arg = (SQLExpression) i.next();
134: st.append(arg);
135: qs = arg.qs;
136:
137: while (i.hasNext()) {
138: arg = (SQLExpression) i.next();
139: st.append(',').append(arg);
140: }
141:
142: st.append(')');
143: }
144:
145: protected SQLExpression(MonadicOperator op, SQLExpression operand) {
146: st.append(op);
147:
148: if (op.isHigherThan(operand.lowestOperator))
149: st.append('(').append(operand).append(')');
150: else
151: st.append(operand);
152:
153: qs = operand.qs;
154: lowestOperator = op;
155: }
156:
157: protected SQLExpression(SQLExpression operand1, DyadicOperator op,
158: SQLExpression operand2) {
159: if (op.isHigherThanLeftSide(operand1.lowestOperator))
160: st.append('(').append(operand1).append(')');
161: else
162: st.append(operand1);
163:
164: st.append(op);
165:
166: if (op.isHigherThanRightSide(operand2.lowestOperator))
167: st.append('(').append(operand2).append(')');
168: else
169: st.append(operand2);
170:
171: qs = operand1.qs;
172: lowestOperator = op;
173: }
174:
175: public QueryStatement getQueryStatement() {
176: return qs;
177: }
178:
179: public BooleanExpression and(SQLExpression expr) {
180: throw new IllegalOperationException(this , "&&", expr);
181: }
182:
183: public BooleanExpression eor(SQLExpression expr) {
184: throw new IllegalOperationException(this , "^", expr);
185: }
186:
187: public BooleanExpression ior(SQLExpression expr) {
188: throw new IllegalOperationException(this , "||", expr);
189: }
190:
191: public BooleanExpression not() {
192: throw new IllegalOperationException("!", this );
193: }
194:
195: public BooleanExpression eq(SQLExpression expr) {
196: throw new IllegalOperationException(this , "==", expr);
197: }
198:
199: public BooleanExpression noteq(SQLExpression expr) {
200: throw new IllegalOperationException(this , "!=", expr);
201: }
202:
203: public BooleanExpression lt(SQLExpression expr) {
204: throw new IllegalOperationException(this , "<", expr);
205: }
206:
207: public BooleanExpression lteq(SQLExpression expr) {
208: throw new IllegalOperationException(this , "<=", expr);
209: }
210:
211: public BooleanExpression gt(SQLExpression expr) {
212: throw new IllegalOperationException(this , ">", expr);
213: }
214:
215: public BooleanExpression gteq(SQLExpression expr) {
216: throw new IllegalOperationException(this , ">=", expr);
217: }
218:
219: public BooleanExpression in(SQLExpression expr) {
220: throw new IllegalOperationException(this , "in", expr);
221: }
222:
223: public SQLExpression add(SQLExpression expr) {
224: throw new IllegalOperationException(this , "+", expr);
225: }
226:
227: public SQLExpression sub(SQLExpression expr) {
228: throw new IllegalOperationException(this , "-", expr);
229: }
230:
231: public SQLExpression mul(SQLExpression expr) {
232: throw new IllegalOperationException(this , "*", expr);
233: }
234:
235: public SQLExpression div(SQLExpression expr) {
236: throw new IllegalOperationException(this , "/", expr);
237: }
238:
239: public SQLExpression mod(SQLExpression expr) {
240: throw new IllegalOperationException(this , "%", expr);
241: }
242:
243: public SQLExpression neg() {
244: throw new IllegalOperationException("-", this );
245: }
246:
247: public SQLExpression com() {
248: throw new IllegalOperationException("~", this );
249: }
250:
251: public SQLExpression cast(Class type) {
252: throw new IllegalOperationException(
253: "cast to " + type.getName(), this );
254: }
255:
256: public SQLExpression accessField(String fieldName) {
257: throw new IllegalOperationException(
258: "access field " + fieldName, this );
259: }
260:
261: /*
262: * This can be enlarged as needed, but for the present there are no methods
263: * accepting more than two arguments.
264: */
265:
266: private static final Class[][] paramTypeSignatures = { null,
267: new Class[] { SQLExpression.class },
268: new Class[] { SQLExpression.class, SQLExpression.class } };
269:
270: public SQLExpression callMethod(String methodName, List arguments) {
271: SQLExpression expr;
272:
273: try {
274: int numArgs = arguments.size();
275:
276: if (numArgs >= paramTypeSignatures.length)
277: throw new NoSuchMethodException(methodName
278: + typeList(arguments));
279:
280: Method m = getClass().getMethod(methodName + "Method",
281: paramTypeSignatures[numArgs]);
282:
283: expr = (SQLExpression) m.invoke(this , arguments.toArray());
284: } catch (InvocationTargetException e) {
285: Throwable t = e.getTargetException();
286:
287: if (t instanceof Error)
288: throw (Error) t;
289: if (t instanceof JDOException)
290: throw (JDOException) t;
291: else
292: throw new MethodInvocationException(methodName,
293: arguments, t);
294: } catch (Exception e) {
295: throw new MethodInvocationException(methodName, arguments,
296: e);
297: }
298:
299: return expr;
300: }
301:
302: public StatementText toStatementText() {
303: return st;
304: }
305:
306: public String toString() {
307: String value;
308:
309: try {
310: value = " \"" + toStatementText().toString() + '"';
311: } catch (JDOException e) {
312: value = "";
313: }
314:
315: String className = getClass().getName();
316:
317: return className.substring(className.lastIndexOf('.') + 1)
318: + value;
319: }
320:
321: public static String typeList(List exprs) {
322: StringBuffer s = new StringBuffer("(");
323: Iterator i = exprs.iterator();
324:
325: while (i.hasNext())
326: s.append(i.next()).append(i.hasNext() ? ',' : ')');
327:
328: return s.toString();
329: }
330:
331: public static class IllegalArgumentTypeException extends
332: IllegalArgumentException {
333: public IllegalArgumentTypeException(SQLExpression arg) {
334: super ("Illegal argument type: " + arg);
335: }
336: }
337:
338: public static class MethodInvocationException extends
339: JDOUserException {
340: public MethodInvocationException(String methodName,
341: List arguments, Throwable t) {
342: super ("Exception occurred invoking method " + methodName
343: + typeList(arguments), t);
344: }
345: }
346:
347: public static class IllegalOperationException extends
348: JDOUserException {
349: public IllegalOperationException(String operation,
350: SQLExpression operand) {
351: super ("Cannot perform operation \"" + operation + "\" on "
352: + operand);
353: }
354:
355: public IllegalOperationException(SQLExpression operand1,
356: String operation, SQLExpression operand2) {
357: super ("Cannot perform operation \"" + operation + "\" on "
358: + operand1 + " and " + operand2);
359: }
360: }
361: }
|