1 package xdoclet.modules.ojb.model; 2 3 17 18 import java.util.*; 19 20 import xdoclet.modules.ojb.CommaListIterator; 21 import xdoclet.modules.ojb.LogHelper; 22 import xdoclet.modules.ojb.constraints.*; 23 import xjavadoc.XClass; 24 25 30 public class ClassDescriptorDef extends DefBase 31 { 32 33 private XClass _origin; 34 35 private HashMap _directBaseTypes = new HashMap(); 36 37 private ArrayList _extents = new ArrayList(); 38 39 private ArrayList _fields = new ArrayList(); 40 41 private ArrayList _references = new ArrayList(); 42 43 private ArrayList _collections = new ArrayList(); 44 45 private ArrayList _nested = new ArrayList(); 46 48 private HashMap _modifications = new HashMap(); 49 50 private ArrayList _indexDescriptors = new ArrayList(); 51 52 private ObjectCacheDef _objectCache = null; 53 54 private SortedMap _procedures = new TreeMap(); 55 56 private HashMap _procedureArguments = new HashMap(); 57 58 private boolean _hasBeenProcessed = false; 59 60 65 public ClassDescriptorDef(XClass origin) 66 { 67 super(origin.getTransformedQualifiedName()); 68 _origin = origin; 69 } 70 71 76 public XClass getOriginalClass() 77 { 78 return _origin; 79 } 80 81 86 public String getQualifiedName() 87 { 88 return getName().replace('$', '.'); 89 } 90 91 96 public String getDefaultTableName() 97 { 98 String name = getName(); 99 int lastDotPos = name.lastIndexOf('.'); 100 int lastDollarPos = name.lastIndexOf('$'); 101 102 return lastDollarPos > lastDotPos ? name.substring(lastDollarPos + 1) : name.substring(lastDotPos + 1); 103 } 104 105 110 boolean hasBeenProcessed() 111 { 112 return _hasBeenProcessed; 113 } 114 115 121 public void process() throws ConstraintException 122 { 123 ClassDescriptorDef otherClassDef; 124 125 for (Iterator it = getDirectBaseTypes(); it.hasNext();) 126 { 127 otherClassDef = (ClassDescriptorDef)it.next(); 128 if (!otherClassDef.hasBeenProcessed()) 129 { 130 otherClassDef.process(); 131 } 132 } 133 for (Iterator it = getNested(); it.hasNext();) 134 { 135 otherClassDef = ((NestedDef)it.next()).getNestedType(); 136 if (!otherClassDef.hasBeenProcessed()) 137 { 138 otherClassDef.process(); 139 } 140 } 141 142 ArrayList newFields = new ArrayList(); 143 ArrayList newReferences = new ArrayList(); 144 ArrayList newCollections = new ArrayList(); 145 FieldDescriptorDef newFieldDef; 146 ReferenceDescriptorDef newRefDef; 147 CollectionDescriptorDef newCollDef; 148 149 if (getBooleanProperty(PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED, true)) 151 { 152 ArrayList baseTypes = new ArrayList(); 153 DefBase featureDef; 154 155 addRelevantBaseTypes(this, baseTypes); 156 for (Iterator it = baseTypes.iterator(); it.hasNext();) 157 { 158 cloneInheritedFeatures((ClassDescriptorDef)it.next(), newFields, newReferences, newCollections); 159 } 160 161 for (Iterator it = newFields.iterator(); it.hasNext();) 162 { 163 newFieldDef = (FieldDescriptorDef)it.next(); 164 featureDef = getFeature(newFieldDef.getName()); 165 if (featureDef != null) 166 { 167 if (!getBooleanProperty(PropertyHelper.OJB_PROPERTY_IGNORE, false)) 168 { 169 if ("anonymous".equals(featureDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS))) 172 { 173 throw new ConstraintException("The anonymous field "+featureDef.getName()+" in class "+getName()+" overrides an inherited field"); 174 } 175 if ("anonymous".equals(newFieldDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS))) 176 { 177 throw new ConstraintException("The inherited anonymous field "+newFieldDef.getName()+" is overriden in class "+getName()); 178 } 179 } 180 LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited field "+newFieldDef.getName()); 181 it.remove(); 182 } 183 } 184 for (Iterator it = newReferences.iterator(); it.hasNext();) 185 { 186 newRefDef = (ReferenceDescriptorDef)it.next(); 187 if ("super".equals(newRefDef.getName())) 188 { 189 it.remove(); 191 } 192 else if (hasFeature(newRefDef.getName())) 193 { 194 LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited reference "+newRefDef.getName()); 195 it.remove(); 196 } 197 } 198 for (Iterator it = newCollections.iterator(); it.hasNext();) 199 { 200 newCollDef = (CollectionDescriptorDef)it.next(); 201 if (hasFeature(newCollDef.getName())) 202 { 203 LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited collection "+newCollDef.getName()); 204 it.remove(); 205 } 206 } 207 } 208 for (Iterator it = getNested(); it.hasNext();) 210 { 211 cloneNestedFeatures((NestedDef)it.next(), newFields, newReferences, newCollections); 212 } 213 _fields.addAll(0, newFields); 214 _references.addAll(0, newReferences); 215 _collections.addAll(0, newCollections); 216 sortFields(); 217 _hasBeenProcessed = true; 218 } 219 220 223 private void sortFields() 224 { 225 HashMap fields = new HashMap(); 226 ArrayList fieldsWithId = new ArrayList(); 227 ArrayList fieldsWithoutId = new ArrayList(); 228 FieldDescriptorDef fieldDef; 229 230 for (Iterator it = getFields(); it.hasNext(); ) 231 { 232 fieldDef = (FieldDescriptorDef)it.next(); 233 fields.put(fieldDef.getName(), fieldDef); 234 if (fieldDef.hasProperty(PropertyHelper.OJB_PROPERTY_ID)) 235 { 236 fieldsWithId.add(fieldDef.getName()); 237 } 238 else 239 { 240 fieldsWithoutId.add(fieldDef.getName()); 241 } 242 } 243 244 Collections.sort(fieldsWithId, new FieldWithIdComparator(fields)); 245 246 ArrayList result = new ArrayList(); 247 248 for (Iterator it = fieldsWithId.iterator(); it.hasNext();) 249 { 250 result.add(getField((String )it.next())); 251 } 252 for (Iterator it = fieldsWithoutId.iterator(); it.hasNext();) 253 { 254 result.add(getField((String )it.next())); 255 } 256 257 _fields = result; 258 } 259 260 266 public void checkConstraints(String checkLevel) throws ConstraintException 267 { 268 FieldDescriptorConstraints fieldConstraints = new FieldDescriptorConstraints(); 270 ReferenceDescriptorConstraints refConstraints = new ReferenceDescriptorConstraints(); 271 CollectionDescriptorConstraints collConstraints = new CollectionDescriptorConstraints(); 272 273 for (Iterator it = getFields(); it.hasNext();) 274 { 275 fieldConstraints.check((FieldDescriptorDef)it.next(), checkLevel); 276 } 277 for (Iterator it = getReferences(); it.hasNext();) 278 { 279 refConstraints.check((ReferenceDescriptorDef)it.next(), checkLevel); 280 } 281 for (Iterator it = getCollections(); it.hasNext();) 282 { 283 collConstraints.check((CollectionDescriptorDef)it.next(), checkLevel); 284 } 285 new ClassDescriptorConstraints().check(this, checkLevel); 286 } 287 288 294 private void addRelevantBaseTypes(ClassDescriptorDef curType, ArrayList baseTypes) 295 { 296 ClassDescriptorDef baseDef; 297 298 for (Iterator it = curType.getDirectBaseTypes(); it.hasNext();) 299 { 300 baseDef = (ClassDescriptorDef)it.next(); 301 if (!baseDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED, true)) 302 { 303 addRelevantBaseTypes(baseDef, baseTypes); 307 } 308 baseTypes.add(baseDef); 309 } 310 } 311 312 319 private boolean contains(ArrayList defs, DefBase obj) 320 { 321 for (Iterator it = defs.iterator(); it.hasNext();) 322 { 323 if (obj.getName().equals(((DefBase)it.next()).getName())) 324 { 325 return true; 326 } 327 } 328 return false; 329 } 330 331 340 private void cloneInheritedFeatures(ClassDescriptorDef baseDef, ArrayList newFields, ArrayList newReferences, ArrayList newCollections) 341 { 342 FieldDescriptorDef copyFieldDef; 343 ReferenceDescriptorDef copyRefDef; 344 CollectionDescriptorDef copyCollDef; 345 346 for (Iterator fieldIt = baseDef.getFields(); fieldIt.hasNext();) 349 { 350 copyFieldDef = cloneField((FieldDescriptorDef)fieldIt.next(), null); 351 if (!contains(newFields, copyFieldDef)) 352 { 353 copyFieldDef.setInherited(); 354 newFields.add(copyFieldDef); 355 } 356 } 357 for (Iterator refIt = baseDef.getReferences(); refIt.hasNext();) 358 { 359 copyRefDef = cloneReference((ReferenceDescriptorDef)refIt.next(), null); 360 if (!contains(newReferences, copyRefDef)) 361 { 362 copyRefDef.setInherited(); 363 newReferences.add(copyRefDef); 364 } 365 } 366 for (Iterator collIt = baseDef.getCollections(); collIt.hasNext();) 367 { 368 copyCollDef = cloneCollection((CollectionDescriptorDef)collIt.next(), null); 369 if (!contains(newCollections, copyCollDef)) 370 { 371 copyCollDef.setInherited(); 372 newCollections.add(copyCollDef); 373 } 374 } 375 } 376 377 386 private void cloneNestedFeatures(NestedDef nestedDef, ArrayList newFields, ArrayList newReferences, ArrayList newCollections) 387 { 388 ClassDescriptorDef nestedClassDef = nestedDef.getNestedType(); 389 String prefix = nestedDef.getName()+"::"; 390 FieldDescriptorDef copyFieldDef; 391 ReferenceDescriptorDef copyRefDef; 392 CollectionDescriptorDef copyCollDef; 393 StringBuffer newForeignkey; 394 395 for (Iterator fieldIt = nestedClassDef.getFields(); fieldIt.hasNext();) 396 { 397 copyFieldDef = cloneField((FieldDescriptorDef)fieldIt.next(), prefix); 398 if (!contains(newFields, copyFieldDef)) 399 { 400 copyFieldDef.setNested(); 401 newFields.add(copyFieldDef); 402 } 403 } 404 for (Iterator refIt = nestedClassDef.getReferences(); refIt.hasNext();) 405 { 406 copyRefDef = cloneReference((ReferenceDescriptorDef)refIt.next(), prefix); 407 if (contains(newReferences, copyRefDef)) 408 { 409 continue; 410 } 411 copyRefDef.setNested(); 412 413 newForeignkey = new StringBuffer (); 415 416 for (CommaListIterator it = new CommaListIterator(copyRefDef.getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY)); it.hasNext();) 417 { 418 if (newForeignkey.length() > 0) 419 { 420 newForeignkey.append(","); 421 } 422 newForeignkey.append(prefix); 423 newForeignkey.append(it.next()); 424 } 425 copyRefDef.setProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY, newForeignkey.toString()); 426 newReferences.add(copyRefDef); 427 } 428 for (Iterator collIt = nestedClassDef.getCollections(); collIt.hasNext();) 429 { 430 copyCollDef = cloneCollection((CollectionDescriptorDef)collIt.next(), prefix); 431 if (!contains(newCollections, copyCollDef)) 432 { 433 copyCollDef.setNested(); 434 newCollections.add(copyCollDef); 435 } 436 } 437 } 438 439 446 private FieldDescriptorDef cloneField(FieldDescriptorDef fieldDef, String prefix) 447 { 448 FieldDescriptorDef copyFieldDef = new FieldDescriptorDef(fieldDef, prefix); 449 450 copyFieldDef.setOwner(this); 451 copyFieldDef.setProperty(PropertyHelper.OJB_PROPERTY_IGNORE, null); 453 454 Properties mod = getModification(copyFieldDef.getName()); 455 456 if (mod != null) 457 { 458 if (!PropertyHelper.toBoolean(mod.getProperty(PropertyHelper.OJB_PROPERTY_IGNORE), false) && 459 hasFeature(copyFieldDef.getName())) 460 { 461 LogHelper.warn(true, 462 ClassDescriptorDef.class, 463 "process", 464 "Class "+getName()+" has a feature that has the same name as its included field "+ 465 copyFieldDef.getName()+" from class "+fieldDef.getOwner().getName()); 466 } 467 copyFieldDef.applyModifications(mod); 468 } 469 return copyFieldDef; 470 } 471 472 479 private ReferenceDescriptorDef cloneReference(ReferenceDescriptorDef refDef, String prefix) 480 { 481 ReferenceDescriptorDef copyRefDef = new ReferenceDescriptorDef(refDef, prefix); 482 483 copyRefDef.setOwner(this); 484 copyRefDef.setProperty(PropertyHelper.OJB_PROPERTY_IGNORE, null); 486 487 Properties mod = getModification(copyRefDef.getName()); 488 489 if (mod != null) 490 { 491 if (!PropertyHelper.toBoolean(mod.getProperty(PropertyHelper.OJB_PROPERTY_IGNORE), false) && 492 hasFeature(copyRefDef.getName())) 493 { 494 LogHelper.warn(true, 495 ClassDescriptorDef.class, 496 "process", 497 "Class "+getName()+" has a feature that has the same name as its included reference "+ 498 copyRefDef.getName()+" from class "+refDef.getOwner().getName()); 499 } 500 copyRefDef.applyModifications(mod); 501 } 502 return copyRefDef; 503 } 504 505 512 private CollectionDescriptorDef cloneCollection(CollectionDescriptorDef collDef, String prefix) 513 { 514 CollectionDescriptorDef copyCollDef = new CollectionDescriptorDef(collDef, prefix); 515 516 copyCollDef.setOwner(this); 517 copyCollDef.setProperty(PropertyHelper.OJB_PROPERTY_IGNORE, null); 519 520 Properties mod = getModification(copyCollDef.getName()); 521 522 if (mod != null) 523 { 524 if (!PropertyHelper.toBoolean(mod.getProperty(PropertyHelper.OJB_PROPERTY_IGNORE), false) && 525 hasFeature(copyCollDef.getName())) 526 { 527 LogHelper.warn(true, 528 ClassDescriptorDef.class, 529 "process", 530 "Class "+getName()+" has a feature that has the same name as its included collection "+ 531 copyCollDef.getName()+" from class "+collDef.getOwner().getName()); 532 } 533 copyCollDef.applyModifications(mod); 534 } 535 return copyCollDef; 536 } 537 538 543 public void addDirectBaseType(ClassDescriptorDef baseType) 544 { 545 _directBaseTypes.put(baseType.getName(), baseType); 546 } 547 548 553 public Iterator getDirectBaseTypes() 554 { 555 return _directBaseTypes.values().iterator(); 556 } 557 558 563 public Iterator getAllBaseTypes() 564 { 565 ArrayList baseTypes = new ArrayList(); 566 567 baseTypes.addAll(_directBaseTypes.values()); 568 569 for (int idx = baseTypes.size() - 1; idx >= 0; idx--) 570 { 571 ClassDescriptorDef curClassDef = (ClassDescriptorDef)baseTypes.get(idx); 572 573 for (Iterator it = curClassDef.getDirectBaseTypes(); it.hasNext();) 574 { 575 ClassDescriptorDef curBaseTypeDef = (ClassDescriptorDef)it.next(); 576 577 if (!baseTypes.contains(curBaseTypeDef)) 578 { 579 baseTypes.add(0, curBaseTypeDef); 580 idx++; 581 } 582 } 583 } 584 return baseTypes.iterator(); 585 } 586 587 592 public void addExtentClass(ClassDescriptorDef subType) 593 { 594 if (!_extents.contains(subType)) 595 { 596 _extents.add(subType); 597 } 598 } 599 600 605 public Iterator getExtentClasses() 606 { 607 Collections.sort(_extents, new DefBaseComparator()); 609 return _extents.iterator(); 610 } 611 612 617 public Iterator getAllExtentClasses() 618 { 619 ArrayList subTypes = new ArrayList(); 620 621 subTypes.addAll(_extents); 622 623 for (int idx = 0; idx < subTypes.size(); idx++) 624 { 625 ClassDescriptorDef curClassDef = (ClassDescriptorDef)subTypes.get(idx); 626 627 for (Iterator it = curClassDef.getExtentClasses(); it.hasNext();) 628 { 629 ClassDescriptorDef curSubTypeDef = (ClassDescriptorDef)it.next(); 630 631 if (!subTypes.contains(curSubTypeDef)) 632 { 633 subTypes.add(curSubTypeDef); 634 } 635 } 636 } 637 return subTypes.iterator(); 638 } 639 640 645 public boolean canBeInstantiated() 646 { 647 return !_origin.isAbstract() && !_origin.isInterface(); 648 } 649 650 656 public boolean hasFeature(String name) 657 { 658 return getFeature(name) != null; 659 } 660 661 667 public DefBase getFeature(String name) 668 { 669 DefBase result = getField(name); 670 671 if (result == null) 672 { 673 result = getReference(name); 674 } 675 if (result == null) 676 { 677 result = getCollection(name); 678 } 679 return result; 680 } 681 682 687 public void addField(FieldDescriptorDef fieldDef) 688 { 689 fieldDef.setOwner(this); 690 _fields.add(fieldDef); 691 } 692 693 698 public void addFieldClone(FieldDescriptorDef fieldDef) 699 { 700 _fields.add(cloneField(fieldDef, "")); 701 } 702 703 709 public FieldDescriptorDef getField(String name) 710 { 711 FieldDescriptorDef fieldDef = null; 712 713 for (Iterator it = _fields.iterator(); it.hasNext(); ) 714 { 715 fieldDef = (FieldDescriptorDef)it.next(); 716 if (fieldDef.getName().equals(name)) 717 { 718 return fieldDef; 719 } 720 } 721 return null; 722 } 723 724 729 public Iterator getFields() 730 { 731 return _fields.iterator(); 732 } 733 734 741 public ArrayList getFields(String fieldNames) throws NoSuchFieldException 742 { 743 ArrayList result = new ArrayList(); 744 FieldDescriptorDef fieldDef; 745 String name; 746 747 for (CommaListIterator it = new CommaListIterator(fieldNames); it.hasNext();) 748 { 749 name = it.getNext(); 750 fieldDef = getField(name); 751 if (fieldDef == null) 752 { 753 throw new NoSuchFieldException (name); 754 } 755 result.add(fieldDef); 756 } 757 return result; 758 } 759 760 765 public ArrayList getPrimaryKeys() 766 { 767 ArrayList result = new ArrayList(); 768 FieldDescriptorDef fieldDef; 769 770 for (Iterator it = getFields(); it.hasNext();) 771 { 772 fieldDef = (FieldDescriptorDef)it.next(); 773 if (fieldDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_PRIMARYKEY, false)) 774 { 775 result.add(fieldDef); 776 } 777 } 778 return result; 779 } 780 781 786 public void addReference(ReferenceDescriptorDef refDef) 787 { 788 refDef.setOwner(this); 789 _references.add(refDef); 790 } 791 792 798 public ReferenceDescriptorDef getReference(String name) 799 { 800 ReferenceDescriptorDef refDef; 801 802 for (Iterator it = _references.iterator(); it.hasNext(); ) 803 { 804 refDef = (ReferenceDescriptorDef)it.next(); 805 if (refDef.getName().equals(name)) 806 { 807 return refDef; 808 } 809 } 810 return null; 811 } 812 813 818 public Iterator getReferences() 819 { 820 return _references.iterator(); 821 } 822 823 828 public void addCollection(CollectionDescriptorDef collDef) 829 { 830 collDef.setOwner(this); 831 _collections.add(collDef); 832 } 833 834 840 public CollectionDescriptorDef getCollection(String name) 841 { 842 CollectionDescriptorDef collDef = null; 843 844 for (Iterator it = _collections.iterator(); it.hasNext(); ) 845 { 846 collDef = (CollectionDescriptorDef)it.next(); 847 if (collDef.getName().equals(name)) 848 { 849 return collDef; 850 } 851 } 852 return null; 853 } 854 855 860 public Iterator getCollections() 861 { 862 return _collections.iterator(); 863 } 864 865 870 public void addNested(NestedDef nestedDef) 871 { 872 nestedDef.setOwner(this); 873 _nested.add(nestedDef); 874 } 875 876 882 public NestedDef getNested(String name) 883 { 884 NestedDef nestedDef = null; 885 886 for (Iterator it = _nested.iterator(); it.hasNext(); ) 887 { 888 nestedDef = (NestedDef)it.next(); 889 if (nestedDef.getName().equals(name)) 890 { 891 return nestedDef; 892 } 893 } 894 return null; 895 } 896 897 902 public Iterator getNested() 903 { 904 return _nested.iterator(); 905 } 906 907 912 public void addIndexDescriptor(IndexDescriptorDef indexDef) 913 { 914 indexDef.setOwner(this); 915 _indexDescriptors.add(indexDef); 916 } 917 918 924 public IndexDescriptorDef getIndexDescriptor(String name) 925 { 926 IndexDescriptorDef indexDef = null; 927 928 for (Iterator it = _indexDescriptors.iterator(); it.hasNext(); ) 929 { 930 indexDef = (IndexDescriptorDef)it.next(); 931 if (indexDef.getName().equals(name)) 932 { 933 return indexDef; 934 } 935 } 936 return null; 937 } 938 939 944 public Iterator getIndexDescriptors() 945 { 946 return _indexDescriptors.iterator(); 947 } 948 949 955 public ObjectCacheDef setObjectCache(String name) 956 { 957 if ((_objectCache == null) || !_objectCache.getName().equals(name)) 958 { 959 _objectCache = new ObjectCacheDef(name); 960 961 _objectCache.setOwner(this); 962 } 963 return _objectCache; 964 } 965 966 971 public ObjectCacheDef getObjectCache() 972 { 973 return _objectCache; 974 } 975 976 981 public void addProcedure(ProcedureDef procDef) 982 { 983 procDef.setOwner(this); 984 _procedures.put(procDef.getName(), procDef); 985 } 986 987 993 public ProcedureDef getProcedure(String name) 994 { 995 return (ProcedureDef)_procedures.get(name); 996 } 997 998 1003 public Iterator getProcedures() 1004 { 1005 return _procedures.values().iterator(); 1006 } 1007 1008 1013 public void addProcedureArgument(ProcedureArgumentDef argDef) 1014 { 1015 argDef.setOwner(this); 1016 _procedureArguments.put(argDef.getName(), argDef); 1017 } 1018 1019 1025 public ProcedureArgumentDef getProcedureArgument(String name) 1026 { 1027 return (ProcedureArgumentDef)_procedureArguments.get(name); 1028 } 1029 1030 1035 public Iterator getProcedureArguments() 1036 { 1037 return _procedureArguments.values().iterator(); 1038 } 1039 1040 1046 public void addModification(String name, Properties mods) 1047 { 1048 _modifications.put(name, mods); 1049 } 1050 1051 1056 public Iterator getModificationNames() 1057 { 1058 return _modifications.keySet().iterator(); 1059 } 1060 1061 1067 public Properties getModification(String name) 1068 { 1069 return (Properties)_modifications.get(name); 1070 } 1071 1072 1075 public boolean equals(Object other) 1076 { 1077 if ((other == null) || !(other instanceof ClassDescriptorDef)) 1078 { 1079 return false; 1080 } 1081 return _origin == ((ClassDescriptorDef)other)._origin; 1082 } 1083 1084 1087 public int hashCode() 1088 { 1089 return _origin.hashCode(); 1090 } 1091} 1092 | Popular Tags |