1 56 package org.objectstyle.cayenne.access.trans; 57 58 import java.util.Iterator ; 59 import java.util.List ; 60 import java.util.Map ; 61 62 import org.objectstyle.cayenne.CayenneRuntimeException; 63 import org.objectstyle.cayenne.DataObject; 64 import org.objectstyle.cayenne.ObjectId; 65 import org.objectstyle.cayenne.exp.Expression; 66 import org.objectstyle.cayenne.map.DbAttribute; 67 import org.objectstyle.cayenne.map.DbEntity; 68 import org.objectstyle.cayenne.map.DbJoin; 69 import org.objectstyle.cayenne.map.DbRelationship; 70 import org.objectstyle.cayenne.map.ObjAttribute; 71 import org.objectstyle.cayenne.map.ObjEntity; 72 import org.objectstyle.cayenne.map.ObjRelationship; 73 74 80 public abstract class QueryAssemblerHelper { 81 82 protected QueryAssembler queryAssembler; 83 84 public QueryAssemblerHelper() { 85 } 86 87 88 public QueryAssemblerHelper(QueryAssembler queryAssembler) { 89 this.queryAssembler = queryAssembler; 90 } 91 92 93 public QueryAssembler getQueryAssembler() { 94 return queryAssembler; 95 } 96 97 public void setQueryAssembler(QueryAssembler queryAssembler) { 98 this.queryAssembler = queryAssembler; 99 } 100 101 108 public abstract String doTranslation(); 109 110 public ObjEntity getObjEntity() { 111 return getQueryAssembler().getRootEntity(); 112 } 113 114 public DbEntity getDbEntity() { 115 return getQueryAssembler().getRootDbEntity(); 116 } 117 118 119 protected void appendObjPath(StringBuffer buf, Expression pathExp) { 120 121 Iterator it = getObjEntity().resolvePathComponents(pathExp); 122 ObjRelationship lastRelationship = null; 123 124 while (it.hasNext()) { 125 Object pathComp = it.next(); 126 127 if (pathComp instanceof ObjRelationship) { 128 ObjRelationship rel = (ObjRelationship) pathComp; 129 130 if (!it.hasNext()) { 133 processRelTermination(buf, rel); 134 } 135 else { 136 Iterator relit = rel.getDbRelationships().iterator(); 138 while (relit.hasNext()) { 139 queryAssembler.dbRelationshipAdded((DbRelationship) relit.next()); 140 } 141 } 142 lastRelationship = rel; 143 } 144 else { 145 ObjAttribute objAttr = (ObjAttribute) pathComp; 146 if (lastRelationship != null) { 147 List lastDbRelList = lastRelationship.getDbRelationships(); 148 DbRelationship lastDbRel = 149 (DbRelationship) lastDbRelList.get(lastDbRelList.size() - 1); 150 processColumn(buf, objAttr.getDbAttribute(), lastDbRel); 151 } 152 else { 153 processColumn(buf, objAttr.getDbAttribute()); 154 } 155 } 156 } 157 } 158 159 protected void appendDbPath(StringBuffer buf, Expression pathExp) { 160 Iterator it = getDbEntity().resolvePathComponents(pathExp); 161 162 while (it.hasNext()) { 163 Object pathComp = it.next(); 164 if (pathComp instanceof DbRelationship) { 165 DbRelationship rel = (DbRelationship) pathComp; 166 167 if (!it.hasNext()) { 170 processRelTermination(buf, rel); 171 } 172 else { 173 queryAssembler.dbRelationshipAdded(rel); 175 } 176 } 177 else { 178 DbAttribute dbAttr = (DbAttribute) pathComp; 179 processColumn(buf, dbAttr); 180 } 181 } 182 } 183 184 185 protected void processColumn(StringBuffer buf, Expression nameExp) { 186 if (queryAssembler.supportsTableAliases()) { 187 String alias = queryAssembler.aliasForTable(getDbEntity()); 188 buf.append(alias).append('.'); 189 } 190 191 buf.append(nameExp.getOperand(0)); 192 } 193 194 protected void processColumn( 195 StringBuffer buf, 196 DbAttribute dbAttr, 197 DbRelationship relationship) { 198 String alias = null; 199 200 if (queryAssembler.supportsTableAliases()) { 201 202 if (relationship != null) { 203 alias = queryAssembler.aliasForTable( 204 (DbEntity) dbAttr.getEntity(), 205 relationship); 206 } 207 208 if (alias == null) { 213 alias = queryAssembler.aliasForTable((DbEntity) dbAttr.getEntity()); 214 } 215 } 216 217 buf.append(dbAttr.getAliasedName(alias)); 218 } 219 220 protected void processColumn(StringBuffer buf, DbAttribute dbAttr) { 221 String alias = 222 (queryAssembler.supportsTableAliases()) 223 ? queryAssembler.aliasForTable((DbEntity) dbAttr.getEntity()) 224 : null; 225 226 buf.append(dbAttr.getAliasedName(alias)); 227 } 228 229 249 protected void appendLiteral( 250 StringBuffer buf, 251 Object val, 252 DbAttribute attr, 253 Expression parentExpression) { 254 if (val == null) { 255 buf.append("NULL"); 256 } 257 else if (val instanceof DataObject) { 258 ObjectId id = ((DataObject) val).getObjectId(); 259 260 if (id == null) { 262 throw new CayenneRuntimeException("Can't use TRANSIENT object as a query parameter."); 263 } 264 265 if (id.isTemporary()) { 266 throw new CayenneRuntimeException("Can't use NEW object as a query parameter."); 267 } 268 269 Map snap = id.getIdSnapshot(); 270 if (snap.size() != 1) { 271 StringBuffer msg = new StringBuffer (); 272 msg 273 .append("Object must have a single primary key column ") 274 .append("to serve as a query parameter. ") 275 .append("This object has ") 276 .append(snap.size()) 277 .append(": ") 278 .append(snap); 279 280 throw new CayenneRuntimeException(msg.toString()); 281 } 282 283 appendLiteralDirect( 285 buf, 286 snap.get(snap.keySet().iterator().next()), 287 attr, 288 parentExpression); 289 } 290 else { 291 appendLiteralDirect(buf, val, attr, parentExpression); 292 } 293 } 294 295 305 protected void appendLiteralDirect( 306 StringBuffer buf, 307 Object val, 308 DbAttribute attr, 309 Expression parentExpression) { 310 buf.append('?'); 311 312 queryAssembler.addToParamList(attr, val); 316 } 317 318 322 protected DbAttribute paramsDbType(Expression e) { 323 int len = e.getOperandCount(); 324 if (len < 2) { 326 return null; 327 } 328 329 331 335 DbAttribute attribute = null; 337 DbRelationship relationship = null; 338 for (int i = 0; i < len; i++) { 339 Object op = e.getOperand(i); 340 341 if (op instanceof Expression) { 342 Expression expression = (Expression) op; 343 if (expression.getType() == Expression.OBJ_PATH) { 344 Object last = getObjEntity().lastPathComponent(expression); 345 if (last instanceof ObjAttribute) { 346 attribute = ((ObjAttribute) last).getDbAttribute(); 347 break; 348 } 349 else if (last instanceof ObjRelationship) { 350 ObjRelationship objRelationship = (ObjRelationship) last; 351 List dbPath = objRelationship.getDbRelationships(); 352 if (dbPath.size() > 0) { 353 relationship = (DbRelationship) dbPath.get(dbPath.size() - 1); 354 break; 355 } 356 } 357 } 358 else if (expression.getType() == Expression.DB_PATH) { 359 Object last = getDbEntity().lastPathComponent(expression); 360 if (last instanceof DbAttribute) { 361 attribute = (DbAttribute) last; 362 break; 363 } 364 else if (last instanceof DbRelationship) { 365 relationship = (DbRelationship) last; 366 break; 367 } 368 } 369 } 370 } 371 372 if (attribute != null) { 373 return attribute; 374 } 375 376 if (relationship != null) { 377 if (relationship.getJoins().size() == 1) { 379 DbJoin join = (DbJoin) relationship.getJoins().get(0); 380 return join.getSource(); 381 } 382 } 383 384 return null; 385 } 386 387 392 protected void processRelTermination(StringBuffer buf, ObjRelationship rel) { 393 394 Iterator dbRels = rel.getDbRelationships().iterator(); 395 396 while (dbRels.hasNext()) { 398 DbRelationship dbRel = (DbRelationship) dbRels.next(); 399 400 if (!dbRels.hasNext()) { 403 processRelTermination(buf, dbRel); 404 } 405 else { 406 queryAssembler.dbRelationshipAdded(dbRel); 408 } 409 } 410 } 411 412 418 protected void processRelTermination(StringBuffer buf, DbRelationship rel) { 419 420 if (rel.isToMany()) { 421 queryAssembler.dbRelationshipAdded(rel); 423 } 424 425 List joins = rel.getJoins(); 427 if (joins.size() != 1) { 428 StringBuffer msg = new StringBuffer (); 429 msg 430 .append("OBJ_PATH expressions are only supported ") 431 .append("for a single-join relationships. ") 432 .append("This relationship has ") 433 .append(joins.size()) 434 .append(" joins."); 435 436 throw new CayenneRuntimeException(msg.toString()); 437 } 438 439 DbJoin join = (DbJoin) joins.get(0); 440 441 DbAttribute att = null; 442 443 if (rel.isToMany()) { 444 DbEntity ent = (DbEntity) join.getRelationship().getTargetEntity(); 445 List pk = ent.getPrimaryKey(); 446 if (pk.size() != 1) { 447 StringBuffer msg = new StringBuffer (); 448 msg 449 .append("DB_NAME expressions can only support ") 450 .append("targets with a single column PK. ") 451 .append("This entity has ") 452 .append(pk.size()) 453 .append(" columns in primary key."); 454 455 throw new CayenneRuntimeException(msg.toString()); 456 } 457 458 att = (DbAttribute) pk.get(0); 459 } 460 else { 461 att = join.getSource(); 462 } 463 464 processColumn(buf, att); 465 } 466 } 467 | Popular Tags |