1 56 package org.objectstyle.cayenne.exp; 57 58 import java.io.PrintWriter ; 59 import java.io.Reader ; 60 import java.io.Serializable ; 61 import java.io.StringReader ; 62 import java.io.StringWriter ; 63 import java.util.Collection ; 64 import java.util.Collections ; 65 import java.util.Iterator ; 66 import java.util.LinkedList ; 67 import java.util.List ; 68 import java.util.Map ; 69 70 import org.apache.commons.collections.Transformer; 71 import org.objectstyle.cayenne.exp.parser.ExpressionParser; 72 import org.objectstyle.cayenne.exp.parser.ParseException; 73 import org.objectstyle.cayenne.util.ConversionUtil; 74 import org.objectstyle.cayenne.util.Util; 75 import org.objectstyle.cayenne.util.XMLEncoder; 76 import org.objectstyle.cayenne.util.XMLSerializable; 77 78 82 public abstract class Expression implements Serializable , XMLSerializable { 83 84 private final static Object nullValue = new Object (); 85 86 public static final int AND = 0; 87 public static final int OR = 1; 88 public static final int NOT = 2; 89 public static final int EQUAL_TO = 3; 90 public static final int NOT_EQUAL_TO = 4; 91 public static final int LESS_THAN = 5; 92 public static final int GREATER_THAN = 6; 93 public static final int LESS_THAN_EQUAL_TO = 7; 94 public static final int GREATER_THAN_EQUAL_TO = 8; 95 public static final int BETWEEN = 9; 96 public static final int IN = 10; 97 public static final int LIKE = 11; 98 public static final int LIKE_IGNORE_CASE = 12; 99 public static final int EXISTS = 15; 100 public static final int ADD = 16; 101 public static final int SUBTRACT = 17; 102 public static final int MULTIPLY = 18; 103 public static final int DIVIDE = 19; 104 public static final int NEGATIVE = 20; 105 public static final int POSITIVE = 21; 106 107 110 public static final int ALL = 22; 111 112 115 public static final int SOME = 23; 116 117 120 public static final int ANY = 24; 121 122 126 public static final int RAW_SQL = 25; 127 128 141 public static final int OBJ_PATH = 26; 142 143 166 public static final int DB_PATH = 27; 167 168 171 public static final int LIST = 28; 172 173 176 public static final int SUBQUERY = 29; 177 178 181 public static final int COUNT = 30; 182 183 186 public static final int AVG = 31; 187 188 191 public static final int SUM = 32; 192 193 196 public static final int MAX = 33; 197 198 201 public static final int MIN = 34; 202 203 public static final int NOT_BETWEEN = 35; 204 public static final int NOT_IN = 36; 205 public static final int NOT_LIKE = 37; 206 public static final int NOT_LIKE_IGNORE_CASE = 38; 207 208 protected int type; 209 210 217 public static Expression fromString(String expressionString) { 219 if (expressionString == null) { 220 throw new NullPointerException ("Null expression string."); 221 } 222 223 Reader reader = new StringReader (expressionString); 224 try { 225 return new ExpressionParser(reader).expression(); 226 } 227 catch (ParseException ex) { 228 throw new ExpressionException(ex.getMessage(), ex); 229 } 230 catch (Throwable th) { 231 throw new ExpressionException(th.getMessage(), th); 233 } 234 } 235 236 239 public String expName() { 240 switch (type) { 241 case AND : 242 return "AND"; 243 case OR : 244 return "OR"; 245 case NOT : 246 return "NOT"; 247 case EQUAL_TO : 248 return "="; 249 case NOT_EQUAL_TO : 250 return "<>"; 251 case LESS_THAN : 252 return "<"; 253 case LESS_THAN_EQUAL_TO : 254 return "<="; 255 case GREATER_THAN : 256 return ">"; 257 case GREATER_THAN_EQUAL_TO : 258 return ">="; 259 case BETWEEN : 260 return "BETWEEN"; 261 case IN : 262 return "IN"; 263 case LIKE : 264 return "LIKE"; 265 case LIKE_IGNORE_CASE : 266 return "LIKE_IGNORE_CASE"; 267 case EXISTS : 268 return "EXISTS"; 269 case OBJ_PATH : 270 return "OBJ_PATH"; 271 case DB_PATH : 272 return "DB_PATH"; 273 case LIST : 274 return "LIST"; 275 case NOT_BETWEEN : 276 return "NOT BETWEEN"; 277 case NOT_IN : 278 return "NOT IN"; 279 case NOT_LIKE : 280 return "NOT LIKE"; 281 case NOT_LIKE_IGNORE_CASE : 282 return "NOT LIKE IGNORE CASE"; 283 default : 284 return "other"; 285 } 286 } 287 288 public boolean equals(Object object) { 289 if (!(object instanceof Expression)) { 290 return false; 291 } 292 293 Expression e = (Expression) object; 294 295 if (e.getType() != getType() || e.getOperandCount() != getOperandCount()) { 296 return false; 297 } 298 299 int len = e.getOperandCount(); 301 for (int i = 0; i < len; i++) { 302 if (!Util.nullSafeEquals(e.getOperand(i), getOperand(i))) { 303 return false; 304 } 305 } 306 307 return true; 308 } 309 310 314 public int getType() { 315 return type; 316 } 317 318 public void setType(int type) { 319 this.type = type; 320 } 321 322 325 public Expression expWithParameters(Map parameters) { 326 return expWithParameters(parameters, true); 327 } 328 329 349 public Expression expWithParameters( 350 final Map parameters, 351 final boolean pruneMissing) { 352 353 Transformer transformer = new Transformer() { 355 public Object transform(Object object) { 356 if (!(object instanceof ExpressionParameter)) { 357 return object; 358 } 359 360 String name = ((ExpressionParameter) object).getName(); 361 if (!parameters.containsKey(name)) { 362 if (pruneMissing) { 363 return null; 364 } 365 else { 366 throw new ExpressionException( 367 "Missing required parameter: $" + name); 368 } 369 } 370 else { 371 Object value = parameters.get(name); 372 373 return (value != null) 375 ? ExpressionFactory.wrapPathOperand(value) 376 : nullValue; 377 } 378 } 379 }; 380 381 return transform(transformer); 382 } 383 384 390 public Expression joinExp(int type, Expression exp) { 391 Expression join = ExpressionFactory.expressionOfType(type); 392 join.setOperand(0, this); 393 join.setOperand(1, exp); 394 join.flattenTree(); 395 return join; 396 } 397 398 401 public Expression andExp(Expression exp) { 402 return joinExp(Expression.AND, exp); 403 } 404 405 408 public Expression orExp(Expression exp) { 409 return joinExp(Expression.OR, exp); 410 } 411 412 417 public Expression notExp() { 418 Expression exp = ExpressionFactory.expressionOfType(Expression.NOT); 419 exp.setOperand(0, this); 420 return exp; 421 } 422 423 428 public abstract int getOperandCount(); 429 430 434 public abstract Object getOperand(int index); 435 436 440 public abstract void setOperand(int index, Object value); 441 442 448 public Object evaluate(Object o) { 449 return ASTCompiler.compile(this).evaluateASTChain(o); 450 } 451 452 458 public boolean match(Object o) { 459 return ConversionUtil.toBoolean(evaluate(o)); 460 } 461 462 465 public List filterObjects(List objects) { 466 if (objects == null || objects.size() == 0) { 467 return Collections.EMPTY_LIST; 468 } 469 470 return (List ) filter(objects, new LinkedList ()); 471 } 472 473 479 public Collection filter(Collection source, Collection target) { 480 Iterator it = source.iterator(); 481 while (it.hasNext()) { 482 Object o = it.next(); 483 if (match(o)) { 484 target.add(o); 485 } 486 } 487 488 return target; 489 } 490 491 496 public Expression deepCopy() { 497 return transform(null); 498 } 499 500 505 public abstract Expression shallowCopy(); 506 507 513 protected abstract boolean pruneNodeForPrunedChild(Object prunedChild); 514 515 521 protected abstract void flattenTree(); 522 523 530 public void traverse(TraversalHandler visitor) { 531 if (visitor == null) { 532 throw new NullPointerException ("Null Visitor."); 533 } 534 535 traverse(null, visitor); 536 } 537 538 544 protected void traverse(Expression parentExp, TraversalHandler visitor) { 545 546 visitor.startNode(this, parentExp); 547 548 int count = getOperandCount(); 550 for (int i = 0; i < count; i++) { 551 Object child = getOperand(i); 552 553 if (child instanceof Expression) { 554 Expression childExp = (Expression) child; 555 childExp.traverse(this, visitor); 556 } 557 else { 558 visitor.objectNode(child, this); 559 } 560 561 visitor.finishedChild(this, i, i < count - 1); 562 } 563 564 visitor.endNode(this, parentExp); 565 } 566 567 584 public Expression transform(Transformer transformer) { 585 586 Expression copy = shallowCopy(); 587 int count = getOperandCount(); 588 for (int i = 0, j = 0; i < count; i++) { 589 Object operand = getOperand(i); 590 Object transformedChild = operand; 591 592 if (operand instanceof Expression) { 593 transformedChild = ((Expression) operand).transform(transformer); 594 } 595 else if (transformer != null) { 596 transformedChild = transformer.transform(operand); 597 } 598 599 if (transformedChild != null) { 600 Object value = (transformedChild != nullValue) ? transformedChild : null; 601 copy.setOperand(j, value); 602 j++; 603 } 604 else if (pruneNodeForPrunedChild(operand)) { 605 return null; 607 } 608 } 609 610 return (transformer != null) ? (Expression) transformer.transform(copy) : copy; 612 } 613 614 618 public void encodeAsXML(XMLEncoder encoder) { 619 encoder.print("<![CDATA["); 620 encodeAsString(encoder.getPrintWriter()); 621 encoder.print("]]>"); 622 } 623 624 630 public abstract void encodeAsString(PrintWriter pw); 631 632 639 protected void toStringBuffer(StringBuffer buf) { 640 for (int i = 0; i < getOperandCount(); i++) { 641 if (i > 0 || getOperandCount() == 1) { 642 buf.append(" ").append(expName()).append(" "); 643 } 644 645 Object op = getOperand(i); 646 if (op == null) { 647 buf.append("<null>"); 648 } 649 else if (op instanceof String ) { 650 buf.append("'").append(op).append("'"); 651 } 652 else if (op instanceof Expression) { 653 buf.append('('); 654 ((Expression) op).toStringBuffer(buf); 655 buf.append(')'); 656 } 657 else { 658 buf.append(String.valueOf(op)); 659 } 660 } 661 662 } 663 664 public String toString() { 665 StringWriter buffer = new StringWriter (); 666 PrintWriter pw = new PrintWriter (buffer); 667 encodeAsString(pw); 668 pw.close(); 669 buffer.flush(); 670 return buffer.toString(); 671 } 672 } 673 | Popular Tags |