1 10 11 package com.triactive.jdo.store; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.lang.reflect.Method ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import javax.jdo.JDOException; 18 import javax.jdo.JDOUserException; 19 20 21 abstract class SQLExpression 22 { 23 protected static class Operator 24 { 25 protected final String sql; 26 protected final int precedence; 27 28 public Operator(String sql, int precedence) 29 { 30 this.sql = sql; 31 this.precedence = precedence; 32 } 33 34 public String toString() 35 { 36 return sql; 37 } 38 } 39 40 protected static class MonadicOperator extends Operator 41 { 42 public MonadicOperator(String sql, int precedence) 43 { 44 super(sql, precedence); 45 } 46 47 public boolean isHigherThan(Operator op) 48 { 49 if (op == null) 50 return false; 51 else 52 return precedence > op.precedence; 53 } 54 } 55 56 protected static class DyadicOperator extends Operator 57 { 58 private final boolean isAssociative; 59 60 public DyadicOperator(String sql, int precedence, boolean isAssociative) 61 { 62 super(" " + sql + " ", precedence); 63 this.isAssociative = isAssociative; 64 } 65 66 public boolean isHigherThanLeftSide(Operator op) 67 { 68 if (op == null) 69 return false; 70 else 71 return precedence > op.precedence; 72 } 73 74 public boolean isHigherThanRightSide(Operator op) 75 { 76 if (op == null) 77 return false; 78 else if (precedence == op.precedence) 79 return !isAssociative; 80 else 81 return precedence > op.precedence; 82 } 83 } 84 85 protected static final DyadicOperator OP_OR = new DyadicOperator ("OR", 0, true); 86 protected static final DyadicOperator OP_AND = new DyadicOperator ("AND", 1, true); 87 protected static final MonadicOperator OP_NOT = new MonadicOperator("NOT ", 2); 88 protected static final DyadicOperator OP_EQ = new DyadicOperator ("=", 3, false); 89 protected static final DyadicOperator OP_NOTEQ = new DyadicOperator ("<>", 3, false); 90 protected static final DyadicOperator OP_LT = new DyadicOperator ("<", 3, false); 91 protected static final DyadicOperator OP_LTEQ = new DyadicOperator ("<=", 3, false); 92 protected static final DyadicOperator OP_GT = new DyadicOperator (">", 3, false); 93 protected static final DyadicOperator OP_GTEQ = new DyadicOperator (">=", 3, false); 94 protected static final DyadicOperator OP_LIKE = new DyadicOperator ("LIKE", 3, false); 95 protected static final DyadicOperator OP_BETWEEN = new DyadicOperator ("BETWEEN",3, false); 96 protected static final DyadicOperator OP_IS = new DyadicOperator ("IS", 3, false); 97 protected static final DyadicOperator OP_ISNOT = new DyadicOperator ("IS NOT", 3, false); 98 protected static final DyadicOperator OP_IN = new DyadicOperator ("IN" , 3, false); 99 protected static final DyadicOperator OP_ADD = new DyadicOperator ("+", 4, true); 100 protected static final DyadicOperator OP_SUB = new DyadicOperator ("-", 4, false); 101 protected static final DyadicOperator OP_CONCAT = new DyadicOperator ("||", 4, true); 102 protected static final DyadicOperator OP_MUL = new DyadicOperator ("*", 5, true); 103 protected static final DyadicOperator OP_DIV = new DyadicOperator ("/", 5, false); 104 protected static final MonadicOperator OP_NEG = new MonadicOperator("-", 6); 105 106 protected final QueryStatement qs; 107 protected final StatementText st = new StatementText(); 108 protected Operator lowestOperator = null; 109 110 111 protected SQLExpression(QueryStatement qs) 112 { 113 this.qs = qs; 114 } 115 116 protected SQLExpression(QueryStatement qs, QueryStatement.QueryColumn qsc) 117 { 118 this(qs); 119 st.append(qsc); 120 } 121 122 protected SQLExpression(String functionName, List args) 123 { 124 st.append(functionName).append('('); 125 126 Iterator i = args.iterator(); 127 SQLExpression arg = (SQLExpression)i.next(); 128 st.append(arg); 129 qs = arg.qs; 130 131 while (i.hasNext()) 132 { 133 arg = (SQLExpression)i.next(); 134 st.append(',').append(arg); 135 } 136 137 st.append(')'); 138 } 139 140 protected SQLExpression(MonadicOperator op, SQLExpression operand) 141 { 142 st.append(op); 143 144 if (op.isHigherThan(operand.lowestOperator)) 145 st.append('(').append(operand).append(')'); 146 else 147 st.append(operand); 148 149 qs = operand.qs; 150 lowestOperator = op; 151 } 152 153 protected SQLExpression(SQLExpression operand1, DyadicOperator op, SQLExpression operand2) 154 { 155 if (op.isHigherThanLeftSide(operand1.lowestOperator)) 156 st.append('(').append(operand1).append(')'); 157 else 158 st.append(operand1); 159 160 st.append(op); 161 162 if (op.isHigherThanRightSide(operand2.lowestOperator)) 163 st.append('(').append(operand2).append(')'); 164 else 165 st.append(operand2); 166 167 qs = operand1.qs; 168 lowestOperator = op; 169 } 170 171 public QueryStatement getQueryStatement() 172 { 173 return qs; 174 } 175 176 public BooleanExpression and(SQLExpression expr) 177 { 178 throw new IllegalOperationException(this, "&&", expr); 179 } 180 181 public BooleanExpression eor(SQLExpression expr) 182 { 183 throw new IllegalOperationException(this, "^", expr); 184 } 185 186 public BooleanExpression ior(SQLExpression expr) 187 { 188 throw new IllegalOperationException(this, "||", expr); 189 } 190 191 public BooleanExpression not() 192 { 193 throw new IllegalOperationException("!", this); 194 } 195 196 public BooleanExpression eq(SQLExpression expr) 197 { 198 throw new IllegalOperationException(this, "==", expr); 199 } 200 201 public BooleanExpression noteq(SQLExpression expr) 202 { 203 throw new IllegalOperationException(this, "!=", expr); 204 } 205 206 public BooleanExpression lt(SQLExpression expr) 207 { 208 throw new IllegalOperationException(this, "<", expr); 209 } 210 211 public BooleanExpression lteq(SQLExpression expr) 212 { 213 throw new IllegalOperationException(this, "<=", expr); 214 } 215 216 public BooleanExpression gt(SQLExpression expr) 217 { 218 throw new IllegalOperationException(this, ">", expr); 219 } 220 221 public BooleanExpression gteq(SQLExpression expr) 222 { 223 throw new IllegalOperationException(this, ">=", expr); 224 } 225 226 public BooleanExpression in(SQLExpression expr) 227 { 228 throw new IllegalOperationException(this, "in", expr); 229 } 230 231 public SQLExpression add(SQLExpression expr) 232 { 233 throw new IllegalOperationException(this, "+", expr); 234 } 235 236 public SQLExpression sub(SQLExpression expr) 237 { 238 throw new IllegalOperationException(this, "-", expr); 239 } 240 241 public SQLExpression mul(SQLExpression expr) 242 { 243 throw new IllegalOperationException(this, "*", expr); 244 } 245 246 public SQLExpression div(SQLExpression expr) 247 { 248 throw new IllegalOperationException(this, "/", expr); 249 } 250 251 public SQLExpression mod(SQLExpression expr) 252 { 253 throw new IllegalOperationException(this, "%", expr); 254 } 255 256 public SQLExpression neg() 257 { 258 throw new IllegalOperationException("-", this); 259 } 260 261 public SQLExpression com() 262 { 263 throw new IllegalOperationException("~", this); 264 } 265 266 public SQLExpression cast(Class type) 267 { 268 throw new IllegalOperationException("cast to " + type.getName(), this); 269 } 270 271 public SQLExpression accessField(String fieldName) 272 { 273 throw new IllegalOperationException("access field " + fieldName, this); 274 } 275 276 280 281 private static final Class [][] paramTypeSignatures = 282 { 283 null, 284 new Class [] { SQLExpression.class }, 285 new Class [] { SQLExpression.class, SQLExpression.class } 286 }; 287 288 public SQLExpression callMethod(String methodName, List arguments) 289 { 290 SQLExpression expr; 291 292 try 293 { 294 int numArgs = arguments.size(); 295 296 if (numArgs >= paramTypeSignatures.length) 297 throw new NoSuchMethodException (methodName + typeList(arguments)); 298 299 Method m = getClass().getMethod(methodName + "Method", paramTypeSignatures[numArgs]); 300 301 expr = (SQLExpression)m.invoke(this, arguments.toArray()); 302 } 303 catch (InvocationTargetException e) 304 { 305 Throwable t = e.getTargetException(); 306 307 if (t instanceof Error ) 308 throw (Error )t; 309 if (t instanceof JDOException) 310 throw (JDOException)t; 311 else 312 throw new MethodInvocationException(methodName, arguments, t); 313 } 314 catch (Exception e) 315 { 316 throw new MethodInvocationException(methodName, arguments, e); 317 } 318 319 return expr; 320 } 321 322 public StatementText toStatementText() 323 { 324 return st; 325 } 326 327 public String toString() 328 { 329 String value; 330 331 try 332 { 333 value = " \"" + toStatementText().toString() + '"'; 334 } 335 catch (JDOException e) 336 { 337 value = ""; 338 } 339 340 String className = getClass().getName(); 341 342 return className.substring(className.lastIndexOf('.') + 1) + value; 343 } 344 345 public static String typeList(List exprs) 346 { 347 StringBuffer s = new StringBuffer ("("); 348 Iterator i = exprs.iterator(); 349 350 while (i.hasNext()) 351 s.append(i.next()).append(i.hasNext() ? ',' : ')'); 352 353 return s.toString(); 354 } 355 356 public static class IllegalArgumentTypeException extends IllegalArgumentException 357 { 358 public IllegalArgumentTypeException(SQLExpression arg) 359 { 360 super("Illegal argument type: " + arg); 361 } 362 } 363 364 public static class MethodInvocationException extends JDOUserException 365 { 366 public MethodInvocationException(String methodName, List arguments, Throwable t) 367 { 368 super("Exception occurred invoking method " + methodName + typeList(arguments), t); 369 } 370 } 371 372 public static class IllegalOperationException extends JDOUserException 373 { 374 public IllegalOperationException(String operation, SQLExpression operand) 375 { 376 super("Cannot perform operation \"" + operation + "\" on " + operand); 377 } 378 379 public IllegalOperationException(SQLExpression operand1, String operation, SQLExpression operand2) 380 { 381 super("Cannot perform operation \"" + operation + "\" on " + operand1 + " and " + operand2); 382 } 383 } 384 } 385 | Popular Tags |