1 56 package org.objectstyle.cayenne.access.trans; 57 58 import java.util.Iterator ; 59 import java.util.List ; 60 61 import org.apache.commons.collections.IteratorUtils; 62 import org.objectstyle.cayenne.DataObject; 63 import org.objectstyle.cayenne.exp.Expression; 64 import org.objectstyle.cayenne.exp.TraversalHandler; 65 import org.objectstyle.cayenne.map.DbAttribute; 66 import org.objectstyle.cayenne.map.DbRelationship; 67 import org.objectstyle.cayenne.map.EntityInheritanceTree; 68 import org.objectstyle.cayenne.map.ObjEntity; 69 import org.objectstyle.cayenne.query.QualifiedQuery; 70 import org.objectstyle.cayenne.query.Query; 71 import org.objectstyle.cayenne.query.SelectQuery; 72 73 78 public class QualifierTranslator 79 extends QueryAssemblerHelper 80 implements TraversalHandler { 81 82 protected StringBuffer qualBuf = new StringBuffer (); 83 84 protected boolean translateParentQual; 85 protected DataObjectMatchTranslator objectMatchTranslator; 86 protected boolean matchingObject; 87 88 public QualifierTranslator() { 89 this(null); 90 } 91 92 public QualifierTranslator(QueryAssembler queryAssembler) { 93 super(queryAssembler); 94 } 95 96 99 public String doTranslation() { 100 qualBuf.setLength(0); 101 102 Expression rootNode = extractQualifier(); 103 if (rootNode == null) { 104 return null; 105 } 106 107 rootNode.traverse(this); 110 return qualBuf.length() > 0 ? qualBuf.toString() : null; 111 } 112 113 protected Expression extractQualifier() { 114 Query q = queryAssembler.getQuery(); 115 116 Expression qualifier = 117 (isTranslateParentQual()) 118 ? ((SelectQuery) q).getParentQualifier() 119 : ((QualifiedQuery) q).getQualifier(); 120 121 ObjEntity entity = getObjEntity(); 123 124 if (entity != null) { 125 EntityInheritanceTree tree = 126 queryAssembler.getEntityResolver().lookupInheritanceTree( 127 entity); 128 Expression entityQualifier = 129 (tree != null) 130 ? tree.qualifierForEntityAndSubclasses() 131 : entity.getDeclaredQualifier(); 132 if (entityQualifier != null) { 133 qualifier = 134 (qualifier != null) 135 ? qualifier.andExp(entityQualifier) 136 : entityQualifier; 137 } 138 } 139 140 return qualifier; 141 } 142 143 147 protected void detectObjectMatch(Expression exp) { 148 153 matchingObject = false; 154 155 if (exp.getOperandCount() != 2) { 156 return; 158 } 159 160 for (int i = 0; i < 2; i++) { 162 Object op = exp.getOperand(i); 163 if (op instanceof DataObject) { 164 matchingObject = true; 165 166 if (objectMatchTranslator == null) { 167 objectMatchTranslator = new DataObjectMatchTranslator(); 168 } 169 else { 170 objectMatchTranslator.reset(); 171 } 172 break; 173 } 174 } 175 } 176 177 protected void appendObjectMatch() { 178 if (!matchingObject || objectMatchTranslator == null) { 179 throw new IllegalStateException ("An invalid attempt to append object match."); 180 } 181 182 matchingObject = false; 184 185 boolean first = true; 186 DbRelationship relationship = objectMatchTranslator.getRelationship(); 187 Iterator it = objectMatchTranslator.keys(); 188 while (it.hasNext()) { 189 if (first) { 190 first = false; 191 } 192 else { 193 qualBuf.append(" AND "); 194 } 195 196 String key = (String ) it.next(); 197 DbAttribute attr = objectMatchTranslator.getAttribute(key); 198 Object val = objectMatchTranslator.getValue(key); 199 200 processColumn(qualBuf, attr, relationship); 201 qualBuf.append(objectMatchTranslator.getOperation()); 202 appendLiteral(qualBuf, val, attr, objectMatchTranslator.getExpression()); 203 } 204 205 objectMatchTranslator.reset(); 206 } 207 208 209 public void finishedChild(Expression node, int childIndex, boolean hasMoreChildren) { 210 211 if (!hasMoreChildren) { 212 return; 213 } 214 215 StringBuffer buf = (matchingObject) ? new StringBuffer () : qualBuf; 216 217 switch (node.getType()) { 218 case Expression.AND : 219 buf.append(" AND "); 220 break; 221 case Expression.OR : 222 buf.append(" OR "); 223 break; 224 case Expression.EQUAL_TO : 225 if (childIndex == 0 227 && node.getOperandCount() == 2 228 && node.getOperand(1) == null) { 229 buf.append(" IS "); 230 } 231 else { 232 buf.append(" = "); 233 } 234 break; 235 case Expression.NOT_EQUAL_TO : 236 if (childIndex == 0 238 && node.getOperandCount() == 2 239 && node.getOperand(1) == null) { 240 buf.append(" IS NOT "); 241 } 242 else { 243 buf.append(" <> "); 244 } 245 break; 246 case Expression.LESS_THAN : 247 buf.append(" < "); 248 break; 249 case Expression.GREATER_THAN : 250 buf.append(" > "); 251 break; 252 case Expression.LESS_THAN_EQUAL_TO : 253 buf.append(" <= "); 254 break; 255 case Expression.GREATER_THAN_EQUAL_TO : 256 buf.append(" >= "); 257 break; 258 case Expression.IN : 259 buf.append(" IN "); 260 break; 261 case Expression.NOT_IN : 262 buf.append(" NOT IN "); 263 break; 264 case Expression.LIKE : 265 buf.append(" LIKE "); 266 break; 267 case Expression.NOT_LIKE : 268 buf.append(" NOT LIKE "); 269 break; 270 case Expression.LIKE_IGNORE_CASE : 271 buf.append(") LIKE UPPER("); 272 break; 273 case Expression.NOT_LIKE_IGNORE_CASE : 274 buf.append(") NOT LIKE UPPER("); 275 break; 276 case Expression.ADD : 277 buf.append(" + "); 278 break; 279 case Expression.SUBTRACT : 280 buf.append(" - "); 281 break; 282 case Expression.MULTIPLY : 283 buf.append(" * "); 284 break; 285 case Expression.DIVIDE : 286 buf.append(" / "); 287 break; 288 case Expression.BETWEEN : 289 if (childIndex == 0) 290 buf.append(" BETWEEN "); 291 else if (childIndex == 1) 292 buf.append(" AND "); 293 break; 294 case Expression.NOT_BETWEEN : 295 if (childIndex == 0) 296 buf.append(" NOT BETWEEN "); 297 else if (childIndex == 1) 298 buf.append(" AND "); 299 break; 300 } 301 302 if (matchingObject) { 303 objectMatchTranslator.setOperation(buf.toString()); 304 objectMatchTranslator.setExpression(node); 305 } 306 } 307 308 public void startNode(Expression node, Expression parentNode) { 309 int count = node.getOperandCount(); 310 311 if (count == 2) { 312 detectObjectMatch(node); 314 } 315 316 if (parenthesisNeeded(node, parentNode)) { 317 qualBuf.append('('); 318 } 319 320 if (count == 1) { 321 if (node.getType() == Expression.NEGATIVE) 322 qualBuf.append('-'); 323 else if (node.getType() == Expression.NOT) 327 qualBuf.append("NOT "); 328 else if (node.getType() == Expression.EXISTS) 329 qualBuf.append("EXISTS "); 330 else if (node.getType() == Expression.ALL) 331 qualBuf.append("ALL "); 332 else if (node.getType() == Expression.SOME) 333 qualBuf.append("SOME "); 334 else if (node.getType() == Expression.ANY) 335 qualBuf.append("ANY "); 336 } 337 else if ( 338 node.getType() == Expression.LIKE_IGNORE_CASE 339 || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) { 340 qualBuf.append("UPPER("); 341 } 342 } 343 344 347 public void endNode(Expression node, Expression parentNode) { 348 349 if (node.getOperandCount() == 2 && matchingObject) { 351 appendObjectMatch(); 352 } 353 354 if (parenthesisNeeded(node, parentNode)) { 355 qualBuf.append(')'); 356 } 357 358 if (node.getType() == Expression.LIKE_IGNORE_CASE 359 || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) { 360 qualBuf.append(')'); 361 } 362 } 363 364 public void objectNode(Object leaf, Expression parentNode) { 365 if (parentNode.getType() == Expression.RAW_SQL) { 366 appendRawSql(leaf); 367 } 368 else if (parentNode.getType() == Expression.OBJ_PATH) { 369 appendObjPath(qualBuf, parentNode); 370 } 371 else if (parentNode.getType() == Expression.DB_PATH) { 372 appendDbPath(qualBuf, parentNode); 373 } 374 else if (parentNode.getType() == Expression.LIST) { 375 appendList(parentNode, paramsDbType(parentNode)); 376 } 377 else { 378 appendLiteral(qualBuf, leaf, paramsDbType(parentNode), parentNode); 379 } 380 } 381 382 protected boolean parenthesisNeeded(Expression node, Expression parentNode) { 383 if (parentNode == null) 384 return false; 385 386 if (node.getOperandCount() > 1) 388 return true; 389 390 if (node.getType() == Expression.OBJ_PATH) 391 return false; 392 393 if (node.getType() == Expression.DB_PATH) 394 return false; 395 396 return true; 397 } 398 399 private void appendRawSql(Object sql) { 400 if (sql != null) { 401 qualBuf.append(sql); 402 } 403 } 404 405 private final void appendList(Expression listExpr, DbAttribute paramDesc) { 406 Iterator it = null; 407 Object list = listExpr.getOperand(0); 408 if (list instanceof List ) { 409 it = ((List ) list).iterator(); 410 } 411 else if (list instanceof Object []) { 412 it = IteratorUtils.arrayIterator((Object []) list); 413 } 414 else { 415 String className = (list != null) ? list.getClass().getName() : "<null>"; 416 throw new IllegalArgumentException ( 417 "Unsupported type for the list expressions: " + className); 418 } 419 420 if (it.hasNext()) 423 appendLiteral(qualBuf, it.next(), paramDesc, listExpr); 424 else 425 return; 426 427 while (it.hasNext()) { 428 qualBuf.append(", "); 429 appendLiteral(qualBuf, it.next(), paramDesc, listExpr); 430 } 431 } 432 433 439 public boolean isTranslateParentQual() { 440 return translateParentQual; 441 } 442 443 449 public void setTranslateParentQual(boolean translateParentQual) { 450 this.translateParentQual = translateParentQual; 451 } 452 453 public ObjEntity getObjEntity() { 454 if (isTranslateParentQual()) { 455 SelectQuery query = (SelectQuery) queryAssembler.getQuery(); 456 return queryAssembler.getEntityResolver().getObjEntity( 457 query.getParentObjEntityName()); 458 } 459 else { 460 return super.getObjEntity(); 461 } 462 } 463 464 protected void appendLiteral( 465 StringBuffer buf, 466 Object val, 467 DbAttribute attr, 468 Expression parentExpression) { 469 470 if (!matchingObject) { 471 super.appendLiteral(buf, val, attr, parentExpression); 472 } 473 else if (val == null || (val instanceof DataObject)) { 474 objectMatchTranslator.setDataObject((DataObject) val); 475 } 476 else { 477 throw new IllegalArgumentException ("Attempt to use literal other than DataObject during object match."); 478 } 479 } 480 481 protected void processRelTermination(StringBuffer buf, DbRelationship rel) { 482 483 if (!matchingObject) { 484 super.processRelTermination(buf, rel); 485 } 486 else { 487 if (rel.isToMany()) { 488 queryAssembler.dbRelationshipAdded(rel); 490 } 491 objectMatchTranslator.setRelationship(rel); 492 } 493 } 494 } | Popular Tags |