1 19 20 package org.apache.cayenne.access.trans; 21 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import org.apache.cayenne.CayenneRuntimeException; 27 import org.apache.cayenne.ObjectId; 28 import org.apache.cayenne.Persistent; 29 import org.apache.cayenne.exp.Expression; 30 import org.apache.cayenne.map.DbAttribute; 31 import org.apache.cayenne.map.DbEntity; 32 import org.apache.cayenne.map.DbJoin; 33 import org.apache.cayenne.map.DbRelationship; 34 import org.apache.cayenne.map.ObjAttribute; 35 import org.apache.cayenne.map.ObjEntity; 36 import org.apache.cayenne.map.ObjRelationship; 37 38 44 public abstract class QueryAssemblerHelper { 45 46 protected QueryAssembler queryAssembler; 47 48 public QueryAssemblerHelper() { 49 } 50 51 52 public QueryAssemblerHelper(QueryAssembler queryAssembler) { 53 this.queryAssembler = queryAssembler; 54 } 55 56 57 public QueryAssembler getQueryAssembler() { 58 return queryAssembler; 59 } 60 61 public void setQueryAssembler(QueryAssembler queryAssembler) { 62 this.queryAssembler = queryAssembler; 63 } 64 65 72 public abstract String doTranslation(); 73 74 public ObjEntity getObjEntity() { 75 return getQueryAssembler().getRootEntity(); 76 } 77 78 public DbEntity getDbEntity() { 79 return getQueryAssembler().getRootDbEntity(); 80 } 81 82 83 protected void appendObjPath(StringBuffer buf, Expression pathExp) { 84 85 Iterator it = getObjEntity().resolvePathComponents(pathExp); 86 ObjRelationship lastRelationship = null; 87 88 while (it.hasNext()) { 89 Object pathComp = it.next(); 90 91 if (pathComp instanceof ObjRelationship) { 92 ObjRelationship rel = (ObjRelationship) pathComp; 93 94 if (!it.hasNext()) { 97 processRelTermination(buf, rel); 98 } 99 else { 100 Iterator relit = rel.getDbRelationships().iterator(); 102 while (relit.hasNext()) { 103 queryAssembler.dbRelationshipAdded((DbRelationship) relit.next()); 104 } 105 } 106 lastRelationship = rel; 107 } 108 else { 109 ObjAttribute objAttr = (ObjAttribute) pathComp; 110 if (lastRelationship != null) { 111 List lastDbRelList = lastRelationship.getDbRelationships(); 112 DbRelationship lastDbRel = 113 (DbRelationship) lastDbRelList.get(lastDbRelList.size() - 1); 114 processColumn(buf, objAttr.getDbAttribute(), lastDbRel); 115 } 116 else { 117 processColumn(buf, objAttr.getDbAttribute()); 118 } 119 } 120 } 121 } 122 123 protected void appendDbPath(StringBuffer buf, Expression pathExp) { 124 Iterator it = getDbEntity().resolvePathComponents(pathExp); 125 126 while (it.hasNext()) { 127 Object pathComp = it.next(); 128 if (pathComp instanceof DbRelationship) { 129 DbRelationship rel = (DbRelationship) pathComp; 130 131 if (!it.hasNext()) { 134 processRelTermination(buf, rel); 135 } 136 else { 137 queryAssembler.dbRelationshipAdded(rel); 139 } 140 } 141 else { 142 DbAttribute dbAttr = (DbAttribute) pathComp; 143 processColumn(buf, dbAttr); 144 } 145 } 146 } 147 148 149 protected void processColumn(StringBuffer buf, Expression nameExp) { 150 if (queryAssembler.supportsTableAliases()) { 151 String alias = queryAssembler.aliasForTable(getDbEntity()); 152 buf.append(alias).append('.'); 153 } 154 155 buf.append(nameExp.getOperand(0)); 156 } 157 158 protected void processColumn( 159 StringBuffer buf, 160 DbAttribute dbAttr, 161 DbRelationship relationship) { 162 String alias = null; 163 164 if (queryAssembler.supportsTableAliases()) { 165 166 if (relationship != null) { 167 alias = queryAssembler.aliasForTable( 168 (DbEntity) dbAttr.getEntity(), 169 relationship); 170 } 171 172 if (alias == null) { 177 alias = queryAssembler.aliasForTable((DbEntity) dbAttr.getEntity()); 178 } 179 } 180 181 buf.append(dbAttr.getAliasedName(alias)); 182 } 183 184 protected void processColumn(StringBuffer buf, DbAttribute dbAttr) { 185 String alias = 186 (queryAssembler.supportsTableAliases()) 187 ? queryAssembler.aliasForTable((DbEntity) dbAttr.getEntity()) 188 : null; 189 190 buf.append(dbAttr.getAliasedName(alias)); 191 } 192 193 213 protected void appendLiteral( 214 StringBuffer buf, 215 Object val, 216 DbAttribute attr, 217 Expression parentExpression) { 218 if (val == null) { 219 buf.append("NULL"); 220 } 221 else if (val instanceof Persistent) { 222 ObjectId id = ((Persistent) val).getObjectId(); 223 224 if (id == null) { 226 throw new CayenneRuntimeException("Can't use TRANSIENT object as a query parameter."); 227 } 228 229 if (id.isTemporary()) { 230 throw new CayenneRuntimeException("Can't use NEW object as a query parameter."); 231 } 232 233 Map snap = id.getIdSnapshot(); 234 if (snap.size() != 1) { 235 StringBuffer msg = new StringBuffer (); 236 msg 237 .append("Object must have a single primary key column ") 238 .append("to serve as a query parameter. ") 239 .append("This object has ") 240 .append(snap.size()) 241 .append(": ") 242 .append(snap); 243 244 throw new CayenneRuntimeException(msg.toString()); 245 } 246 247 appendLiteralDirect( 249 buf, 250 snap.get(snap.keySet().iterator().next()), 251 attr, 252 parentExpression); 253 } 254 else { 255 appendLiteralDirect(buf, val, attr, parentExpression); 256 } 257 } 258 259 269 protected void appendLiteralDirect( 270 StringBuffer buf, 271 Object val, 272 DbAttribute attr, 273 Expression parentExpression) { 274 buf.append('?'); 275 276 queryAssembler.addToParamList(attr, val); 280 } 281 282 286 protected DbAttribute paramsDbType(Expression e) { 287 int len = e.getOperandCount(); 288 if (len < 2) { 290 return null; 291 } 292 293 295 299 DbAttribute attribute = null; 301 DbRelationship relationship = null; 302 for (int i = 0; i < len; i++) { 303 Object op = e.getOperand(i); 304 305 if (op instanceof Expression) { 306 Expression expression = (Expression) op; 307 if (expression.getType() == Expression.OBJ_PATH) { 308 Object last = getObjEntity().lastPathComponent(expression); 309 if (last instanceof ObjAttribute) { 310 attribute = ((ObjAttribute) last).getDbAttribute(); 311 break; 312 } 313 else if (last instanceof ObjRelationship) { 314 ObjRelationship objRelationship = (ObjRelationship) last; 315 List dbPath = objRelationship.getDbRelationships(); 316 if (dbPath.size() > 0) { 317 relationship = (DbRelationship) dbPath.get(dbPath.size() - 1); 318 break; 319 } 320 } 321 } 322 else if (expression.getType() == Expression.DB_PATH) { 323 Object last = getDbEntity().lastPathComponent(expression); 324 if (last instanceof DbAttribute) { 325 attribute = (DbAttribute) last; 326 break; 327 } 328 else if (last instanceof DbRelationship) { 329 relationship = (DbRelationship) last; 330 break; 331 } 332 } 333 } 334 } 335 336 if (attribute != null) { 337 return attribute; 338 } 339 340 if (relationship != null) { 341 if (relationship.getJoins().size() == 1) { 343 DbJoin join = (DbJoin) relationship.getJoins().get(0); 344 return join.getSource(); 345 } 346 } 347 348 return null; 349 } 350 351 356 protected void processRelTermination(StringBuffer buf, ObjRelationship rel) { 357 358 Iterator dbRels = rel.getDbRelationships().iterator(); 359 360 while (dbRels.hasNext()) { 362 DbRelationship dbRel = (DbRelationship) dbRels.next(); 363 364 if (!dbRels.hasNext()) { 367 processRelTermination(buf, dbRel); 368 } 369 else { 370 queryAssembler.dbRelationshipAdded(dbRel); 372 } 373 } 374 } 375 376 382 protected void processRelTermination(StringBuffer buf, DbRelationship rel) { 383 384 if (rel.isToMany()) { 385 queryAssembler.dbRelationshipAdded(rel); 387 } 388 389 List joins = rel.getJoins(); 391 if (joins.size() != 1) { 392 StringBuffer msg = new StringBuffer (); 393 msg 394 .append("OBJ_PATH expressions are only supported ") 395 .append("for a single-join relationships. ") 396 .append("This relationship has ") 397 .append(joins.size()) 398 .append(" joins."); 399 400 throw new CayenneRuntimeException(msg.toString()); 401 } 402 403 DbJoin join = (DbJoin) joins.get(0); 404 405 DbAttribute att = null; 406 407 if (rel.isToMany()) { 408 DbEntity ent = (DbEntity) join.getRelationship().getTargetEntity(); 409 List pk = ent.getPrimaryKey(); 410 if (pk.size() != 1) { 411 StringBuffer msg = new StringBuffer (); 412 msg 413 .append("DB_NAME expressions can only support ") 414 .append("targets with a single column PK. ") 415 .append("This entity has ") 416 .append(pk.size()) 417 .append(" columns in primary key."); 418 419 throw new CayenneRuntimeException(msg.toString()); 420 } 421 422 att = (DbAttribute) pk.get(0); 423 } 424 else { 425 att = join.getSource(); 426 } 427 428 processColumn(buf, att); 429 } 430 } 431 | Popular Tags |