1 19 20 package org.apache.cayenne.access.trans; 21 22 import java.util.Iterator ; 23 import java.util.List ; 24 25 import org.apache.cayenne.ObjectId; 26 import org.apache.cayenne.Persistent; 27 import org.apache.cayenne.exp.Expression; 28 import org.apache.cayenne.exp.TraversalHandler; 29 import org.apache.cayenne.map.DbAttribute; 30 import org.apache.cayenne.map.DbRelationship; 31 import org.apache.cayenne.map.EntityInheritanceTree; 32 import org.apache.cayenne.map.ObjEntity; 33 import org.apache.cayenne.query.QualifiedQuery; 34 import org.apache.cayenne.query.Query; 35 import org.apache.cayenne.query.SelectQuery; 36 import org.apache.commons.collections.IteratorUtils; 37 38 43 public class QualifierTranslator 44 extends QueryAssemblerHelper 45 implements TraversalHandler { 46 47 protected StringBuffer qualBuf = new StringBuffer (); 48 49 protected boolean translateParentQual; 50 protected DataObjectMatchTranslator objectMatchTranslator; 51 protected boolean matchingObject; 52 53 public QualifierTranslator() { 54 this(null); 55 } 56 57 public QualifierTranslator(QueryAssembler queryAssembler) { 58 super(queryAssembler); 59 } 60 61 64 public String doTranslation() { 65 qualBuf.setLength(0); 66 67 Expression rootNode = extractQualifier(); 68 if (rootNode == null) { 69 return null; 70 } 71 72 rootNode.traverse(this); 75 return qualBuf.length() > 0 ? qualBuf.toString() : null; 76 } 77 78 protected Expression extractQualifier() { 79 Query q = queryAssembler.getQuery(); 80 81 Expression qualifier = 82 (isTranslateParentQual()) 83 ? ((SelectQuery) q).getParentQualifier() 84 : ((QualifiedQuery) q).getQualifier(); 85 86 ObjEntity entity = getObjEntity(); 88 89 if (entity != null) { 90 EntityInheritanceTree tree = 91 queryAssembler.getEntityResolver().lookupInheritanceTree( 92 entity); 93 Expression entityQualifier = 94 (tree != null) 95 ? tree.qualifierForEntityAndSubclasses() 96 : entity.getDeclaredQualifier(); 97 if (entityQualifier != null) { 98 qualifier = 99 (qualifier != null) 100 ? qualifier.andExp(entityQualifier) 101 : entityQualifier; 102 } 103 } 104 105 return qualifier; 106 } 107 108 112 protected void detectObjectMatch(Expression exp) { 113 118 matchingObject = false; 119 120 if (exp.getOperandCount() != 2) { 121 return; 123 } 124 125 for (int i = 0; i < 2; i++) { 127 Object op = exp.getOperand(i); 128 if (op instanceof Persistent || op instanceof ObjectId) { 129 matchingObject = true; 130 131 if (objectMatchTranslator == null) { 132 objectMatchTranslator = new DataObjectMatchTranslator(); 133 } 134 else { 135 objectMatchTranslator.reset(); 136 } 137 break; 138 } 139 } 140 } 141 142 protected void appendObjectMatch() { 143 if (!matchingObject || objectMatchTranslator == null) { 144 throw new IllegalStateException ("An invalid attempt to append object match."); 145 } 146 147 matchingObject = false; 149 150 boolean first = true; 151 DbRelationship relationship = objectMatchTranslator.getRelationship(); 152 153 if(!relationship.isToMany() && !relationship.isToPK()) { 154 queryAssembler.dbRelationshipAdded(relationship); 155 } 156 157 Iterator it = objectMatchTranslator.keys(); 158 while (it.hasNext()) { 159 if (first) { 160 first = false; 161 } 162 else { 163 qualBuf.append(" AND "); 164 } 165 166 String key = (String ) it.next(); 167 DbAttribute attr = objectMatchTranslator.getAttribute(key); 168 Object val = objectMatchTranslator.getValue(key); 169 170 processColumn(qualBuf, attr, relationship); 171 qualBuf.append(objectMatchTranslator.getOperation()); 172 appendLiteral(qualBuf, val, attr, objectMatchTranslator.getExpression()); 173 } 174 175 objectMatchTranslator.reset(); 176 } 177 178 179 public void finishedChild(Expression node, int childIndex, boolean hasMoreChildren) { 180 181 if (!hasMoreChildren) { 182 return; 183 } 184 185 StringBuffer buf = (matchingObject) ? new StringBuffer () : qualBuf; 186 187 switch (node.getType()) { 188 case Expression.AND : 189 buf.append(" AND "); 190 break; 191 case Expression.OR : 192 buf.append(" OR "); 193 break; 194 case Expression.EQUAL_TO : 195 if (childIndex == 0 197 && node.getOperandCount() == 2 198 && node.getOperand(1) == null) { 199 buf.append(" IS "); 200 } 201 else { 202 buf.append(" = "); 203 } 204 break; 205 case Expression.NOT_EQUAL_TO : 206 if (childIndex == 0 208 && node.getOperandCount() == 2 209 && node.getOperand(1) == null) { 210 buf.append(" IS NOT "); 211 } 212 else { 213 buf.append(" <> "); 214 } 215 break; 216 case Expression.LESS_THAN : 217 buf.append(" < "); 218 break; 219 case Expression.GREATER_THAN : 220 buf.append(" > "); 221 break; 222 case Expression.LESS_THAN_EQUAL_TO : 223 buf.append(" <= "); 224 break; 225 case Expression.GREATER_THAN_EQUAL_TO : 226 buf.append(" >= "); 227 break; 228 case Expression.IN : 229 buf.append(" IN "); 230 break; 231 case Expression.NOT_IN : 232 buf.append(" NOT IN "); 233 break; 234 case Expression.LIKE : 235 buf.append(" LIKE "); 236 break; 237 case Expression.NOT_LIKE : 238 buf.append(" NOT LIKE "); 239 break; 240 case Expression.LIKE_IGNORE_CASE : 241 buf.append(") LIKE UPPER("); 242 break; 243 case Expression.NOT_LIKE_IGNORE_CASE : 244 buf.append(") NOT LIKE UPPER("); 245 break; 246 case Expression.ADD : 247 buf.append(" + "); 248 break; 249 case Expression.SUBTRACT : 250 buf.append(" - "); 251 break; 252 case Expression.MULTIPLY : 253 buf.append(" * "); 254 break; 255 case Expression.DIVIDE : 256 buf.append(" / "); 257 break; 258 case Expression.BETWEEN : 259 if (childIndex == 0) 260 buf.append(" BETWEEN "); 261 else if (childIndex == 1) 262 buf.append(" AND "); 263 break; 264 case Expression.NOT_BETWEEN : 265 if (childIndex == 0) 266 buf.append(" NOT BETWEEN "); 267 else if (childIndex == 1) 268 buf.append(" AND "); 269 break; 270 } 271 272 if (matchingObject) { 273 objectMatchTranslator.setOperation(buf.toString()); 274 objectMatchTranslator.setExpression(node); 275 } 276 } 277 278 public void startNode(Expression node, Expression parentNode) { 279 int count = node.getOperandCount(); 280 281 if (count == 2) { 282 detectObjectMatch(node); 284 } 285 286 if (parenthesisNeeded(node, parentNode)) { 287 qualBuf.append('('); 288 } 289 290 if (count == 0) { 291 if (node.getType() == Expression.TRUE) { 293 qualBuf.append("1 = 1"); 294 } 295 if (node.getType() == Expression.FALSE) { 296 qualBuf.append("1 = 0"); 297 } 298 } 299 300 if (count == 1) { 301 if (node.getType() == Expression.NEGATIVE) 302 qualBuf.append('-'); 303 else if (node.getType() == Expression.NOT) 307 qualBuf.append("NOT "); 308 } 309 else if ( 310 node.getType() == Expression.LIKE_IGNORE_CASE 311 || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) { 312 qualBuf.append("UPPER("); 313 } 314 } 315 316 319 public void endNode(Expression node, Expression parentNode) { 320 321 if (node.getOperandCount() == 2 && matchingObject) { 323 appendObjectMatch(); 324 } 325 326 if (parenthesisNeeded(node, parentNode)) { 327 qualBuf.append(')'); 328 } 329 330 if (node.getType() == Expression.LIKE_IGNORE_CASE 331 || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) { 332 qualBuf.append(')'); 333 } 334 } 335 336 public void objectNode(Object leaf, Expression parentNode) { 337 if (parentNode.getType() == Expression.OBJ_PATH) { 338 appendObjPath(qualBuf, parentNode); 339 } 340 else if (parentNode.getType() == Expression.DB_PATH) { 341 appendDbPath(qualBuf, parentNode); 342 } 343 else if (parentNode.getType() == Expression.LIST) { 344 appendList(parentNode, paramsDbType(parentNode)); 345 } 346 else { 347 appendLiteral(qualBuf, leaf, paramsDbType(parentNode), parentNode); 348 } 349 } 350 351 protected boolean parenthesisNeeded(Expression node, Expression parentNode) { 352 if (parentNode == null) 353 return false; 354 355 if (node.getOperandCount() > 1) 357 return true; 358 359 if (node.getType() == Expression.OBJ_PATH) 360 return false; 361 362 if (node.getType() == Expression.DB_PATH) 363 return false; 364 365 return true; 366 } 367 368 private final void appendList(Expression listExpr, DbAttribute paramDesc) { 369 Iterator it = null; 370 Object list = listExpr.getOperand(0); 371 if (list instanceof List ) { 372 it = ((List ) list).iterator(); 373 } 374 else if (list instanceof Object []) { 375 it = IteratorUtils.arrayIterator((Object []) list); 376 } 377 else { 378 String className = (list != null) ? list.getClass().getName() : "<null>"; 379 throw new IllegalArgumentException ( 380 "Unsupported type for the list expressions: " + className); 381 } 382 383 if (it.hasNext()) 386 appendLiteral(qualBuf, it.next(), paramDesc, listExpr); 387 else 388 return; 389 390 while (it.hasNext()) { 391 qualBuf.append(", "); 392 appendLiteral(qualBuf, it.next(), paramDesc, listExpr); 393 } 394 } 395 396 402 public boolean isTranslateParentQual() { 403 return translateParentQual; 404 } 405 406 412 public void setTranslateParentQual(boolean translateParentQual) { 413 this.translateParentQual = translateParentQual; 414 } 415 416 public ObjEntity getObjEntity() { 417 if (isTranslateParentQual()) { 418 SelectQuery query = (SelectQuery) queryAssembler.getQuery(); 419 return queryAssembler.getEntityResolver().getObjEntity( 420 query.getParentObjEntityName()); 421 } 422 else { 423 return super.getObjEntity(); 424 } 425 } 426 427 protected void appendLiteral( 428 StringBuffer buf, 429 Object val, 430 DbAttribute attr, 431 Expression parentExpression) { 432 433 if (!matchingObject) { 434 super.appendLiteral(buf, val, attr, parentExpression); 435 } 436 else if (val == null || (val instanceof Persistent)) { 437 objectMatchTranslator.setDataObject((Persistent) val); 438 } 439 else if(val instanceof ObjectId) { 440 objectMatchTranslator.setObjectId((ObjectId) val); 441 } 442 else { 443 throw new IllegalArgumentException ("Attempt to use literal other than DataObject during object match."); 444 } 445 } 446 447 protected void processRelTermination(StringBuffer buf, DbRelationship rel) { 448 449 if (!matchingObject) { 450 super.processRelTermination(buf, rel); 451 } 452 else { 453 if (rel.isToMany()) { 454 queryAssembler.dbRelationshipAdded(rel); 456 } 457 objectMatchTranslator.setRelationship(rel); 458 } 459 } 460 } 461 | Popular Tags |