1 19 20 package org.apache.cayenne.exp; 21 22 import java.io.PrintWriter ; 23 import java.io.Reader ; 24 import java.io.Serializable ; 25 import java.io.StringReader ; 26 import java.io.StringWriter ; 27 import java.util.Collection ; 28 import java.util.Collections ; 29 import java.util.Iterator ; 30 import java.util.LinkedList ; 31 import java.util.List ; 32 import java.util.Map ; 33 34 import org.apache.commons.collections.Transformer; 35 import org.apache.cayenne.exp.parser.ExpressionParser; 36 import org.apache.cayenne.exp.parser.ParseException; 37 import org.apache.cayenne.util.ConversionUtil; 38 import org.apache.cayenne.util.Util; 39 import org.apache.cayenne.util.XMLEncoder; 40 import org.apache.cayenne.util.XMLSerializable; 41 42 45 public abstract class Expression implements Serializable , XMLSerializable { 46 47 53 public final static Object PRUNED_NODE = new Object (); 54 55 public static final int AND = 0; 56 public static final int OR = 1; 57 public static final int NOT = 2; 58 public static final int EQUAL_TO = 3; 59 public static final int NOT_EQUAL_TO = 4; 60 public static final int LESS_THAN = 5; 61 public static final int GREATER_THAN = 6; 62 public static final int LESS_THAN_EQUAL_TO = 7; 63 public static final int GREATER_THAN_EQUAL_TO = 8; 64 public static final int BETWEEN = 9; 65 public static final int IN = 10; 66 public static final int LIKE = 11; 67 public static final int LIKE_IGNORE_CASE = 12; 68 public static final int ADD = 16; 69 public static final int SUBTRACT = 17; 70 public static final int MULTIPLY = 18; 71 public static final int DIVIDE = 19; 72 public static final int NEGATIVE = 20; 73 public static final int TRUE = 21; 74 public static final int FALSE = 22; 75 76 91 public static final int OBJ_PATH = 26; 92 93 108 public static final int DB_PATH = 27; 109 110 113 public static final int LIST = 28; 114 115 public static final int NOT_BETWEEN = 35; 116 public static final int NOT_IN = 36; 117 public static final int NOT_LIKE = 37; 118 public static final int NOT_LIKE_IGNORE_CASE = 38; 119 120 protected int type; 121 122 128 public static Expression fromString(String expressionString) { 130 if (expressionString == null) { 131 throw new NullPointerException ("Null expression string."); 132 } 133 134 Reader reader = new StringReader (expressionString); 135 try { 136 return new ExpressionParser(reader).expression(); 137 } 138 catch (ParseException ex) { 139 throw new ExpressionException(ex.getMessage(), ex); 140 } 141 catch (Throwable th) { 142 throw new ExpressionException(th.getMessage(), th); 144 } 145 } 146 147 150 public String expName() { 151 switch (type) { 152 case AND: 153 return "AND"; 154 case OR: 155 return "OR"; 156 case NOT: 157 return "NOT"; 158 case EQUAL_TO: 159 return "="; 160 case NOT_EQUAL_TO: 161 return "<>"; 162 case LESS_THAN: 163 return "<"; 164 case LESS_THAN_EQUAL_TO: 165 return "<="; 166 case GREATER_THAN: 167 return ">"; 168 case GREATER_THAN_EQUAL_TO: 169 return ">="; 170 case BETWEEN: 171 return "BETWEEN"; 172 case IN: 173 return "IN"; 174 case LIKE: 175 return "LIKE"; 176 case LIKE_IGNORE_CASE: 177 return "LIKE_IGNORE_CASE"; 178 case OBJ_PATH: 179 return "OBJ_PATH"; 180 case DB_PATH: 181 return "DB_PATH"; 182 case LIST: 183 return "LIST"; 184 case NOT_BETWEEN: 185 return "NOT BETWEEN"; 186 case NOT_IN: 187 return "NOT IN"; 188 case NOT_LIKE: 189 return "NOT LIKE"; 190 case NOT_LIKE_IGNORE_CASE: 191 return "NOT LIKE IGNORE CASE"; 192 default: 193 return "other"; 194 } 195 } 196 197 public boolean equals(Object object) { 198 if (!(object instanceof Expression)) { 199 return false; 200 } 201 202 Expression e = (Expression) object; 203 204 if (e.getType() != getType() || e.getOperandCount() != getOperandCount()) { 205 return false; 206 } 207 208 int len = e.getOperandCount(); 210 for (int i = 0; i < len; i++) { 211 if (!Util.nullSafeEquals(e.getOperand(i), getOperand(i))) { 212 return false; 213 } 214 } 215 216 return true; 217 } 218 219 223 public int getType() { 224 return type; 225 } 226 227 public void setType(int type) { 228 this.type = type; 229 } 230 231 234 public Expression expWithParameters(Map parameters) { 235 return expWithParameters(parameters, true); 236 } 237 238 256 public Expression expWithParameters(final Map parameters, final boolean pruneMissing) { 257 258 Transformer transformer = new Transformer() { 260 261 public Object transform(Object object) { 262 if (!(object instanceof ExpressionParameter)) { 263 return object; 264 } 265 266 String name = ((ExpressionParameter) object).getName(); 267 if (!parameters.containsKey(name)) { 268 if (pruneMissing) { 269 return PRUNED_NODE; 270 } 271 else { 272 throw new ExpressionException("Missing required parameter: $" 273 + name); 274 } 275 } 276 else { 277 Object value = parameters.get(name); 278 279 return (value != null) 281 ? ExpressionFactory.wrapPathOperand(value) 282 : null; 283 } 284 } 285 }; 286 287 return transform(transformer); 288 } 289 290 295 public Expression joinExp(int type, Expression exp) { 296 Expression join = ExpressionFactory.expressionOfType(type); 297 join.setOperand(0, this); 298 join.setOperand(1, exp); 299 join.flattenTree(); 300 return join; 301 } 302 303 306 public Expression andExp(Expression exp) { 307 return joinExp(Expression.AND, exp); 308 } 309 310 313 public Expression orExp(Expression exp) { 314 return joinExp(Expression.OR, exp); 315 } 316 317 322 public abstract Expression notExp(); 323 324 328 public abstract int getOperandCount(); 329 330 333 public abstract Object getOperand(int index); 334 335 338 public abstract void setOperand(int index, Object value); 339 340 345 public abstract Object evaluate(Object o); 346 347 352 public boolean match(Object o) { 353 return ConversionUtil.toBoolean(evaluate(o)); 354 } 355 356 359 public List filterObjects(List objects) { 360 if (objects == null || objects.size() == 0) { 361 return Collections.EMPTY_LIST; 362 } 363 364 return (List ) filter(objects, new LinkedList ()); 365 } 366 367 373 public Collection filter(Collection source, Collection target) { 374 Iterator it = source.iterator(); 375 while (it.hasNext()) { 376 Object o = it.next(); 377 if (match(o)) { 378 target.add(o); 379 } 380 } 381 382 return target; 383 } 384 385 390 public Expression deepCopy() { 391 return transform(null); 392 } 393 394 399 public abstract Expression shallowCopy(); 400 401 407 protected abstract boolean pruneNodeForPrunedChild(Object prunedChild); 408 409 415 protected abstract void flattenTree(); 416 417 424 public void traverse(TraversalHandler visitor) { 425 if (visitor == null) { 426 throw new NullPointerException ("Null Visitor."); 427 } 428 429 traverse(null, visitor); 430 } 431 432 438 protected void traverse(Expression parentExp, TraversalHandler visitor) { 439 440 visitor.startNode(this, parentExp); 441 442 int count = getOperandCount(); 444 for (int i = 0; i < count; i++) { 445 Object child = getOperand(i); 446 447 if (child instanceof Expression) { 448 Expression childExp = (Expression) child; 449 childExp.traverse(this, visitor); 450 } 451 else { 452 visitor.objectNode(child, this); 453 } 454 455 visitor.finishedChild(this, i, i < count - 1); 456 } 457 458 visitor.endNode(this, parentExp); 459 } 460 461 473 public Expression transform(Transformer transformer) { 474 Object transformed = transformExpression(transformer); 475 476 if (transformed == PRUNED_NODE || transformed == null) { 477 return null; 478 } 479 else if (transformed instanceof Expression) { 480 return (Expression) transformed; 481 } 482 483 throw new ExpressionException("Invalid transformed expression: " + transformed); 484 } 485 486 492 protected Object transformExpression(Transformer transformer) { 493 Expression copy = shallowCopy(); 494 int count = getOperandCount(); 495 for (int i = 0, j = 0; i < count; i++) { 496 Object operand = getOperand(i); 497 Object transformedChild; 498 499 if (operand instanceof Expression) { 500 transformedChild = ((Expression) operand) 501 .transformExpression(transformer); 502 } 503 else if (transformer != null) { 504 transformedChild = transformer.transform(operand); 505 } 506 else { 507 transformedChild = operand; 508 } 509 510 boolean prune = transformer != null && transformedChild == PRUNED_NODE; 512 513 if (!prune) { 514 copy.setOperand(j, transformedChild); 515 j++; 516 } 517 518 if (prune && pruneNodeForPrunedChild(operand)) { 519 return PRUNED_NODE; 521 } 522 } 523 524 return (transformer != null) ? (Expression) transformer.transform(copy) : copy; 526 } 527 528 533 public void encodeAsXML(XMLEncoder encoder) { 534 encoder.print("<![CDATA["); 535 encodeAsString(encoder.getPrintWriter()); 536 encoder.print("]]>"); 537 } 538 539 544 public abstract void encodeAsString(PrintWriter pw); 545 546 public String toString() { 547 StringWriter buffer = new StringWriter (); 548 PrintWriter pw = new PrintWriter (buffer); 549 encodeAsString(pw); 550 pw.close(); 551 buffer.flush(); 552 return buffer.toString(); 553 } 554 } 555 | Popular Tags |