1 19 20 package org.apache.cayenne.map; 21 22 import java.util.ArrayList ; 23 import java.util.Arrays ; 24 import java.util.Collection ; 25 import java.util.Collections ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.SortedMap ; 30 import java.util.TreeMap ; 31 32 import org.apache.cayenne.CayenneRuntimeException; 33 import org.apache.cayenne.exp.Expression; 34 import org.apache.cayenne.exp.ExpressionException; 35 import org.apache.cayenne.exp.ExpressionFactory; 36 import org.apache.cayenne.map.event.AttributeEvent; 37 import org.apache.cayenne.map.event.EntityEvent; 38 import org.apache.cayenne.map.event.ObjAttributeListener; 39 import org.apache.cayenne.map.event.ObjEntityListener; 40 import org.apache.cayenne.map.event.ObjRelationshipListener; 41 import org.apache.cayenne.map.event.RelationshipEvent; 42 import org.apache.cayenne.util.CayenneMapEntry; 43 import org.apache.cayenne.util.Util; 44 import org.apache.cayenne.util.XMLEncoder; 45 import org.apache.commons.collections.Transformer; 46 47 54 public class ObjEntity extends Entity implements ObjEntityListener, ObjAttributeListener, 55 ObjRelationshipListener { 56 57 final public static int LOCK_TYPE_NONE = 0; 58 final public static int LOCK_TYPE_OPTIMISTIC = 1; 59 60 static final String CAYENNE_DATA_OBJECT_CLASS = "org.apache.cayenne.CayenneDataObject"; 62 67 protected static final Collection DEFAULT_GENERIC_CLASSES = Arrays 68 .asList(new String [] { 69 CAYENNE_DATA_OBJECT_CLASS 70 }); 71 72 protected String superClassName; 73 protected String className; 74 protected String dbEntityName; 75 protected String superEntityName; 76 protected Expression qualifier; 77 protected boolean readOnly; 78 protected int lockType; 79 80 protected boolean serverOnly; 81 protected String clientClassName; 82 protected String clientSuperClassName; 83 84 protected List entityListeners; 85 protected CallbackMap callbacks; 86 protected boolean excludingDefaultListeners; 87 protected boolean excludingSuperclassListeners; 88 89 public ObjEntity() { 90 this(null); 91 } 92 93 public ObjEntity(String name) { 94 setName(name); 95 this.lockType = LOCK_TYPE_NONE; 96 this.callbacks = new CallbackMap(); 97 this.entityListeners = new ArrayList (2); 98 } 99 100 105 public void encodeAsXML(XMLEncoder encoder) { 106 encoder.print("<obj-entity name=\""); 107 encoder.print(getName()); 108 109 if (getSuperEntityName() != null && getSuperEntity() != null) { 111 encoder.print("\" superEntityName=\""); 112 encoder.print(getSuperEntityName()); 113 } 114 115 if (isServerOnly()) { 116 encoder.print("\" serverOnly=\"true"); 117 } 118 119 if (getClassName() != null) { 120 encoder.print("\" className=\""); 121 encoder.print(getClassName()); 122 } 123 124 if (getClientClassName() != null) { 125 encoder.print("\" clientClassName=\""); 126 encoder.print(getClientClassName()); 127 } 128 129 if (isReadOnly()) { 130 encoder.print("\" readOnly=\"true"); 131 } 132 133 if (getDeclaredLockType() == LOCK_TYPE_OPTIMISTIC) { 134 encoder.print("\" lock-type=\"optimistic"); 135 } 136 137 if (getSuperEntityName() == null && getDbEntity() != null) { 138 encoder.print("\" dbEntityName=\""); 139 encoder.print(Util.encodeXmlAttribute(getDbEntityName())); 140 } 141 142 if (getSuperEntityName() == null && getSuperClassName() != null) { 143 encoder.print("\" superClassName=\""); 144 encoder.print(getSuperClassName()); 145 } 146 147 if (getSuperEntityName() == null && getClientSuperClassName() != null) { 148 encoder.print("\" clientSuperClassName=\""); 149 encoder.print(getClientSuperClassName()); 150 } 151 152 encoder.println("\">"); 153 encoder.indent(1); 154 155 if (qualifier != null) { 156 encoder.print("<qualifier>"); 157 qualifier.encodeAsXML(encoder); 158 encoder.println("</qualifier>"); 159 } 160 161 encoder.print(getDeclaredAttributes()); 163 164 encoder.indent(-1); 165 encoder.println("</obj-entity>"); 166 } 167 168 175 public ObjEntity getClientEntity() { 176 177 ObjEntity entity = new ObjEntity(getName()); 178 entity.setClassName(getClientClassName()); 179 entity.setSuperClassName(getClientSuperClassName()); 180 entity.setSuperEntityName(getSuperEntityName()); 181 182 184 Iterator attributes = getDeclaredAttributes().iterator(); 186 while (attributes.hasNext()) { 187 ObjAttribute attribute = (ObjAttribute) attributes.next(); 188 entity.addAttribute(attribute.getClientAttribute()); 189 } 190 191 Iterator relationships = getDeclaredRelationships().iterator(); 193 while (relationships.hasNext()) { 194 ObjRelationship relationship = (ObjRelationship) relationships.next(); 195 entity.addRelationship(relationship.getClientRelationship()); 196 } 197 198 201 return entity; 202 } 203 204 209 String getJavaClassName() { 210 String name = getClassName(); 211 212 if (name == null && getDataMap() != null) { 213 name = getDataMap().getDefaultSuperclass(); 214 } 215 216 if (name == null) { 217 name = CAYENNE_DATA_OBJECT_CLASS; 218 } 219 220 return name; 221 } 222 223 231 public Class getJavaClass() { 232 String name = getJavaClassName(); 233 234 try { 235 return Util.getJavaClass(name); 236 } 237 catch (ClassNotFoundException e) { 238 throw new CayenneRuntimeException("Failed to load class " 239 + name 240 + ": " 241 + e.getMessage(), e); 242 } 243 } 244 245 252 public List getEntityListeners() { 253 return Collections.unmodifiableList(entityListeners); 254 } 255 256 263 public void addEntityListener(EntityListener listener) { 264 Iterator it = entityListeners.iterator(); 265 while (it.hasNext()) { 266 EntityListener next = (EntityListener) it.next(); 267 if (listener.getClassName().equals(next.getClassName())) { 268 throw new IllegalArgumentException ("Duplicate listener for " 269 + next.getClassName()); 270 } 271 } 272 273 entityListeners.add(listener); 274 } 275 276 281 public void removeEntityListener(String className) { 282 Iterator it = entityListeners.iterator(); 283 while (it.hasNext()) { 284 EntityListener next = (EntityListener) it.next(); 285 if (className.equals(next.getClassName())) { 286 it.remove(); 287 break; 288 } 289 } 290 } 291 292 295 public EntityListener getEntityListener(String className) { 296 Iterator it = entityListeners.iterator(); 297 while (it.hasNext()) { 298 EntityListener next = (EntityListener) it.next(); 299 if (className.equals(next.getClassName())) { 300 return next; 301 } 302 } 303 304 return null; 305 } 306 307 312 public CallbackMap getCallbackMap() { 313 return callbacks; 314 } 315 316 323 public int getLockType() { 324 if (lockType != LOCK_TYPE_NONE) { 327 return lockType; 328 } 329 330 ObjEntity superEntity = getSuperEntity(); 331 return (superEntity != null) ? superEntity.getLockType() : lockType; 332 } 333 334 340 public int getDeclaredLockType() { 341 return lockType; 342 } 343 344 349 public void setDeclaredLockType(int i) { 350 lockType = i; 351 } 352 353 360 public boolean isGeneric() { 361 String className = getClassName(); 362 return className == null 363 || DEFAULT_GENERIC_CLASSES.contains(className) 364 || (getDataMap() != null && className.equals(getDataMap() 365 .getDefaultSuperclass())); 366 } 367 368 375 public boolean isClientAllowed() { 376 return (getDataMap() == null || isServerOnly()) ? false : getDataMap() 377 .isClientSupported(); 378 } 379 380 385 public boolean isServerOnly() { 386 return serverOnly; 387 } 388 389 394 public void setServerOnly(boolean serverOnly) { 395 this.serverOnly = serverOnly; 396 } 397 398 405 public Expression getDeclaredQualifier() { 406 return qualifier; 407 } 408 409 414 public String getSuperEntityName() { 415 return superEntityName; 416 } 417 418 423 public void setDeclaredQualifier(Expression qualifier) { 424 this.qualifier = qualifier; 425 } 426 427 432 public void setSuperEntityName(String superEntityName) { 433 this.superEntityName = superEntityName; 434 } 435 436 439 public String getClassName() { 440 return className; 441 } 442 443 446 public void setClassName(String className) { 447 this.className = className; 448 } 449 450 455 public String getClientClassName() { 456 return clientClassName; 457 } 458 459 464 public void setClientClassName(String clientClassName) { 465 this.clientClassName = clientClassName; 466 } 467 468 473 public String getSuperClassName() { 474 ObjEntity superEntity = getSuperEntity(); 475 return (superEntity != null) ? superEntity.getClassName() : superClassName; 476 } 477 478 486 public void setSuperClassName(String superClassName) { 487 this.superClassName = superClassName; 488 } 489 490 497 public String getClientSuperClassName() { 498 ObjEntity superEntity = getSuperEntity(); 499 return (superEntity != null) 500 ? superEntity.getClientClassName() 501 : clientSuperClassName; 502 } 503 504 514 public void setClientSuperClassName(String clientSuperClassName) { 515 this.clientSuperClassName = clientSuperClassName; 516 } 517 518 523 public ObjEntity getSuperEntity() { 524 return (superEntityName != null) ? getNonNullNamespace().getObjEntity( 525 superEntityName) : null; 526 } 527 528 531 public DbEntity getDbEntity() { 532 533 if (dbEntityName != null) { 535 return getNonNullNamespace().getDbEntity(dbEntityName); 536 } 537 538 ObjEntity superEntity = getSuperEntity(); 539 if (superEntity != null) { 540 return superEntity.getDbEntity(); 541 } 542 543 return null; 544 } 545 546 553 public void setDbEntity(DbEntity dbEntity) { 554 this.dbEntityName = (dbEntity != null) ? dbEntity.getName() : null; 555 } 556 557 561 public Attribute getAttribute(String name) { 562 Attribute attribute = super.getAttribute(name); 563 if (attribute != null) { 564 return attribute; 565 } 566 567 int dot = name.indexOf('.'); 569 if (dot > 0 && dot < name.length() - 1) { 570 Attribute embedded = getAttribute(name.substring(0, dot)); 571 if (embedded instanceof EmbeddedAttribute) { 572 return ((EmbeddedAttribute) embedded).getAttribute(name 573 .substring(dot + 1)); 574 } 575 } 576 577 if (superEntityName == null) { 578 return null; 579 } 580 581 ObjEntity superEntity = getSuperEntity(); 582 return (superEntity != null) ? superEntity.getAttribute(name) : null; 583 } 584 585 589 public SortedMap getAttributeMap() { 590 if (superEntityName == null) { 591 return super.getAttributeMap(); 592 } 593 594 SortedMap attributeMap = new TreeMap (); 595 appendAttributes(attributeMap); 596 return attributeMap; 597 } 598 599 602 final void appendAttributes(Map map) { 603 map.putAll(super.getAttributeMap()); 604 605 ObjEntity superEntity = getSuperEntity(); 606 if (superEntity != null) { 607 superEntity.appendAttributes(map); 608 } 609 } 610 611 615 public Collection getAttributes() { 616 if (superEntityName == null) { 617 return super.getAttributes(); 618 } 619 620 return getAttributeMap().values(); 621 } 622 623 629 public Collection getDeclaredAttributes() { 630 return super.getAttributes(); 631 } 632 633 637 public Relationship getRelationship(String name) { 638 Relationship relationship = super.getRelationship(name); 639 if (relationship != null) { 640 return relationship; 641 } 642 643 if (superEntityName == null) { 644 return null; 645 } 646 647 ObjEntity superEntity = getSuperEntity(); 648 return (superEntity != null) ? superEntity.getRelationship(name) : null; 649 } 650 651 public SortedMap getRelationshipMap() { 652 if (superEntityName == null) { 653 return super.getRelationshipMap(); 654 } 655 656 SortedMap relationshipMap = new TreeMap (); 657 appendRelationships(relationshipMap); 658 return relationshipMap; 659 } 660 661 664 final void appendRelationships(Map map) { 665 map.putAll(super.getRelationshipMap()); 666 667 ObjEntity superEntity = getSuperEntity(); 668 if (superEntity != null) { 669 superEntity.appendRelationships(map); 670 } 671 } 672 673 public Collection getRelationships() { 674 if (superEntityName == null) { 675 return super.getRelationships(); 676 } 677 678 return getRelationshipMap().values(); 679 } 680 681 687 public Collection getDeclaredRelationships() { 688 return super.getRelationships(); 689 } 690 691 695 public ObjAttribute getAttributeForDbAttribute(DbAttribute dbAttribute) { 696 Iterator it = getAttributeMap().values().iterator(); 697 while (it.hasNext()) { 698 Object next = it.next(); 699 700 if (next instanceof EmbeddedAttribute) { 701 ObjAttribute embeddedAttribute = ((EmbeddedAttribute) next) 702 .getAttributeForDbPath(dbAttribute.getName()); 703 if (embeddedAttribute != null) { 704 return embeddedAttribute; 705 } 706 } 707 else { 708 ObjAttribute objAttr = (ObjAttribute) next; 709 if (objAttr.getDbAttribute() == dbAttribute) { 710 return objAttr; 711 } 712 } 713 } 714 715 return null; 716 } 717 718 722 public ObjRelationship getRelationshipForDbRelationship(DbRelationship dbRelationship) { 723 Iterator it = getRelationshipMap().entrySet().iterator(); 724 while (it.hasNext()) { 725 Map.Entry entry = (Map.Entry ) it.next(); 726 ObjRelationship objRel = (ObjRelationship) entry.getValue(); 727 728 List relList = objRel.getDbRelationships(); 729 if (relList.size() != 1) { 730 continue; 731 } 732 733 if (relList.get(0) == dbRelationship) { 734 return objRel; 735 } 736 } 737 return null; 738 } 739 740 744 public void clearDbMapping() { 745 if (dbEntityName == null) 746 return; 747 748 Iterator it = getAttributeMap().values().iterator(); 749 while (it.hasNext()) { 750 ObjAttribute objAttr = (ObjAttribute) it.next(); 751 DbAttribute dbAttr = objAttr.getDbAttribute(); 752 if (null != dbAttr) { 753 objAttr.setDbAttribute(null); 754 } 755 } 756 757 Iterator rels = this.getRelationships().iterator(); 758 while (rels.hasNext()) { 759 ((ObjRelationship) rels.next()).clearDbRelationships(); 760 } 761 762 dbEntityName = null; 763 } 764 765 771 public boolean isReadOnly() { 772 return readOnly; 773 } 774 775 public void setReadOnly(boolean readOnly) { 776 this.readOnly = readOnly; 777 } 778 779 785 public boolean isSubentityOf(ObjEntity entity) { 786 if (entity == null) { 787 return false; 788 } 789 790 if (entity == this) { 791 return false; 792 } 793 794 ObjEntity superEntity = getSuperEntity(); 795 if (superEntity == entity) { 796 return true; 797 } 798 799 return (superEntity != null) ? superEntity.isSubentityOf(entity) : false; 800 } 801 802 public Iterator resolvePathComponents(Expression pathExp) throws ExpressionException { 803 804 if (pathExp.getType() == Expression.DB_PATH) { 806 if (getDbEntity() == null) { 807 throw new ExpressionException("Can't resolve DB_PATH '" 808 + pathExp 809 + "', DbEntity is not set."); 810 } 811 812 return getDbEntity().resolvePathComponents(pathExp); 813 } 814 815 if (pathExp.getType() == Expression.OBJ_PATH) { 816 return new PathIterator((String ) pathExp.getOperand(0)); 817 } 818 819 throw new ExpressionException("Invalid expression type: '" 820 + pathExp.expName() 821 + "', OBJ_PATH is expected."); 822 } 823 824 830 public Expression translateToDbPath(Expression expression) { 831 832 if (expression == null) { 833 return null; 834 } 835 836 if (getDbEntity() == null) { 837 throw new CayenneRuntimeException( 838 "Can't translate expression to DB_PATH, no DbEntity for '" 839 + getName() 840 + "'."); 841 } 842 843 return expression.transform(new DBPathConverter()); 846 } 847 848 854 public Expression translateToRelatedEntity( 855 Expression expression, 856 String relationshipPath) { 857 858 if (expression == null) { 859 return null; 860 } 861 862 if (relationshipPath == null) { 863 return expression; 864 } 865 866 if (getDbEntity() == null) { 867 throw new CayenneRuntimeException( 868 "Can't transform expression, no DbEntity for '" + getName() + "'."); 869 } 870 871 874 DBPathConverter transformer = new DBPathConverter(); 875 876 String dbPath = transformer.toDbPath(resolvePathComponents(relationshipPath)); 877 Expression dbClone = expression.transform(transformer); 878 879 return getDbEntity().translateToRelatedEntity(dbClone, dbPath); 880 } 881 882 final class DBPathConverter implements Transformer { 883 884 String toDbPath(Iterator objectPathComponents) { 887 StringBuffer buf = new StringBuffer (); 888 while (objectPathComponents.hasNext()) { 889 Object component = objectPathComponents.next(); 890 891 Iterator dbSubpath; 892 893 if (component instanceof ObjRelationship) { 894 dbSubpath = ((ObjRelationship) component) 895 .getDbRelationships() 896 .iterator(); 897 } 898 else if (component instanceof ObjAttribute) { 899 dbSubpath = ((ObjAttribute) component).getDbPathIterator(); 900 } 901 else { 902 throw new CayenneRuntimeException("Unknown path component: " 903 + component); 904 } 905 906 while (dbSubpath.hasNext()) { 907 CayenneMapEntry subComponent = (CayenneMapEntry) dbSubpath.next(); 908 if (buf.length() > 0) { 909 buf.append(Entity.PATH_SEPARATOR); 910 } 911 912 buf.append(subComponent.getName()); 913 } 914 } 915 916 return buf.toString(); 917 } 918 919 public Object transform(Object input) { 920 921 if (!(input instanceof Expression)) { 922 return input; 923 } 924 925 Expression expression = (Expression) input; 926 927 if (expression.getType() != Expression.OBJ_PATH) { 928 return input; 929 } 930 931 933 String converted = toDbPath(resolvePathComponents(expression)); 934 Expression exp = ExpressionFactory.expressionOfType(Expression.DB_PATH); 935 exp.setOperand(0, converted); 936 return exp; 937 } 938 } 939 940 945 public String getDbEntityName() { 946 return dbEntityName; 947 } 948 949 954 public void setDbEntityName(String string) { 955 dbEntityName = string; 956 } 957 958 965 public void objEntityChanged(EntityEvent e) { 966 if ((e == null) || (e.getEntity() != this)) { 967 return; 969 } 970 971 if (e.getId() == EntityEvent.CHANGE && e.isNameChange()) { 973 String oldName = e.getOldName(); 974 String newName = e.getNewName(); 975 976 DataMap map = getDataMap(); 977 if (map != null) { 978 ObjEntity oe = (ObjEntity) e.getEntity(); 979 Iterator rit = oe.getRelationships().iterator(); 980 while (rit.hasNext()) { 981 ObjRelationship or = (ObjRelationship) rit.next(); 982 or = or.getReverseRelationship(); 983 if (null != or && or.targetEntityName.equals(oldName)) { 984 or.targetEntityName = newName; 985 } 986 } 987 } 988 } 989 } 990 991 992 public void objEntityAdded(EntityEvent e) { 993 } 995 996 997 public void objEntityRemoved(EntityEvent e) { 998 } 1000 1001 1002 public void objAttributeChanged(AttributeEvent e) { 1003 } 1005 1006 1007 public void objAttributeAdded(AttributeEvent e) { 1008 } 1010 1011 1012 public void objAttributeRemoved(AttributeEvent e) { 1013 } 1015 1016 1017 public void objRelationshipChanged(RelationshipEvent e) { 1018 } 1020 1021 1022 public void objRelationshipAdded(RelationshipEvent e) { 1023 } 1025 1026 1027 public void objRelationshipRemoved(RelationshipEvent e) { 1028 } 1030 1031 1037 public boolean isExcludingDefaultListeners() { 1038 return excludingDefaultListeners; 1039 } 1040 1041 public void setExcludingDefaultListeners(boolean excludingDefaultListeners) { 1042 this.excludingDefaultListeners = excludingDefaultListeners; 1043 } 1044 1045 1051 public boolean isExcludingSuperclassListeners() { 1052 return excludingSuperclassListeners; 1053 } 1054 1055 public void setExcludingSuperclassListeners(boolean excludingSuperclassListeners) { 1056 this.excludingSuperclassListeners = excludingSuperclassListeners; 1057 } 1058 1059} 1060 | Popular Tags |