1 56 package org.objectstyle.cayenne.map; 57 58 import java.util.ArrayList ; 59 import java.util.Collection ; 60 import java.util.Collections ; 61 import java.util.Iterator ; 62 import java.util.LinkedList ; 63 import java.util.List ; 64 import java.util.Map ; 65 66 import org.apache.commons.collections.Transformer; 67 import org.objectstyle.cayenne.CayenneRuntimeException; 68 import org.objectstyle.cayenne.ObjectId; 69 import org.objectstyle.cayenne.exp.Expression; 70 import org.objectstyle.cayenne.exp.ExpressionException; 71 import org.objectstyle.cayenne.exp.ExpressionFactory; 72 import org.objectstyle.cayenne.map.event.AttributeEvent; 73 import org.objectstyle.cayenne.map.event.DbAttributeListener; 74 import org.objectstyle.cayenne.map.event.DbEntityListener; 75 import org.objectstyle.cayenne.map.event.DbRelationshipListener; 76 import org.objectstyle.cayenne.map.event.EntityEvent; 77 import org.objectstyle.cayenne.map.event.MapEvent; 78 import org.objectstyle.cayenne.map.event.RelationshipEvent; 79 import org.objectstyle.cayenne.util.Util; 80 import org.objectstyle.cayenne.util.XMLEncoder; 81 82 88 public class DbEntity extends Entity implements DbEntityListener, 89 DbAttributeListener, 90 DbRelationshipListener { 91 92 protected String catalog; 93 protected String schema; 94 protected List primaryKey; 95 protected List primaryKeyRef; 96 97 100 protected Collection generatedAttributes; 101 102 105 protected Collection generatedAttributesRef; 106 107 protected DbKeyGenerator primaryKeyGenerator; 108 109 112 public DbEntity() { 113 super(); 114 115 this.primaryKey = new ArrayList (2); 116 this.primaryKeyRef = Collections.unmodifiableList(primaryKey); 117 118 this.generatedAttributes = new ArrayList (2); 119 this.generatedAttributesRef = Collections 120 .unmodifiableCollection(generatedAttributes); 121 } 122 123 126 public DbEntity(String name) { 127 this(); 128 this.setName(name); 129 } 130 131 136 public void encodeAsXML(XMLEncoder encoder) { 137 encoder.print("<db-entity name=\""); 138 encoder.print(Util.encodeXmlAttribute(getName())); 139 encoder.print('\"'); 140 141 if (getSchema() != null && getSchema().trim().length() > 0) { 142 encoder.print(" schema=\""); 143 encoder.print(Util.encodeXmlAttribute(getSchema().trim())); 144 encoder.print('\"'); 145 } 146 147 if (getCatalog() != null && getCatalog().trim().length() > 0) { 148 encoder.print(" catalog=\""); 149 encoder.print(Util.encodeXmlAttribute(getCatalog().trim())); 150 encoder.print('\"'); 151 } 152 153 encoder.println('>'); 154 155 encoder.indent(1); 156 encoder.print(getAttributeMap()); 157 158 if (getPrimaryKeyGenerator() != null) { 159 getPrimaryKeyGenerator().encodeAsXML(encoder); 160 } 161 162 encoder.indent(-1); 163 encoder.println("</db-entity>"); 164 } 165 166 169 public String getFullyQualifiedName() { 170 return (schema != null) ? schema + '.' + getName() : getName(); 171 } 172 173 178 public String getSchema() { 179 return schema; 180 } 181 182 185 public void setSchema(String schema) { 186 this.schema = schema; 187 } 188 189 192 public String getCatalog() { 193 return catalog; 194 } 195 196 199 public void setCatalog(String catalog) { 200 this.catalog = catalog; 201 } 202 203 207 public List getPrimaryKey() { 208 return primaryKeyRef; 209 } 210 211 217 public Collection getGeneratedAttributes() { 218 return generatedAttributesRef; 219 } 220 221 public void addAttribute(Attribute attr) { 222 super.addAttribute(attr); 223 this.dbAttributeAdded(new AttributeEvent(this, attr, this, MapEvent.ADD)); 224 } 225 226 232 public void removeAttribute(String attrName) { 233 Attribute attr = getAttribute(attrName); 234 if (attr == null) { 235 return; 236 } 237 238 DataMap map = getDataMap(); 239 if (map != null) { 240 Iterator ents = map.getDbEntities().iterator(); 241 while (ents.hasNext()) { 242 DbEntity ent = (DbEntity) ents.next(); 243 Iterator it = ent.getRelationships().iterator(); 244 while (it.hasNext()) { 245 DbRelationship rel = (DbRelationship) it.next(); 246 Iterator joins = rel.getJoins().iterator(); 247 while (joins.hasNext()) { 248 DbJoin join = (DbJoin) joins.next(); 249 if (join.getSource() == attr || join.getTarget() == attr) { 250 joins.remove(); 251 } 252 } 253 } 254 } 255 } 256 257 super.removeAttribute(attrName); 258 this.dbAttributeRemoved(new AttributeEvent(this, attr, this, MapEvent.REMOVE)); 259 } 260 261 public void clearAttributes() { 262 super.clearAttributes(); 263 this.dbAttributeRemoved(new AttributeEvent(this, null, this, MapEvent.REMOVE)); 265 } 266 267 public Iterator resolvePathComponents(Expression pathExp) throws ExpressionException { 268 if (pathExp.getType() != Expression.DB_PATH) { 269 throw new ExpressionException("Invalid expression type: '" 270 + pathExp.expName() 271 + "', DB_PATH is expected."); 272 } 273 274 return new PathIterator((String ) pathExp.getOperand(0)); 275 } 276 277 public void setPrimaryKeyGenerator(DbKeyGenerator primaryKeyGenerator) { 278 this.primaryKeyGenerator = primaryKeyGenerator; 279 if (primaryKeyGenerator != null) { 280 primaryKeyGenerator.setDbEntity(this); 281 } 282 } 283 284 public DbKeyGenerator getPrimaryKeyGenerator() { 285 return primaryKeyGenerator; 286 } 287 288 295 public void dbEntityChanged(EntityEvent e){ 296 if ((e == null) || (e.getEntity() != this)) { 297 return; 299 } 300 301 if (e.getId() == EntityEvent.CHANGE && e.isNameChange()){ 303 String newName = e.getNewName(); 304 DataMap map = getDataMap(); 305 if (map != null) { 306 Iterator ents = map.getDbEntities().iterator(); 308 while (ents.hasNext()) { 309 DbEntity dbe = (DbEntity) ents.next(); 310 Iterator rit = dbe.getRelationships().iterator(); 311 while (rit.hasNext()){ 312 DbRelationship rel = (DbRelationship) rit.next(); 313 if (rel.getTargetEntity() == this){ 314 rel.setTargetEntityName(newName); 315 } 316 } 317 } 318 ents = map.getMappedEntities(this).iterator(); 320 while (ents.hasNext()) { 321 ObjEntity oe = (ObjEntity) ents.next(); 322 if (oe.getDbEntity() == this){ 323 oe.setDbEntityName(newName); 324 } 325 } 326 } 327 } 328 } 329 330 331 public void dbEntityAdded(EntityEvent e){ 332 } 334 335 336 public void dbEntityRemoved(EntityEvent e){ 337 } 339 340 public void dbAttributeAdded(AttributeEvent e) { 341 this.handleAttributeUpdate(e); 342 } 343 344 public void dbAttributeChanged(AttributeEvent e) { 345 this.handleAttributeUpdate(e); 346 } 347 348 public void dbAttributeRemoved(AttributeEvent e) { 349 this.handleAttributeUpdate(e); 350 } 351 352 private void handleAttributeUpdate(AttributeEvent e) { 353 if ((e == null) || (e.getEntity() != this)) { 354 return; 356 } 357 358 Attribute attr = e.getAttribute(); 360 if ((attr == null) && (this.attributes.isEmpty())) { 361 this.primaryKey.clear(); 362 this.generatedAttributes.clear(); 363 return; 364 } 365 366 if (!(attr instanceof DbAttribute)) { 368 return; 369 } 370 371 DbAttribute dbAttr = (DbAttribute) attr; 372 373 if (e.getId() == AttributeEvent.CHANGE && e.isNameChange()){ 375 String oldName = e.getOldName(); 376 String newName = e.getNewName(); 377 378 DataMap map = getDataMap(); 379 if (map != null) { 380 Iterator ents = map.getDbEntities().iterator(); 381 while (ents.hasNext()) { 382 DbEntity ent = (DbEntity) ents.next(); 383 384 Iterator it = map.getMappedEntities(ent).iterator(); 386 while (it.hasNext()) { 387 ObjEntity oe = (ObjEntity) it.next(); 388 Iterator ait = oe.getAttributes().iterator(); 389 while (ait.hasNext()) { 390 ObjAttribute oa = (ObjAttribute) ait.next(); 391 if (oa.getDbAttribute() == dbAttr){ 392 oa.setDbAttributeName(newName); 393 } 394 } 395 } 396 397 it = ent.getRelationships().iterator(); 399 while (it.hasNext()) { 400 DbRelationship rel = (DbRelationship) it.next(); 401 Iterator joins = rel.getJoins().iterator(); 402 while (joins.hasNext()) { 403 DbJoin join = (DbJoin) joins.next(); 404 if (join.getSource() == dbAttr){ 405 join.setSourceName(newName); 406 } 407 if (join.getTarget() == dbAttr){ 408 join.setTargetName(newName); 409 } 410 } 411 } 412 } 413 } 414 415 attributes.remove(oldName); 417 418 attributes.put(newName, dbAttr); 420 } 421 422 if (primaryKey.contains(dbAttr) || dbAttr.isPrimaryKey()) { 424 switch (e.getId()) { 425 case MapEvent.ADD: 426 this.primaryKey.add(attr); 427 break; 428 429 case MapEvent.REMOVE: 430 this.primaryKey.remove(attr); 431 break; 432 433 default: 434 this.primaryKey.clear(); 436 Iterator it = this.getAttributes().iterator(); 437 while (it.hasNext()) { 438 DbAttribute dba = (DbAttribute) it.next(); 439 if (dba.isPrimaryKey()) { 440 this.primaryKey.add(dba); 441 } 442 } 443 } 444 } 445 446 if (generatedAttributes.contains(dbAttr) || dbAttr.isGenerated()) { 448 switch (e.getId()) { 449 case MapEvent.ADD: 450 this.generatedAttributes.add(attr); 451 break; 452 453 case MapEvent.REMOVE: 454 this.generatedAttributes.remove(attr); 455 break; 456 457 default: 458 this.generatedAttributes.clear(); 460 Iterator it = this.getAttributes().iterator(); 461 while (it.hasNext()) { 462 DbAttribute dba = (DbAttribute) it.next(); 463 if (dba.isGenerated()) { 464 this.generatedAttributes.add(dba); 465 } 466 } 467 } 468 } 469 } 470 471 472 public void dbRelationshipChanged(RelationshipEvent e){ 473 if ((e == null) || (e.getEntity() != this)) { 474 return; 476 } 477 478 Relationship rel = e.getRelationship(); 479 if (!(rel instanceof DbRelationship)) { 481 return; 482 } 483 484 DbRelationship dbRel = (DbRelationship) rel; 485 486 if (e.getId() == RelationshipEvent.CHANGE && e.isNameChange()){ 488 String oldName = e.getOldName(); 489 String newName = e.getNewName(); 490 491 DataMap map = getDataMap(); 492 if (map != null) { 493 Iterator ents = map.getObjEntities().iterator(); 495 while (ents.hasNext()) { 496 ObjEntity oe = (ObjEntity) ents.next(); 497 Iterator rit = oe.getRelationships().iterator(); 498 while (rit.hasNext()) { 499 ObjRelationship or = (ObjRelationship) rit.next(); 500 if (or.getDbRelationshipPath().equals(oldName)){ 502 or.setDbRelationshipPath(newName); 503 } 504 } 505 } 506 } 507 508 relationships.remove(oldName); 510 511 relationships.put(newName, dbRel); 513 } 514 } 515 516 517 public void dbRelationshipAdded(RelationshipEvent e){ 518 } 520 521 522 public void dbRelationshipRemoved(RelationshipEvent e){ 523 } 525 526 532 public boolean isFullReplacementIdAttached(ObjectId id) { 533 if (!id.isReplacementIdAttached()) { 534 return false; 535 } 536 537 Map replacement = id.getReplacementIdMap(); 538 Collection pk = getPrimaryKey(); 539 if(pk.size() != replacement.size()) { 540 return false; 541 } 542 543 Iterator it = pk.iterator(); 544 while(it.hasNext()) { 545 DbAttribute attribute = (DbAttribute) it.next(); 546 if(!replacement.containsKey(attribute.getName())) { 547 return false; 548 } 549 } 550 551 return true; 552 } 553 554 560 public Expression translateToRelatedEntity( 561 Expression expression, 562 String relationshipPath) { 563 564 if (expression == null) { 565 return null; 566 } 567 568 if (relationshipPath == null) { 569 return expression; 570 } 571 572 return expression.transform(new RelationshipPathConverter(relationshipPath)); 573 } 574 575 final class RelationshipPathConverter implements Transformer { 576 577 String relationshipPath; 578 579 RelationshipPathConverter(String relationshipPath) { 580 this.relationshipPath = relationshipPath; 581 } 582 583 public Object transform(Object input) { 584 if (!(input instanceof Expression)) { 585 return input; 586 } 587 588 Expression expression = (Expression) input; 589 590 if (expression.getType() != Expression.DB_PATH) { 591 return input; 592 } 593 594 String path = (String ) expression.getOperand(0); 595 String converted = translatePath(path); 596 Expression transformed = ExpressionFactory 597 .expressionOfType(Expression.DB_PATH); 598 transformed.setOperand(0, converted); 599 return transformed; 600 } 601 602 String translatePath(String path) { 603 604 615 if (path.equals(relationshipPath)) { 617 618 LinkedList finalPath = new LinkedList (); 619 Iterator it = resolvePathComponents(path); 620 621 DbRelationship lastDBR = null; 624 625 while (it.hasNext()) { 626 lastDBR = (DbRelationship) it.next(); 628 } 629 630 if (lastDBR != null) { 631 prependReversedPath(finalPath, lastDBR); 632 appendPath(finalPath, lastDBR); 633 } 634 635 return convertToPath(finalPath); 636 } 637 638 String relationshipPathWithDot = relationshipPath + Entity.PATH_SEPARATOR; 640 if (path.startsWith(relationshipPathWithDot)) { 641 return path.substring(relationshipPathWithDot.length()); 642 } 643 644 Iterator pathIt = resolvePathComponents(path); 646 Iterator relationshipIt = resolvePathComponents(relationshipPath); 647 648 LinkedList finalPath = new LinkedList (); 650 651 while (relationshipIt.hasNext() && pathIt.hasNext()) { 652 DbRelationship nextDBR = (DbRelationship) relationshipIt.next(); 654 655 MapObject next = (MapObject) pathIt.next(); 657 658 if (nextDBR != next) { 659 prependReversedPath(finalPath, nextDBR); 663 appendPath(finalPath, next); 664 break; 665 } 666 667 break; 668 } 669 670 while (relationshipIt.hasNext()) { 672 DbRelationship nextDBR = (DbRelationship) relationshipIt.next(); 673 prependReversedPath(finalPath, nextDBR); 674 } 675 676 while (pathIt.hasNext()) { 677 MapObject next = (MapObject) pathIt.next(); 679 appendPath(finalPath, next); 680 } 681 682 return convertToPath(finalPath); 683 } 684 685 private String convertToPath(List path) { 686 StringBuffer converted = new StringBuffer (); 687 int len = path.size(); 688 for (int i = 0; i < len; i++) { 689 if (i > 0) { 690 converted.append(Entity.PATH_SEPARATOR); 691 } 692 693 converted.append(path.get(i)); 694 } 695 696 return converted.toString(); 697 } 698 699 private void prependReversedPath(LinkedList finalPath, DbRelationship relationship) { 700 DbRelationship revNextDBR = relationship.getReverseRelationship(); 701 702 if (revNextDBR == null) { 703 throw new CayenneRuntimeException( 704 "Unable to find reverse DbRelationship for " 705 + relationship.getSourceEntity().getName() 706 + Entity.PATH_SEPARATOR 707 + relationship.getName() 708 + "."); 709 } 710 711 finalPath.addFirst(revNextDBR.getName()); 712 } 713 714 private void appendPath(LinkedList finalPath, MapObject pathComponent) { 715 finalPath.addLast(pathComponent.getName()); 716 } 717 } 718 } | Popular Tags |