1 23 24 29 30 package com.sun.jdo.api.persistence.model.util; 31 32 import java.util.*; 33 import java.lang.reflect.Modifier ; 34 35 import org.netbeans.modules.dbschema.*; 36 import org.netbeans.modules.dbschema.util.NameUtil; 37 import org.netbeans.modules.dbschema.util.SQLTypeUtil; 38 39 import com.sun.jdo.api.persistence.model.Model; 40 import com.sun.jdo.api.persistence.model.jdo.*; 41 import com.sun.jdo.api.persistence.model.mapping.*; 42 import com.sun.jdo.spi.persistence.utility.*; 43 import com.sun.jdo.spi.persistence.utility.logging.Logger; 44 45 50 public class ModelValidator 51 { 52 53 private Model _model; 54 55 56 private String _className; 57 58 61 private ClassLoader _classLoader; 62 63 64 private ResourceBundle _messages; 65 66 public ModelValidator (Model model, String className, ResourceBundle bundle) 67 { 68 this(model, className, null, bundle); 69 } 70 71 75 public ModelValidator (Model model, String className, 76 ClassLoader classLoader, ResourceBundle bundle) 77 { 78 _model = model; 79 _className = className; 80 _classLoader = classLoader; 81 _messages = bundle; 82 } 83 84 88 public Model getModel () { return _model; } 89 90 94 public String getClassName () { return _className; } 95 96 100 public ClassLoader getClassLoader () { return _classLoader; } 101 102 104 protected ResourceBundle getMessages () { return _messages; } 105 106 114 public boolean parseCheck () 115 { 116 Iterator iterator = getBasicValidationList().iterator(); 117 118 try 119 { 120 while (iterator.hasNext()) 121 ((ValidationComponent)iterator.next()).validate(); 122 } 123 catch (ModelValidationException e) 124 { 125 LogHelperModel.getLogger().log(Logger.FINER, 126 "model.parse_error", e); 128 return false; 129 } 130 131 return true; 132 } 133 134 143 public Collection fullValidationCheck () 144 { 145 ArrayList list = new ArrayList(); 146 Iterator iterator = getFullValidationList().iterator(); 147 148 while (iterator.hasNext()) 149 { 150 try 151 { 152 ((ValidationComponent)iterator.next()).validate(); 153 } 154 catch (ModelValidationException e) 155 { 156 list.add(e); 157 } 158 } 159 160 return Collections.unmodifiableCollection(list); 161 } 162 163 165 173 public Collection getBasicValidationList () 174 { 175 ArrayList list = new ArrayList(); 176 String className = getClassName(); 177 178 list.add(createClassExistenceComponent(className)); 179 list.add(createClassPersistenceComponent(className)); 180 181 list.addAll(getDatabaseValidationList()); 182 list.addAll(getFieldsValidationList()); 183 184 return Collections.unmodifiableCollection(list); 185 } 186 187 196 public Collection getFullValidationList () 197 { 198 ArrayList list = new ArrayList(getBasicValidationList()); 199 String className = getClassName(); 200 PersistenceClassElement persistenceClass = 201 getPersistenceClass(className); 202 203 if (persistenceClass != null) 204 { 205 PersistenceFieldElement[] fields = persistenceClass.getFields(); 206 int i, count = ((fields != null) ? fields.length : 0); 207 208 list.add(createSerializableClassComponent(className)); 209 list.add(createKeyClassComponent(persistenceClass.getKeyClass())); 210 list.add(createClassMappingComponent(persistenceClass)); 211 list.add(createKeyColumnMappingComponent(persistenceClass)); 212 213 for (i = 0; i < count; i++) 214 { 215 PersistenceFieldElement field = fields[i]; 216 217 list.add(createFieldCardinalityComponent(field)); 218 list.add(createFieldMappingComponent(field)); 219 list.add(createFieldBlobMappingComponent(field)); 220 list.addAll(getRelatedClassValidationList(field)); 221 } 222 } 223 224 return Collections.unmodifiableCollection(list); 225 } 226 227 229 234 private Collection getDatabaseValidationList () 235 { 236 ArrayList list = new ArrayList(); 237 String className = getClassName(); 238 MappingClassElement mappingClass = getMappingClass(className); 239 240 if (mappingClass != null) 241 { 242 ArrayList tables = mappingClass.getTables(); 243 int i, count = ((tables != null) ? tables.size() : 0); 244 MappingTableElement primaryTable = null; 245 Iterator iterator = null; 246 247 list.add(createSchemaExistenceComponent(className)); 248 249 for (i = 0; i < count; i++) 250 { 251 MappingTableElement nextTable = 252 (MappingTableElement)tables.get(i); 253 254 list.add(createTableExistenceComponent(nextTable.getTable())); 255 256 if (i == 0) 257 { 258 primaryTable = nextTable; 259 list.add(createPrimaryTableComponent(primaryTable)); 260 } 261 else 262 { 263 MappingReferenceKeyElement referenceKey = 264 findReferenceKey(primaryTable, nextTable); 265 266 if (referenceKey != null) 267 { 268 iterator = referenceKey.getColumnPairNames().iterator(); 269 while (iterator.hasNext()) 270 { 271 list.add(createColumnExistenceComponent( 272 (String )iterator.next())); 273 } 274 } 275 } 276 } 277 278 list.add(createVersionConsistencyComponent(mappingClass)); 279 280 iterator = mappingClass.getFields().iterator(); 281 while (iterator.hasNext()) 282 { 283 MappingFieldElement nextField = 284 (MappingFieldElement)iterator.next(); 285 ArrayList allColumns = new ArrayList(); 286 Iterator columnIterator = null; 287 288 if (isRelationship(nextField)) 289 { 290 allColumns.addAll(((MappingRelationshipElement)nextField). 291 getAssociatedColumns()); 292 } 293 294 allColumns.addAll(nextField.getColumns()); 295 296 columnIterator = allColumns.iterator(); 297 while (columnIterator.hasNext()) 298 { 299 list.add(createColumnExistenceComponent( 300 (String )columnIterator.next(), nextField)); 301 } 302 } 303 } 304 305 return list; 306 } 307 308 313 private Collection getFieldsValidationList () 314 { 315 ArrayList list = new ArrayList(); 316 Model model = getModel(); 317 String className = getClassName(); 318 PersistenceClassElement persistenceClass = 319 getPersistenceClass(className); 320 321 if (persistenceClass != null) 322 { 323 PersistenceFieldElement[] fields = persistenceClass.getFields(); 324 int i, count = ((fields != null) ? fields.length : 0); 325 Iterator iterator = 326 getMappingClass(className).getFields().iterator(); 327 328 for (i = 0; i < count; i++) 329 { 330 PersistenceFieldElement field = fields[i]; 331 332 list.add(createFieldExistenceComponent(field)); 333 334 if (model.hasField(className, field.getName())) 337 { 338 list.add(createFieldPersistenceComponent(field)); 339 list.add(createFieldPersistenceTypeComponent(field)); 340 list.add(createFieldConsistencyComponent(field)); 341 342 if (isLegalRelationship(field)) 343 { 344 RelationshipElement rel = (RelationshipElement)field; 345 346 348 list.add(createElementClassComponent(rel)); 349 list.add(createRelatedClassMatchesComponent(rel)); 350 } 351 } 352 } 353 354 while (iterator.hasNext()) 355 { 356 MappingFieldElement field = 357 (MappingFieldElement)iterator.next(); 358 String fieldName = field.getName(); 359 360 if (persistenceClass.getField(fieldName) == null) 362 { 363 list.add(createFieldExistenceComponent(field)); 364 365 if (model.hasField(className, fieldName)) 368 list.add(createFieldConsistencyComponent(field)); 369 } 370 371 if (!isRelationship(field)) 372 list.add(createColumnOverlapComponent(field)); 373 374 if (Boolean.getBoolean("AllowManagedFieldsInDefaultFetchGroup")) { 377 } 381 else 382 { 383 list.add(createFieldDefaultFetchGroupComponent(field)); 384 } 385 } 386 } 387 388 return list; 389 } 390 391 399 private Collection getRelatedClassValidationList ( 400 PersistenceFieldElement field) 401 { 402 String relatedClass = getRelatedClass(field); 403 ArrayList list = new ArrayList(); 404 405 if ((relatedClass != null) && 408 getModel().hasField(getClassName(), field.getName())) 409 { 410 MappingClassElement relatedClassElement = 411 getMappingClass(relatedClass); 412 413 list.add(createClassExistenceComponent(relatedClass, field)); 414 list.add(createClassPersistenceComponent(relatedClass, field)); 415 list.add(createSchemaExistenceComponent(relatedClass, field)); 416 list.add(createRelatedSchemaMatchesComponent(relatedClass, field)); 417 418 if (relatedClassElement != null) 419 { 420 ArrayList tables = relatedClassElement.getTables(); 421 MappingTableElement primaryTable = null; 422 boolean hasTables = ((tables != null) && (tables.size() > 0)); 423 424 if (hasTables) 425 { 426 primaryTable = (MappingTableElement)tables.get(0); 427 list.add(createTableExistenceComponent( 428 primaryTable.getTable(), field)); 429 } 430 431 if (isRelationship(field)) 432 { 433 RelationshipElement relElement = (RelationshipElement)field; 434 Object rel = getMappingClass(getClassName()). 435 getField(field.getName()); 436 437 list.add(createInverseFieldComponent(relElement)); 438 list.add(createInverseMappingComponent(relElement)); 439 440 if ((rel != null) && isRelationship(rel)) 444 { 445 MappingRelationshipElement relationship = 446 (MappingRelationshipElement)rel; 447 ArrayList columns = 448 relationship.getAssociatedColumns(); 449 Iterator iterator = null; 450 451 if ((columns == null) || (columns.size() == 0)) 452 columns = relationship.getColumns(); 453 454 if (columns != null) 455 { 456 List tableNames = new ArrayList(); 457 458 if (hasTables) 459 { 460 Iterator tableIterator = tables.iterator(); 461 462 while (tableIterator.hasNext()) 463 { 464 tableNames.add(((MappingTableElement) 465 tableIterator.next()).getName()); 466 } 467 } 468 469 iterator = columns.iterator(); 470 471 while (iterator.hasNext()) 472 { 473 list.add(createRelatedTableMatchesComponent( 474 relatedClass, field, tableNames, 475 (String )iterator.next())); 476 } 477 } 478 } 479 } 480 } 481 } 482 483 return list; 484 } 485 486 488 495 protected ValidationComponent createClassExistenceComponent ( 496 final String className, final PersistenceFieldElement relatedField) 497 { 498 return new ValidationComponent () 499 { 500 public void validate () throws ModelValidationException 501 { 502 if ((className == null) || 503 !getModel().hasClass(className, getClassLoader())) 504 { 505 throw constructClassException(className, relatedField, 506 "util.validation.class_not_found"); } 508 } 509 }; 510 } 511 512 516 protected ValidationComponent createClassExistenceComponent ( 517 final String className) 518 { 519 return createClassExistenceComponent(className, null); 520 } 521 522 529 protected ValidationComponent createClassPersistenceComponent ( 530 final String className, final PersistenceFieldElement relatedField) 531 { 532 return new ValidationComponent () 533 { 534 public void validate () throws ModelValidationException 535 { 536 Model model = getModel(); 537 538 if ((className != null) && 539 model.hasClass(className, getClassLoader())) 540 { 541 String key = null; 542 543 if (!isPersistent(className)) 544 key = "util.validation.class_not_persistence_capable"; else if (!model.isPersistenceCapableAllowed(className)) 546 key = "util.validation.class_not_allowed"; 548 if (key != null) 549 { 550 throw constructClassException( 551 className, relatedField, key); 552 } 553 } 554 } 555 }; 556 } 557 558 562 protected ValidationComponent createClassPersistenceComponent ( 563 final String className) 564 { 565 return createClassPersistenceComponent(className, null); 566 } 567 568 572 protected ValidationComponent createFieldExistenceComponent ( 573 final String fieldName) 574 { 575 return new ValidationComponent () 576 { 577 public void validate () throws ModelValidationException 578 { 579 if (!getModel().hasField(getClassName(), fieldName)) 580 { 581 throw constructFieldException(fieldName, 582 "util.validation.field_not_found"); } 584 } 585 }; 586 } 587 588 592 protected ValidationComponent createFieldExistenceComponent (Object field) 593 { 594 return createFieldExistenceComponent(field.toString()); 595 } 596 597 602 protected ValidationComponent createFieldPersistenceComponent ( 603 final PersistenceFieldElement field) 604 { 605 return new ValidationComponent () 606 { 607 public void validate () throws ModelValidationException 608 { 609 boolean isPersistent = (PersistenceFieldElement.PERSISTENT == 610 field.getPersistenceType()); 611 String fieldName = field.getName(); 612 613 if (isPersistent && 614 !isPersistentAllowed(getClassName(), fieldName)) 615 { 616 throw constructFieldException(fieldName, 617 "util.validation.field_persistent_not_allowed"); } 619 } 620 }; 621 } 622 623 628 protected ValidationComponent createFieldConsistencyComponent ( 629 final PersistenceFieldElement field) 630 { 631 return new ValidationComponent () 632 { 633 public void validate () throws ModelValidationException 634 { 635 String fieldName = field.getName(); 636 String className = getClassName(); 637 boolean isLegallyPersistent = 638 isPersistentAllowed(className, fieldName); 639 640 if (isLegallyPersistent) 641 { 642 MappingClassElement mappingClass = 643 getMappingClass(className); 644 MappingFieldElement mappingElement = 645 ((mappingClass != null) ? 646 mappingClass.getField(fieldName) : null); 647 648 if (mappingElement != null) 649 { 650 boolean jdoIsRelationship = isLegalRelationship(field); 651 652 if (jdoIsRelationship != isRelationship(mappingElement)) 653 { 654 throw constructFieldException(fieldName, 655 "util.validation.field_type_inconsistent"); } 657 } 658 } 659 } 660 }; 661 } 662 663 668 protected ValidationComponent createFieldConsistencyComponent ( 669 final MappingFieldElement field) 670 { 671 return new ValidationComponent () 672 { 673 public void validate () throws ModelValidationException 674 { 675 if (field != null) 676 { 677 String fieldName = field.getName(); 678 PersistenceClassElement persistenceClass = 679 getPersistenceClass(getClassName()); 680 PersistenceFieldElement persistenceElement = 681 ((persistenceClass != null) ? 682 persistenceClass.getField(fieldName) : null); 683 684 if (persistenceElement == null) 685 { 686 throw constructFieldException(fieldName, 687 "util.validation.field_model_inconsistent"); } 689 } 690 } 691 }; 692 } 693 694 699 protected ValidationComponent createFieldPersistenceTypeComponent ( 700 final PersistenceFieldElement field) 701 { 702 return new ValidationComponent () 703 { 704 public void validate () throws ModelValidationException 705 { 706 String fieldName = field.getName(); 707 String className = getClassName(); 708 boolean isLegallyPersistent = 709 isPersistentAllowed(className, fieldName); 710 711 if (isLegallyPersistent) 712 { 713 boolean isRelationship = isRelationship(field); 714 boolean mustBeRelationship = shouldBeRelationship(field); 715 716 if (isRelationship && !mustBeRelationship) 717 { 718 throw constructFieldException(fieldName, 719 "util.validation.field_relationship_not_allowed"); } 721 else if (!isRelationship && mustBeRelationship) 722 { 723 throw constructFieldException(fieldName, 724 "util.validation.field_type_not_allowed"); } 726 } 727 } 728 }; 729 } 730 731 736 protected ValidationComponent createFieldCardinalityComponent ( 737 final PersistenceFieldElement field) 738 { 739 return new ValidationComponent () 740 { 741 public void validate () throws ModelValidationException 742 { 743 if (isLegalRelationship(field)) 744 { 745 RelationshipElement relationship = 746 (RelationshipElement)field; 747 String fieldName = field.getName(); 748 boolean nonCollectionRelationship = 749 !isCollection(getClassName(), fieldName); 750 int upperBound = (nonCollectionRelationship ? 751 1 : relationship.getUpperBound()); 752 int lowerBound = relationship.getLowerBound(); 753 MappingRelationshipElement mapping = null; 754 755 if ((lowerBound < 0) || (upperBound <= 0) || 756 (lowerBound > upperBound)) 757 { 758 throw constructFieldException(fieldName, 759 "util.validation.cardinality_invalid"); } 761 762 mapping = getMappingRelationship(relationship); 765 if (nonCollectionRelationship && (lowerBound != 1) && 766 (mapping != null) && !isJoin(mapping)) 767 { 768 ForeignKeyElement fk = getMatchingFK(mapping); 773 774 if ((fk != null) && hasNonNullableColumn(fk)) 775 { 776 throw constructFieldException(fieldName, 777 "util.validation.lower_bound_invalid"); } 779 } 780 } 781 } 782 783 787 private boolean hasNonNullableColumn (ForeignKeyElement fk) 788 { 789 ColumnElement[] localColumns = fk.getLocalColumns(); 790 int count = ((localColumns != null) ? localColumns.length : 0); 791 792 for (int i = 0; i < count; i++) 793 { 794 if (!localColumns[i].isNullable()) 795 return true; 796 } 797 798 return false; 799 } 800 801 806 private ForeignKeyElement getMatchingFK ( 807 MappingRelationshipElement mapping) 808 { 809 MappingClassElement mappingClass = mapping. 810 getDeclaringClass(); 811 String databaseRoot = getSchemaForClass(getClassName()); 812 List pairNames = mapping.getColumns(); 813 List tables = mappingClass.getTables(); 814 815 if (tables != null) 816 { 817 for (Iterator i = tables.iterator(); i.hasNext();) 818 { 819 String tableName = ((MappingTableElement)i.next()). 820 getName(); 821 TableElement table = getTable(tableName, databaseRoot); 822 ForeignKeyElement fk = getMatchingFK(pairNames, table); 823 824 if (fk != null) 825 return fk; 826 } 827 } 828 829 return null; 830 } 831 832 837 private ForeignKeyElement getMatchingFK (List pairNames, 838 TableElement table) 839 { 840 ForeignKeyElement[] foreignKeys = (table != null) ? 841 table.getForeignKeys() : null; 842 int count = ((foreignKeys != null) ? foreignKeys.length : 0); 843 844 for (int i = 0; i < count; i++) 845 { 846 if (matchesFK(pairNames, foreignKeys[i])) 847 return foreignKeys[i]; 848 } 849 850 return null; 851 } 852 853 856 private boolean matchesFK (List pairNames, 857 ForeignKeyElement foreignKey) 858 { 859 ColumnPairElement[] fkPairs = foreignKey.getColumnPairs(); 860 int fkCount = ((fkPairs != null) ? fkPairs.length : 0); 861 int count = ((pairNames != null) ? pairNames.size() : 0); 862 863 if (fkCount == count) 866 { 867 for (int i = 0; i < fkCount; i++) 870 { 871 String fkPairName = NameUtil.getRelativeMemberName( 872 fkPairs[i].getName().getFullName()); 873 874 if (!pairNames.contains(fkPairName)) 875 return false; 876 } 877 878 return true; 879 } 880 881 return false; 882 } 883 }; 884 } 885 886 891 protected ValidationComponent createFieldMappingComponent ( 892 final PersistenceFieldElement field) 893 { 894 return new ValidationComponent () 895 { 896 public void validate () throws ModelValidationException 897 { 898 String fieldName = field.getName(); 899 MappingClassElement mappingClass = 900 getMappingClass(getClassName()); 901 902 if ((mappingClass != null) && 903 (mappingClass.getTables().size() > 0)) 904 { 905 MappingFieldElement mappingField = 906 mappingClass.getField(fieldName); 907 908 if ((mappingField == null) || 909 (mappingField.getColumns().size() == 0)) 910 { 911 throw constructFieldException( 912 ModelValidationException.WARNING, fieldName, 913 "util.validation.field_not_mapped"); } 915 } 916 } 917 }; 918 } 919 920 929 protected ValidationComponent createFieldBlobMappingComponent ( 930 final PersistenceFieldElement field) 931 { 932 return new ValidationComponent () 933 { 934 public void validate () throws ModelValidationException 935 { 936 String className = getClassName(); 937 String fieldName = field.getName(); 938 MappingClassElement mappingClass = getMappingClass(className); 939 MappingFieldElement mappingField = ((mappingClass != null) ? 940 mappingClass.getField(fieldName) : null); 941 942 if (mappingField != null) 943 { 944 boolean isKey = field.isKey(); 945 946 if (isKey || (MappingFieldElement.GROUP_DEFAULT == 947 mappingField.getFetchGroup())) 948 { 949 if (isMappedToBlob(mappingField, 950 getSchemaForClass(className))) 951 { 952 throw constructFieldException(fieldName, (isKey ? 953 "util.validation.field_key_field_not_allowed" : "util.validation.field_fetch_group_not_allowed")); } 956 } 957 } 958 } 959 private boolean isMappedToBlob (MappingFieldElement mappingField, 960 String schema) 961 { 962 if (mappingField instanceof MappingRelationshipElement) 963 { 964 return isMappedToBlob( 965 (MappingRelationshipElement)mappingField, schema); 966 } 967 else 968 { 969 Iterator iterator = mappingField.getColumns().iterator(); 970 971 while (iterator.hasNext()) 972 { 973 String absoluteName = NameUtil.getAbsoluteMemberName( 974 schema, (String )iterator.next()); 975 TableElement table = TableElement.forName( 976 NameUtil.getTableName(absoluteName)); 977 ColumnElement columnElement = ((table != null) ? 978 (ColumnElement)table.getMember( 979 DBIdentifier.create(absoluteName)) : null); 980 981 if (isMappedToBlob(columnElement)) 982 return true; 983 } 984 } 985 986 return false; 987 } 988 private boolean isMappedToBlob (MappingRelationshipElement rel, 989 String schema) 990 { 991 Iterator iterator = rel.getColumns().iterator(); 992 993 while (iterator.hasNext()) 994 { 995 ColumnPairElement pair = 996 getPair((String )iterator.next(), schema); 997 998 if (isMappedToBlob(pair)) 999 return true; 1000 } 1001 1002 iterator = rel.getAssociatedColumns().iterator(); 1004 while (iterator.hasNext()) 1005 { 1006 ColumnPairElement pair = 1007 getPair((String )iterator.next(), schema); 1008 1009 if (isMappedToBlob(pair)) 1010 return true; 1011 } 1012 1013 return false; 1014 } 1015 private boolean isMappedToBlob (ColumnPairElement pair) 1016 { 1017 return ((pair == null) ? false : 1018 isMappedToBlob(pair.getLocalColumn()) && 1019 isMappedToBlob(pair.getReferencedColumn())); 1020 } 1021 private boolean isMappedToBlob (ColumnElement column) 1022 { 1023 return ((column != null) && 1024 SQLTypeUtil.isBlob(column.getType())); 1025 } 1026 }; 1027 } 1028 1029 1034 protected ValidationComponent createCollectionClassComponent ( 1035 final RelationshipElement field) 1036 { 1037 return new ValidationComponent () 1038 { 1039 public void validate () throws ModelValidationException 1040 { 1041 String className = getClassName(); 1042 String fieldName = field.getName(); 1043 1044 if (isCollection(className, fieldName)) 1045 { 1046 Model model = getModel(); 1047 String collectionClass = field.getCollectionClass(); 1048 String fieldType = model.getFieldType(className, fieldName); 1049 boolean missingCollectionClass = 1050 StringHelper.isEmpty(collectionClass); 1051 1052 if (!missingCollectionClass && 1053 !model.getSupportedCollectionClasses(fieldType). 1054 contains(collectionClass)) 1055 { 1056 throw constructFieldException(fieldName, 1057 "util.validation.collection_class_invalid"); } 1059 } 1060 } 1061 }; 1062 } 1063 1064 1069 protected ValidationComponent createElementClassComponent ( 1070 final RelationshipElement field) 1071 { 1072 return new ValidationComponent () 1073 { 1074 public void validate () throws ModelValidationException 1075 { 1076 String className = getClassName(); 1077 String fieldName = field.getName(); 1078 1079 if (isCollection(className, fieldName)) 1080 { 1081 String elementClass = field.getElementClass(); 1082 1083 if (StringHelper.isEmpty(elementClass)) 1084 { 1085 MappingClassElement mappingClass = 1086 getMappingClass(className); 1087 MappingFieldElement mappingElement = 1088 ((mappingClass != null) ? 1089 mappingClass.getField(fieldName) : null); 1090 1091 if ((mappingElement != null) && 1092 (mappingElement.getColumns().size() > 0)) 1093 { 1094 throw constructFieldException(fieldName, 1095 "util.validation.element_class_not_found"); } 1097 } 1098 } 1099 } 1100 }; 1101 } 1102 1103 1122 protected ValidationComponent createVersionConsistencyComponent ( 1123 final MappingClassElement mappingClass) 1124 { 1125 return new ValidationComponent () 1126 { 1127 public void validate () throws ModelValidationException 1128 { 1129 if (MappingClassElement.VERSION_CONSISTENCY == 1131 mappingClass.getConsistencyLevel()) 1132 { 1133 MappingFieldElement versionField = 1134 validateVersionFieldExistence(); 1135 String className = mappingClass.getName(); 1136 String fieldName = versionField.getName(); 1137 String columnName = null; 1138 ColumnElement column = null; 1139 1140 if (versionField instanceof MappingRelationshipElement) 1141 { 1142 throw constructFieldException(fieldName, 1143 "util.validation.version_field_relationship_not_allowed"); } 1145 else if (MappingFieldElement.GROUP_DEFAULT != 1146 versionField.getFetchGroup()) { 1148 throw constructFieldException(fieldName, 1149 "util.validation.version_field_fetch_group_invalid"); } 1151 1152 validatePersistenceFieldAttributes(className, fieldName); 1153 columnName = validateVersionFieldMapping(versionField); 1154 column = validateTableMatch(className, fieldName, columnName); 1155 validateColumnAttributes(className, fieldName, column); 1156 } 1157 } 1158 1161 private MappingFieldElement validateVersionFieldExistence () 1162 throws ModelValidationException 1163 { 1164 List versionFields = mappingClass.getVersionFields(); 1165 1166 if (versionFields.size() != 1) 1168 { 1169 throw constructClassException(mappingClass.getName(), 1170 null, "util.validation.version_field_cardinality"); } 1172 1173 return (MappingFieldElement)versionFields.get(0); 1174 } 1175 1178 private void validatePersistenceFieldAttributes (String className, 1179 String fieldName) throws ModelValidationException 1180 { 1181 Class fieldType = JavaTypeHelper.getPrimitiveClass( 1182 getModel().getFieldType(className, fieldName)); 1183 String keyName = null; 1184 1185 if (getPersistenceClass(className).getField(fieldName).isKey()) 1187 keyName = "util.validation.version_field_key_field_not_allowed"; else if (Long.TYPE != fieldType) keyName = "util.validation.version_field_type_not_allowed"; 1191 if (keyName != null) 1192 throw constructFieldException(fieldName, keyName); 1193 } 1194 1197 private String validateVersionFieldMapping ( 1198 MappingFieldElement versionField) 1199 throws ModelValidationException 1200 { 1201 List columns = versionField.getColumns(); 1202 1203 if (columns.size() != 1) 1205 { 1206 throw constructFieldException(versionField.getName(), 1207 "util.validation.version_field_not_mapped"); } 1209 1210 return (String )columns.get(0); 1211 } 1212 1215 private ColumnElement validateTableMatch (String className, 1216 String fieldName, String columnName) 1217 throws ModelValidationException 1218 { 1219 String schema = getSchemaForClass(className); 1220 String absoluteName = 1221 NameUtil.getAbsoluteMemberName(schema, columnName); 1222 TableElement table = 1223 TableElement.forName(NameUtil.getTableName(absoluteName)); 1224 String primaryName = ((MappingTableElement)mappingClass. 1225 getTables().get(0)).getName(); 1226 TableElement pTable = getTable(primaryName, schema); 1227 1228 if (table != pTable) 1230 { 1231 throw new ModelValidationException( 1232 getModel().getField(className, fieldName), 1233 I18NHelper.getMessage(getMessages(), 1234 "util.validation.version_field_table_mismatch", new Object []{columnName, fieldName, className})); 1236 } 1237 1238 return ((table != null) ? (ColumnElement)table.getMember( 1239 DBIdentifier.create(absoluteName)) : null); 1240 } 1241 1244 private void validateColumnAttributes (String className, 1245 String fieldName, ColumnElement column) 1246 throws ModelValidationException 1247 { 1248 String keyName = null; 1249 1250 if (column.isNullable() || !column.isNumericType()) 1252 keyName = "util.validation.version_field_column_type_invalid"; else { 1255 TableElement table = column.getDeclaringTable(); 1256 UniqueKeyElement[] uks = table.getUniqueKeys(); 1257 ForeignKeyElement[] fks = table.getForeignKeys(); 1258 int i, count = ((uks != null) ? uks.length : 0); 1259 1260 for (i = 0; i < count; i++) 1261 { 1262 UniqueKeyElement uk = uks[i]; 1263 1264 if (uk.isPrimaryKey() && Arrays.asList( 1265 uk.getColumns()).contains(column)) 1266 { 1267 keyName = "util.validation.version_field_column_pk_invalid"; break; 1269 } 1270 } 1271 1272 count = ((fks != null) ? fks.length : 0); 1273 for (i = 0; i < count; i++) 1274 { 1275 ForeignKeyElement fk = fks[i]; 1276 1277 if (Arrays.asList(fk.getLocalColumns()). 1278 contains(column)) 1279 { 1280 keyName = "util.validation.version_field_column_fk_invalid"; break; 1282 } 1283 } 1284 } 1285 1286 if (keyName != null) 1287 { 1288 throw new ModelValidationException( 1289 getModel().getField(className, fieldName), 1290 I18NHelper.getMessage(getMessages(), keyName, 1291 new Object []{column.getName(), fieldName, className})); 1292 } 1293 } 1294 }; 1295 } 1296 1297 1302 protected ValidationComponent createInverseFieldComponent ( 1303 final RelationshipElement field) 1304 { 1305 return new ValidationComponent () 1306 { 1307 public void validate () throws ModelValidationException 1308 { 1309 Model model = getModel(); 1310 RelationshipElement inverse = 1311 field.getInverseRelationship(model); 1312 RelationshipElement inverseInverse = ((inverse != null) ? 1313 inverse.getInverseRelationship(model) : null); 1314 1315 if ((inverse != null) && 1316 (!field.equals(inverseInverse) || (inverseInverse == null))) 1317 { 1318 String fieldName = field.getName(); 1319 1320 throw new ModelValidationException( 1321 model.getField(getClassName(), fieldName), 1322 I18NHelper.getMessage(getMessages(), 1323 "util.validation.inverse_field_invalid", new Object []{fieldName, inverse.getName()})); 1325 } 1326 } 1327 }; 1328 } 1329 1330 1336 protected ValidationComponent createRelatedClassMatchesComponent ( 1337 final RelationshipElement field) 1338 { 1339 return new ValidationComponent () 1340 { 1341 public void validate () throws ModelValidationException 1342 { 1343 String inverseName = 1344 field.getInverseRelationshipName(); 1345 1346 if (!StringHelper.isEmpty(inverseName)) 1347 { 1348 Model model = getModel(); 1349 RelationshipElement inverse = 1350 field.getInverseRelationship(model); 1351 1352 if (inverse == null) { 1354 String relatedClass = getRelatedClass(field); 1355 String fieldName = field.getName(); 1356 String key = ((relatedClass != null) ? 1357 "util.validation.related_class_mismatch" : "util.validation.related_class_not_found"); Object [] args = ((relatedClass != null) ? 1360 new Object []{fieldName, inverseName, relatedClass} 1361 : new Object []{fieldName, inverseName}); 1362 1363 throw new ModelValidationException( 1364 model.getField(getClassName(), fieldName), 1365 I18NHelper.getMessage(getMessages(), key, args)); 1366 } 1367 } 1368 } 1369 }; 1370 } 1371 1372 1378 protected ValidationComponent createInverseMappingComponent ( 1379 final RelationshipElement field) 1380 { 1381 return new ValidationComponent () 1382 { 1383 public void validate () throws ModelValidationException 1384 { 1385 Model model = getModel(); 1386 RelationshipElement inverse = 1387 field.getInverseRelationship(model); 1388 1389 if ((inverse != null) && !isInverseMapping(field, inverse)) 1390 { 1391 String fieldName = field.getName(); 1392 1393 throw new ModelValidationException( 1394 model.getField(getClassName(), fieldName), 1395 I18NHelper.getMessage(getMessages(), 1396 "util.validation.inverse_mapping_mismatch", new Object []{fieldName, inverse.getName()})); 1398 } 1399 } 1400 private boolean hasMappingRows (MappingRelationshipElement field2) 1401 { 1402 if (field2 != null) 1403 { 1404 ArrayList columns = field2.getColumns(); 1405 1406 return ((columns != null) && !columns.isEmpty()); 1407 } 1408 1409 return false; 1410 } 1411 private boolean isInverseMapping (RelationshipElement jdoField1, 1412 RelationshipElement jdoField2) 1413 { 1414 MappingRelationshipElement field1 = 1415 getMappingRelationship(jdoField1); 1416 MappingRelationshipElement field2 = 1417 getMappingRelationship(jdoField2); 1418 boolean field1HasMapping = hasMappingRows(field1); 1419 boolean field2HasMapping = hasMappingRows(field2); 1420 1421 if (field1HasMapping && field2HasMapping) 1423 { 1424 boolean field1IsJoin = isJoin(field1); 1425 1426 if (field1IsJoin == isJoin(field2)) 1427 { 1428 ArrayList pairs1 = field1.getColumns(); 1429 ArrayList pairs2 = field2.getColumns(); 1430 1431 return ((!field1IsJoin) ? isInverse(pairs1, pairs2) : 1432 (isInverse(pairs1, 1433 field2.getAssociatedColumns()) && 1434 isInverse(field1.getAssociatedColumns(), pairs2))); 1435 } 1436 1437 return false; 1438 } 1439 1440 return (field1HasMapping == field2HasMapping); 1442 } 1443 private boolean isInverse (ArrayList pairs1, ArrayList pairs2) 1444 { 1445 int i, size1 = pairs1.size(), size2 = pairs2.size(); 1446 1447 if (size1 == size2) 1448 { 1449 for (i = 0; i < size1; i++) 1450 { 1451 String nextPair = (String )pairs1.get(i); 1452 String inversePair = (String )pairs2.get(i); 1453 int semicolonIndex1 = nextPair.indexOf(';'); 1454 int semicolonIndex2 = inversePair.indexOf(';'); 1455 1456 if (((semicolonIndex1 == -1) || (semicolonIndex2 == -1)) 1457 || (!nextPair.substring(0, semicolonIndex1).equals( 1458 inversePair.substring(semicolonIndex2 + 1)) || 1459 !nextPair.substring(semicolonIndex1 + 1).equals( 1460 inversePair.substring(0, semicolonIndex2)))) 1461 { 1462 return false; 1463 } 1464 } 1465 1466 return true; 1467 } 1468 1469 return false; 1470 } 1471 }; 1472 } 1473 1474 1481 protected ValidationComponent createFieldDefaultFetchGroupComponent ( 1482 final MappingFieldElement field) 1483 { 1484 return new ValidationComponent () 1485 { 1486 public void validate () throws ModelValidationException 1487 { 1488 if (field != null) 1489 { 1490 String fieldName = field.getName(); 1491 PersistenceClassElement persistenceClass = 1492 getPersistenceClass(getClassName()); 1493 PersistenceFieldElement pElement = 1494 ((persistenceClass != null) ? 1495 persistenceClass.getField(fieldName) : null); 1496 1497 if ((pElement != null) && !pElement.isKey() && 1498 (MappingFieldElement.GROUP_DEFAULT == 1499 field.getFetchGroup())) 1500 { 1501 MappingClassElement mappingClass = 1502 field.getDeclaringClass(); 1503 boolean isVersionField = 1504 ((MappingClassElement.VERSION_CONSISTENCY == 1505 mappingClass.getConsistencyLevel()) && 1506 field.isVersion()); 1507 Iterator iterator = mappingClass.getFields().iterator(); 1508 String exceptionKey = (!isVersionField ? 1509 "util.validation.field_fetch_group_invalid": "util.validation.version_field_column_invalid"); 1512 1524 while (iterator.hasNext()) 1525 { 1526 MappingFieldElement testField = 1527 (MappingFieldElement)iterator.next(); 1528 1529 if (isManaged(field, testField) || 1530 isManaged(testField, field)) 1531 { 1532 throw constructFieldException( 1533 fieldName, exceptionKey); 1534 } 1535 else if (!testField.equals(field) && isExactMatch( 1536 field, testField)) 1537 { 1538 throw constructFieldException( 1539 fieldName, exceptionKey); 1540 } 1541 } 1542 } 1543 } 1544 } 1545 private boolean isManaged (MappingFieldElement primField, 1546 MappingFieldElement relField) 1547 { 1548 String className = getClassName(); 1549 1550 if (!isRelationship(primField) && isRelationship(relField) && 1551 !isCollection(className, relField.getName())) 1552 { 1553 ArrayList columns = primField.getColumns(); 1554 Iterator iterator = relField.getColumns().iterator(); 1555 String databaseRoot = getSchemaForClass(className); 1556 1557 while (iterator.hasNext()) 1558 { 1559 if (!testColumn(getLocalColumn((String )iterator.next(), 1560 databaseRoot), columns)) 1561 { 1562 return true; 1563 } 1564 } 1565 } 1566 1567 return false; 1568 } 1569 private boolean testColumn (ColumnElement column, 1570 ArrayList masterList) 1571 { 1572 if ((column != null) && !isPrimaryKeyColumn(column)) 1573 { 1574 return !masterList.contains(NameUtil. 1575 getRelativeMemberName(column.getName().getFullName())); 1576 } 1577 1578 return true; 1579 } 1580 private ColumnElement getLocalColumn (String pairName, 1581 String databaseRoot) 1582 { 1583 ColumnPairElement pair = getPair(pairName, databaseRoot); 1584 1585 return ((pair != null) ? pair.getLocalColumn() : null); 1586 } 1587 private boolean isPrimaryKeyColumn (ColumnElement column) 1588 { 1589 if (column != null) 1590 { 1591 KeyElement key = column.getDeclaringTable().getPrimaryKey(); 1592 1593 return ((key != null) && 1594 (key.getColumn(column.getName()) != null)); 1595 } 1596 1597 return false; 1598 } 1599 private boolean isExactMatch (ArrayList columns1, 1600 ArrayList columns2) 1601 { 1602 int count = columns1.size(); 1603 1604 if ((count > 0) && (count == columns2.size())) 1605 return getDifference(columns1, columns2).isEmpty(); 1606 1607 return false; 1608 } 1609 private boolean isExactMatch (MappingFieldElement field1, 1610 MappingFieldElement field2) 1611 { 1612 boolean field1IsRel = isRelationship(field1); 1613 boolean match = false; 1614 1615 if (field1IsRel == isRelationship(field2)) 1617 { 1618 match = isExactMatch(field1.getColumns(), 1619 field2.getColumns()); 1620 1621 if (match && field1IsRel) 1622 { 1623 MappingRelationshipElement rel1 = 1624 (MappingRelationshipElement)field1; 1625 MappingRelationshipElement rel2 = 1626 (MappingRelationshipElement)field2; 1627 boolean field1IsJoin = isJoin(rel1); 1628 1629 if (field1IsJoin == isJoin(rel2)) 1631 { 1632 if (field1IsJoin) 1633 { 1634 match = isExactMatch( 1635 rel1.getAssociatedColumns(), 1636 rel2.getAssociatedColumns()); 1637 } 1638 } 1639 else 1640 match = false; 1641 } 1642 } 1643 1644 return match; 1645 } 1646 }; 1647 } 1648 1649 1656 protected ValidationComponent createRelatedSchemaMatchesComponent ( 1657 final String relatedClass, final PersistenceFieldElement relatedField) 1658 { 1659 return new ValidationComponent () 1660 { 1661 public void validate () throws ModelValidationException 1662 { 1663 if (relatedClass != null) 1664 { 1665 String className = getClassName(); 1666 String mySchema = getSchemaForClass(className); 1667 String relatedSchema = getSchemaForClass(relatedClass); 1668 1669 if ((mySchema != null) && (relatedSchema != null) && 1670 !(relatedSchema.equals(mySchema))) 1671 { 1672 String fieldName = relatedField.getName(); 1673 1674 throw new ModelValidationException( 1675 getModel().getField(className, fieldName), 1676 I18NHelper.getMessage(getMessages(), 1677 "util.validation.schema_mismatch", new Object []{className, relatedClass, fieldName})); 1679 } 1680 } 1681 } 1682 }; 1683 } 1684 1685 1697 protected ValidationComponent createRelatedTableMatchesComponent ( 1698 final String relatedClass, final PersistenceFieldElement relatedField, 1699 final List tableNames, final String pairName) 1700 { 1701 return new ValidationComponent () 1702 { 1703 public void validate () throws ModelValidationException 1704 { 1705 ColumnPairElement pair = getPair(pairName, 1706 getSchemaForClass(relatedClass)); 1707 1708 if (pair != null) 1709 { 1710 ColumnElement column = pair.getReferencedColumn(); 1711 1712 if (!matchesTable(tableNames, column)) 1713 { 1714 String fieldName = relatedField.getName(); 1715 1716 throw new ModelValidationException( 1717 getModel().getField(getClassName(), fieldName), 1718 I18NHelper.getMessage(getMessages(), 1719 getKey( 1720 "util.validation.table_mismatch", relatedField), 1722 new Object []{column.getName().getFullName(), 1723 fieldName, relatedClass})); 1724 } 1725 } 1726 } 1727 }; 1728 } 1729 1730 1736 protected ValidationComponent createSchemaExistenceComponent ( 1737 final String className) 1738 { 1739 return createSchemaExistenceComponent(className, null); 1740 } 1741 1742 1752 protected ValidationComponent createSchemaExistenceComponent ( 1753 final String className, final PersistenceFieldElement relatedField) 1754 { 1755 return new ValidationComponent () 1756 { 1757 public void validate () throws ModelValidationException 1758 { 1759 String schemaName = getSchemaForClass(className); 1760 1761 if ((schemaName != null) && 1762 (SchemaElement.forName(schemaName) == null)) 1763 { 1764 Object [] args = (relatedField == null) ? 1765 new Object []{schemaName, className} : 1766 new Object []{schemaName, className, relatedField}; 1767 1768 throw new ModelValidationException( 1769 ModelValidationException.WARNING, 1770 getOffendingObject(relatedField), 1771 I18NHelper.getMessage(getMessages(), getKey( 1772 "util.validation.schema_not_found", relatedField), args)); 1774 } 1775 } 1776 }; 1777 } 1778 1779 1785 protected ValidationComponent createPrimaryTableComponent ( 1786 final MappingTableElement primaryTable) 1787 { 1788 return new ValidationComponent () 1789 { 1790 public void validate () throws ModelValidationException 1791 { 1792 if (primaryTable != null) 1793 { 1794 String className = getClassName(); 1795 String schemaName = getSchemaForClass(className); 1796 1797 if (schemaName == null) 1798 { 1799 throw constructClassException(className, null, 1800 "util.validation.schema_not_set"); } 1802 else 1803 { 1804 String tableName = primaryTable.getName(); 1805 TableElement table = getTable(tableName, schemaName); 1806 1807 if ((table != null) && (table.getPrimaryKey() == null)) 1808 { 1809 throw new ModelValidationException( 1810 getOffendingObject(null), 1811 I18NHelper.getMessage(getMessages(), 1812 "util.validation.table_no_primarykey", new Object []{tableName, className})); 1814 } 1815 } 1816 } 1817 } 1818 }; 1819 } 1820 1821 1826 protected ValidationComponent createTableExistenceComponent ( 1827 final String tableName) 1828 { 1829 return createTableExistenceComponent(tableName, null); 1830 } 1831 1832 1841 protected ValidationComponent createTableExistenceComponent ( 1842 final String tableName, final PersistenceFieldElement relatedField) 1843 { 1844 return new ValidationComponent () 1845 { 1846 public void validate () throws ModelValidationException 1847 { 1848 if (tableName != null) 1849 { 1850 String className = getClassName(); 1851 boolean noRelated = (relatedField == null); 1852 TableElement table = getTable(tableName, 1853 getSchemaForClass((noRelated ? className : 1854 getRelatedClass(relatedField)))); 1855 1856 if (table == null) 1857 { 1858 Object [] args = noRelated ? 1859 new Object []{tableName, className} : 1860 new Object []{tableName, relatedField}; 1861 1862 throw new ModelValidationException( 1863 ModelValidationException.WARNING, 1864 getOffendingObject(relatedField), 1865 I18NHelper.getMessage(getMessages(), getKey( 1866 "util.validation.table_not_found", relatedField), args)); 1868 } 1869 } 1870 } 1871 }; 1872 } 1873 1874 1879 protected ValidationComponent createColumnExistenceComponent ( 1880 final String columnName) 1881 { 1882 return createColumnExistenceComponent(columnName, null); 1883 } 1884 1885 1893 protected ValidationComponent createColumnExistenceComponent ( 1894 final String columnName, final MappingFieldElement relatedField) 1895 { 1896 return new ValidationComponent () 1897 { 1898 public void validate () throws ModelValidationException 1899 { 1900 if (columnName != null) 1901 { 1902 String className = getClassName(); 1903 String absoluteName = NameUtil.getAbsoluteMemberName( 1904 getSchemaForClass(className), columnName); 1905 TableElement table = TableElement.forName( 1906 NameUtil.getTableName(absoluteName)); 1907 boolean foundTable = (table != null); 1908 DBMemberElement columnElement = ((foundTable) ? 1909 table.getMember(DBIdentifier.create(absoluteName)) : 1910 null); 1911 boolean noRelated = (relatedField == null); 1912 1913 if (foundTable) 1914 { 1915 boolean isRelationship = 1916 (!noRelated && isRelationship(relatedField)); 1917 boolean noColumn = (columnElement == null); 1918 1919 if (!isRelationship && noColumn) 1920 { 1921 Object [] args = (noRelated) ? 1922 new Object []{columnName, className} : 1923 new Object []{columnName, relatedField, 1924 className}; 1925 1926 throw new ModelValidationException( 1927 ModelValidationException.WARNING, 1928 getOffendingObject(relatedField), 1929 I18NHelper.getMessage(getMessages(), getKey( 1930 "util.validation.column_not_found", relatedField), args)); 1932 } 1933 else if (isRelationship && 1934 (noColumn || !isPairComplete(columnElement))) 1935 { 1936 throw new ModelValidationException( 1937 ModelValidationException.WARNING, 1938 getOffendingObject(relatedField), 1939 I18NHelper.getMessage(getMessages(), 1940 "util.validation.column_invalid", new Object []{columnName, relatedField, 1942 className})); 1943 } 1944 } 1945 } 1946 } 1947 private boolean isPairComplete (DBMemberElement member) 1948 { 1949 return ((member instanceof ColumnPairElement) && 1950 (((ColumnPairElement)member).getLocalColumn() != null) && 1951 (((ColumnPairElement)member).getReferencedColumn() 1952 != null)); 1953 } 1954 }; 1955 } 1956 1957 1962 protected ValidationComponent createColumnOverlapComponent ( 1963 final MappingFieldElement field) 1964 { 1965 return new ValidationComponent () 1966 { 1967 public void validate () throws ModelValidationException 1968 { 1969 MappingClassElement mappingClass = field.getDeclaringClass(); 1970 Iterator iterator = mappingClass.getFields().iterator(); 1971 ArrayList myColumns = field.getColumns(); 1972 1973 while (iterator.hasNext()) 1974 { 1975 MappingFieldElement testField = 1976 (MappingFieldElement)iterator.next(); 1977 1978 if (!testField.equals(field) && !isRelationship(testField) 1979 && isPartialMatch(myColumns, testField.getColumns())) 1980 { 1981 String fieldName = field.getName(); 1982 1983 throw new ModelValidationException(getModel().getField( 1984 getClassName(), fieldName), 1985 I18NHelper.getMessage(getMessages(), 1986 "util.validation.field_mapping_invalid", new Object []{fieldName, testField.getName()})); 1988 } 1989 } 1990 } 1991 private boolean isPartialMatch (ArrayList columns1, 1992 ArrayList columns2) 1993 { 1994 int count = columns1.size(); 1995 1996 if (count > 0) 1997 { 1998 ArrayList difference = getDifference(columns1, columns2); 1999 2000 return (!difference.isEmpty() && 2001 (columns2.size() != difference.size())); 2002 } 2003 2004 return false; 2005 } 2006 }; 2007 } 2008 2009 2026 protected ValidationComponent createKeyClassComponent ( 2027 final String className) 2028 { 2029 return new ValidationComponent () 2030 { 2031 2032 private Object keyClass; 2033 2034 2035 private String keyClassName; 2036 2037 public void validate () throws ModelValidationException 2038 { 2039 keyClassName = validateKeyClassName(className); 2041 keyClass = getModel().getClass(keyClassName, getClassLoader()); 2043 validateClass(); 2044 validateConstructor(); 2045 validateFields(); 2046 validateMethods(); 2047 } 2048 2049 2052 private void validateClass () throws ModelValidationException 2053 { 2054 Model model = getModel(); 2055 int modifiers = model.getModifiersForClass(keyClassName); 2056 boolean hasKeyClassName = !StringHelper.isEmpty(keyClassName); 2057 boolean isInnerClass = 2058 (hasKeyClassName && (keyClassName.indexOf('$') != -1)); 2059 String pcClassName = getClassName(); 2060 2061 if (keyClass == null) 2063 { 2064 throw new ModelValidationException( 2065 ModelValidationException.WARNING, 2066 model.getClass(pcClassName), 2067 I18NHelper.getMessage(getMessages(), 2068 "util.validation.key_class_missing", keyClassName, pcClassName)); 2070 } 2071 2072 if (!Modifier.isPublic(modifiers)) 2074 { 2075 throw new ModelValidationException(keyClass, 2076 I18NHelper.getMessage(getMessages(), 2077 "util.validation.key_class_public", keyClassName, pcClassName)); 2079 } 2080 2081 2096 2097 if (isInnerClass && !Modifier.isStatic(modifiers)) 2099 { 2100 throw new ModelValidationException(keyClass, 2101 I18NHelper.getMessage(getMessages(), 2102 "util.validation.key_class_static", keyClassName, pcClassName)); 2104 } 2105 } 2106 2107 2109 private void validateFields () throws ModelValidationException 2110 { 2111 String pcClassName = getClassName(); 2112 Model model = getModel(); 2113 List keyClassFieldNames = model.getAllFields(keyClassName); 2115 Map keyFields = getKeyFields(); 2116 2117 for (Iterator i = keyClassFieldNames.iterator(); i.hasNext();) 2118 { 2119 String keyClassFieldName = (String )i.next(); 2120 Object keyClassField = 2121 getKeyClassField(keyClassName, keyClassFieldName); 2122 int keyClassFieldModifiers = 2123 model.getModifiers(keyClassField); 2124 String keyClassFieldType = model.getType(keyClassField); 2125 Object keyField = keyFields.get(keyClassFieldName); 2126 2127 if (Modifier.isStatic(keyClassFieldModifiers)) 2128 continue; 2130 2131 if (!model.isValidKeyType(keyClassName, keyClassFieldName)) 2132 { 2133 throw new ModelValidationException(keyClassField, 2134 I18NHelper.getMessage(getMessages(), 2135 "util.validation.key_field_type_invalid", keyClassFieldName, keyClassName)); 2137 } 2138 2139 if (!Modifier.isPublic(keyClassFieldModifiers)) 2140 { 2141 throw new ModelValidationException(keyClassField, 2142 I18NHelper.getMessage(getMessages(), 2143 "util.validation.key_field_public", keyClassFieldName, keyClassName)); 2145 } 2146 2147 if (keyField == null) 2148 continue; 2149 2150 if (!keyClassFieldType.equals(model.getType(keyField))) 2151 { 2152 throw new ModelValidationException(keyClassField, 2153 I18NHelper.getMessage(getMessages(), 2154 "util.validation.key_field_type_mismatch", keyClassFieldName, keyClassName, pcClassName)); 2156 } 2157 2158 keyFields.remove(keyClassFieldName); 2160 } 2161 2162 if (!keyFields.isEmpty()) 2164 { 2165 Object pcClass = model.getClass(pcClassName); 2166 String fieldNames = StringHelper.arrayToSeparatedList( 2167 new ArrayList(keyFields.keySet())); 2168 2169 throw new ModelValidationException(pcClass, 2170 I18NHelper.getMessage(getMessages(), 2171 "util.validation.key_field_missing", pcClassName, keyClassName, fieldNames)); 2173 } 2174 } 2175 2176 2178 private void validateConstructor () throws ModelValidationException 2179 { 2180 Model model = getModel(); 2182 boolean hasConstr = model.hasConstructor(keyClassName); 2183 Object noArgConstr = 2184 model.getConstructor(keyClassName, Model.NO_ARGS); 2185 int modifiers = model.getModifiers(noArgConstr); 2186 2187 if (hasConstr && 2188 ((noArgConstr == null) || !Modifier.isPublic(modifiers))) 2189 { 2190 throw new ModelValidationException(keyClass, 2191 I18NHelper.getMessage(getMessages(), 2192 "util.validation.key_class_constructor", keyClassName, getClassName())); 2194 } 2195 } 2196 2197 2199 private void validateMethods () throws ModelValidationException 2200 { 2201 Model model = getModel(); 2202 Object equalsMethod = getNonObjectMethod(keyClassName, 2203 "equals", Model.EQUALS_ARGS); Object hashCodeMethod = getNonObjectMethod(keyClassName, 2205 "hashCode", Model.NO_ARGS); 2207 if (!matchesMethod(equalsMethod, Modifier.PUBLIC, 2209 0, "boolean")) { 2211 throw new ModelValidationException(keyClass, 2212 I18NHelper.getMessage(getMessages(), 2213 "util.validation.key_class_equals", keyClassName, getClassName())); 2215 } 2216 2217 if (!matchesMethod(hashCodeMethod, Modifier.PUBLIC, 2219 0, "int")) { 2221 throw new ModelValidationException(keyClass, 2222 I18NHelper.getMessage(getMessages(), 2223 "util.validation.key_class_hashcode", keyClassName, getClassName())); 2225 } 2226 } 2227 2228 2230 private String validateKeyClassName (String keyClassName) 2231 throws ModelValidationException 2232 { 2233 String pcClassName = getClassName(); 2234 Model model = getModel(); 2235 boolean hasKeyClassName = !StringHelper.isEmpty(keyClassName); 2236 boolean hasPrefix; 2237 String nameSuffix; 2238 boolean isOIDNameSuffix; 2239 2240 if (!hasKeyClassName) 2242 { 2243 throw new ModelValidationException( 2244 ModelValidationException.WARNING, 2245 model.getClass(pcClassName), 2246 I18NHelper.getMessage(getMessages(), 2247 "util.validation.key_class_unset", pcClassName)); 2249 } 2250 2251 keyClassName = keyClassName.trim(); 2252 hasPrefix = keyClassName.startsWith(pcClassName); 2253 nameSuffix = (hasPrefix ? 2254 keyClassName.substring(pcClassName.length()) : keyClassName); 2255 isOIDNameSuffix = 2256 (nameSuffix.equalsIgnoreCase(".OID") || nameSuffix.equalsIgnoreCase("$OID")); 2259 if (!hasPrefix || 2260 (!nameSuffix.equalsIgnoreCase("Key") && !isOIDNameSuffix)) 2262 { 2263 Object pcClass = getModel().getClass(pcClassName); 2264 throw new ModelValidationException(pcClass, 2265 I18NHelper.getMessage(getMessages(), 2266 "util.validation.key_class_invalid", keyClassName, pcClassName)); 2268 } 2269 if (isOIDNameSuffix) 2270 { 2271 StringBuffer buf = new StringBuffer (keyClassName); 2272 buf.setCharAt(keyClassName.length() - 4, '$'); 2273 return buf.toString(); 2274 } 2275 return keyClassName; 2276 } 2277 2278 private Object getKeyClassField (String keyClassName, 2281 String keyClassFieldName) 2282 { 2283 Model model = getModel(); 2284 Object keyClassField = 2285 model.getField(keyClassName, keyClassFieldName); 2286 2287 if (keyClassField == null) { 2289 keyClassField = model.getInheritedField( 2290 keyClassName, keyClassFieldName); 2291 } 2292 2293 return keyClassField; 2294 } 2295 2296 2298 private Map getKeyFields () 2299 { 2300 Model model = getModel(); 2301 String pcClassName = getClassName(); 2302 PersistenceClassElement pce = 2303 model.getPersistenceClass(pcClassName); 2304 PersistenceFieldElement[] fields = pce.getFields(); 2305 Map keyFields = new HashMap(); 2306 2307 if (fields != null) 2308 { 2309 for (int i = 0; i < fields.length; i++) 2310 { 2311 PersistenceFieldElement pfe = fields[i]; 2312 if (pfe.isKey()) 2313 { 2314 String name = pfe.getName(); 2315 keyFields.put(name, 2316 model.getField(pcClassName, name)); 2317 } 2318 } 2319 } 2320 2321 return keyFields; 2322 } 2323 private Object getNonObjectMethod (String className, 2327 String methodName, String [] argTypeNames) 2328 { 2329 Model model = getModel(); 2330 Object method = 2331 model.getMethod(className, methodName, argTypeNames); 2332 2333 if (method == null) { 2335 method = model.getInheritedMethod( 2336 className, methodName, argTypeNames); 2337 2338 if ((method != null) && model.getDeclaringClass(method). 2339 equals("java.lang.Object")) { 2341 method = null; 2342 } 2343 } 2344 2345 return method; 2346 } 2347 }; 2348 } 2349 2350 2356 protected ValidationComponent createSerializableClassComponent ( 2357 final String className) 2358 { 2359 return new ValidationComponent () 2360 { 2361 public void validate () throws ModelValidationException 2362 { 2363 Model model = getModel(); 2364 Object pcClass = null; 2365 2366 if (className == null) 2367 return; 2368 pcClass = model.getClass(className); 2369 if (pcClass == null) 2370 return; 2371 2372 if (model.implementsInterface(pcClass, "java.io.Serializable")) { 2374 Object readMethod = model.getMethod(className, 2376 "readObject", Model.READ_OBJECT_ARGS); 2378 if (!matchesMethod(readMethod, Modifier.PRIVATE, 2379 Modifier.SYNCHRONIZED, "void")) { 2381 throw new ModelValidationException(pcClass, 2382 I18NHelper.getMessage(getMessages(), 2383 "util.validation.class_readobject", className)); 2385 } 2386 2387 Object writeMethod = model.getMethod(className, 2389 "writeObject", Model.WRITE_OBJECT_ARGS); 2391 if (!matchesMethod(writeMethod, Modifier.PRIVATE, 2392 Modifier.SYNCHRONIZED, "void")) { 2394 throw new ModelValidationException(pcClass, 2395 I18NHelper.getMessage(getMessages(), 2396 "util.validation.class_writeobject", className)); 2398 } 2399 } 2400 } 2401 }; 2402 } 2403 2404 2409 protected ValidationComponent createClassMappingComponent ( 2410 final PersistenceClassElement persistenceClass) 2411 { 2412 return new ValidationComponent () 2413 { 2414 public void validate () throws ModelValidationException 2415 { 2416 PersistenceFieldElement[] fields = persistenceClass.getFields(); 2417 String className = getClassName(); 2418 2419 if ((fields == null) || fields.length == 0) 2420 { 2421 throw constructClassException( 2422 ModelValidationException.WARNING, className, null, 2423 "util.validation.class_no_fields"); } 2425 else { 2427 MappingClassElement mappingClass = 2428 getMappingClass(className); 2429 2430 if ((mappingClass == null) || 2431 (mappingClass.getTables().size() == 0)) 2432 { 2433 throw constructClassException( 2434 ModelValidationException.WARNING, className, null, 2435 "util.validation.class_not_mapped"); } 2437 } 2438 } 2439 }; 2440 } 2441 2442 2447 protected ValidationComponent createKeyColumnMappingComponent ( 2448 final PersistenceClassElement persistenceClass) 2449 { 2450 return new ValidationComponent () 2451 { 2452 public void validate () throws ModelValidationException 2453 { 2454 String className = getClassName(); 2455 MappingClassElement mappingClass = getMappingClass(className); 2456 2457 if (mappingClass != null) 2458 { 2459 List tables = mappingClass.getTables(); 2460 2461 if (tables.size() > 0) 2462 { 2463 String tableName = 2464 ((MappingTableElement)tables.get(0)).getName(); 2465 TableElement table = getTable(tableName, 2466 getSchemaForClass(className)); 2467 List columns = getUnmappedColumnNames( 2468 ((table != null) ? table.getPrimaryKey() : null), 2469 mappingClass); 2470 2471 if ((columns != null) && (columns.size() > 0)) 2472 { 2473 throw new ModelValidationException( 2474 ModelValidationException.WARNING, 2475 getOffendingObject(null), 2476 I18NHelper.getMessage(getMessages(), 2477 "util.validation.class_key_column_missing", className, tableName, 2479 StringHelper.arrayToSeparatedList(columns))); 2480 } 2481 } 2482 } 2483 } 2484 private List getUnmappedColumnNames (KeyElement primaryKey, 2485 MappingClassElement mappingClass) 2486 { 2487 List unmappedColumns = null; 2488 2489 if (primaryKey != null) { 2491 ColumnElement[] columns = primaryKey.getColumns(); 2492 int count = ((columns != null) ? columns.length : 0); 2493 2494 if (count > 0) 2496 { 2497 List mappingFields = mappingClass.getFields(); 2498 Iterator iterator = mappingFields.iterator(); 2499 2500 unmappedColumns = getRelativeColumnNames(columns); 2501 2502 while (iterator.hasNext()) 2503 { 2504 MappingFieldElement field = 2505 (MappingFieldElement)iterator.next(); 2506 2507 if (isKeyField(field)) 2508 unmappedColumns.removeAll(field.getColumns()); 2509 } 2510 } 2511 } 2512 2513 return unmappedColumns; 2514 } 2515 private List getRelativeColumnNames (ColumnElement[] columns) 2516 { 2517 int i, count = ((columns != null) ? columns.length : 0); 2518 List columnNames = new ArrayList(count); 2519 2520 for (i = 0; i < count; i++) 2521 { 2522 columnNames.add(NameUtil.getRelativeMemberName( 2523 columns[i].getName().getFullName())); 2524 } 2525 2526 return columnNames; 2527 } 2528 private boolean isKeyField (MappingFieldElement field) 2529 { 2530 PersistenceFieldElement persistenceField = 2531 persistenceClass.getField(field.getName()); 2532 2533 return ((persistenceField != null) && persistenceField.isKey()); 2534 } 2535 }; 2536 } 2537 2538 2540 2548 private Object getOffendingObject (Object field) 2549 { 2550 return ((field == null) ? 2551 getModel().getClass(getClassName(), getClassLoader()) : 2552 getModel().getField(getClassName(), field.toString())); 2553 } 2554 2555 2564 private String getKey (String keyBase, Object field) 2565 { 2566 return ((field == null) ? keyBase : (keyBase + "_related")); } 2568 2569 2579 private Object [] getArguments (String className, Object field) 2580 { 2581 return ((field == null) ? new Object []{className} : 2582 new Object []{className, field}); 2583 } 2584 2585 2597 private ModelValidationException constructClassException (String className, 2598 Object relatedField, String keyBase) 2599 { 2600 return constructClassException(ModelValidationException.ERROR, 2601 className, relatedField, keyBase); 2602 } 2603 2604 2619 private ModelValidationException constructClassException (int errorType, 2620 String className, Object relatedField, String keyBase) 2621 { 2622 return new ModelValidationException(errorType, 2623 getOffendingObject(relatedField), I18NHelper.getMessage( 2624 getMessages(), getKey(keyBase, relatedField), 2625 getArguments(className, relatedField))); 2626 } 2627 2628 2635 private ModelValidationException constructFieldException (String fieldName, 2636 String key) 2637 { 2638 return constructFieldException(ModelValidationException.ERROR, 2639 fieldName, key); 2640 } 2641 2642 2652 private ModelValidationException constructFieldException (int errorType, 2653 String fieldName, String key) 2654 { 2655 return new ModelValidationException(errorType, 2656 getModel().getField(getClassName(), fieldName), 2657 I18NHelper.getMessage(getMessages(), key, fieldName)); 2658 } 2659 2660 2662 2671 private boolean matchesMethod (final Object method, 2672 final int expectedModifiers, final int optionalModifiers, 2673 final String expectedReturnType) 2674 { 2675 boolean matches = false; 2676 2677 if (method != null) 2678 { 2679 Model model = getModel(); 2680 int modifiers = model.getModifiers(method); 2681 2682 matches = (((modifiers == expectedModifiers) || 2683 (modifiers == (expectedModifiers | optionalModifiers))) && 2684 expectedReturnType.equals(model.getType(method))); 2685 } 2686 2687 return matches; 2688 } 2689 2690 2696 private boolean matchesTable (List tableNames, ColumnElement column) 2697 { 2698 return ((column == null) ? true : tableNames.contains( 2699 column.getDeclaringTable().getName().getName())); 2700 } 2701 2702 private boolean isRelationship (Object field) 2703 { 2704 return ((field instanceof RelationshipElement) || 2705 (field instanceof MappingRelationshipElement)); 2706 } 2707 2708 private boolean shouldBeRelationship (PersistenceFieldElement field) 2709 { 2710 Model model = getModel(); 2711 String fieldType = model.getFieldType(getClassName(), field.getName()); 2712 2713 return (isPersistent(fieldType) || model.isCollection(fieldType)); 2714 } 2715 2716 private boolean isLegalRelationship (PersistenceFieldElement field) 2717 { 2718 return (isRelationship(field) ? shouldBeRelationship(field) : false); 2719 } 2720 2721 private boolean isCollection (String className, String fieldName) 2722 { 2723 Model model = getModel(); 2724 2725 return model.isCollection(model.getFieldType(className, fieldName)); 2726 } 2727 2728 private String getRelatedClass (PersistenceFieldElement field) 2729 { 2730 if (isLegalRelationship(field)) 2731 return getModel().getRelatedClass((RelationshipElement)field); 2732 2733 return null; 2734 } 2735 2736 private String getSchemaForClass (String className) 2737 { 2738 MappingClassElement mappingClass = getMappingClass(className); 2739 String schema = ((mappingClass != null) ? 2740 mappingClass.getDatabaseRoot() : null); 2741 2742 return (StringHelper.isEmpty(schema) ? null : schema.trim()); 2743 } 2744 2745 private MappingRelationshipElement getMappingRelationship ( 2746 RelationshipElement jdoElement) 2747 { 2748 MappingRelationshipElement mappingElement = null; 2749 2750 if (jdoElement != null) 2751 { 2752 MappingClassElement mappingClass = getMappingClass( 2753 jdoElement.getDeclaringClass().getName()); 2754 2755 if (mappingClass != null) 2756 { 2757 MappingFieldElement fieldElement = 2758 mappingClass.getField(jdoElement.getName()); 2759 2760 if (isRelationship(fieldElement)) 2761 mappingElement = (MappingRelationshipElement)fieldElement; 2762 } 2763 } 2764 2765 return mappingElement; 2766 } 2767 2768 private boolean isJoin (MappingRelationshipElement field) 2769 { 2770 if (field != null) 2771 { 2772 ArrayList columns = field.getAssociatedColumns(); 2773 2774 return ((columns != null) && !columns.isEmpty()); 2775 } 2776 2777 return false; 2778 } 2779 2780 private MappingReferenceKeyElement findReferenceKey ( 2781 MappingTableElement primaryTable, MappingTableElement secondaryTable) 2782 { 2783 if ((primaryTable != null) && (secondaryTable != null)) 2784 { 2785 Iterator iterator = primaryTable.getReferencingKeys().iterator(); 2786 2787 while (iterator.hasNext()) 2788 { 2789 MappingReferenceKeyElement testKey = 2790 (MappingReferenceKeyElement)iterator.next(); 2791 2792 if (testKey.getTable().equals(secondaryTable)) 2793 return testKey; 2794 } 2795 } 2796 2797 return null; 2798 } 2799 2800 private TableElement getTable (String tableName, String databaseRoot) 2801 { 2802 String absoluteName = NameUtil.getAbsoluteTableName(databaseRoot, 2803 tableName); 2804 return TableElement.forName(absoluteName); 2805 } 2806 2807 private ColumnPairElement getPair (String pairName, String databaseRoot) 2808 { 2809 String absoluteName = NameUtil.getAbsoluteMemberName( 2810 databaseRoot, pairName); 2811 TableElement tableElement = TableElement.forName( 2812 NameUtil.getTableName(absoluteName)); 2813 DBMemberElement pair = ((tableElement == null) ? null : 2814 tableElement.getMember(DBIdentifier.create(absoluteName))); 2815 2816 return ((pair instanceof ColumnPairElement) ? 2817 ((ColumnPairElement)pair) : null); 2818 } 2819 2820 private ArrayList getDifference (ArrayList columns1, ArrayList columns2) 2821 { 2822 ArrayList differenceColumns = new ArrayList(columns2); 2823 2824 differenceColumns.removeAll(columns1); 2825 2826 return differenceColumns; 2827 } 2828 2829 2832 private MappingClassElement getMappingClass (String className) 2833 { 2834 return getModel().getMappingClass(className, getClassLoader()); 2835 } 2836 2837 2840 private PersistenceClassElement getPersistenceClass (String className) 2841 { 2842 return getModel().getPersistenceClass(className, getClassLoader()); 2843 } 2844 2845 2848 private boolean isPersistent (String className) 2849 { 2850 return getModel().isPersistent(className, getClassLoader()); 2851 } 2852 2853 2856 private boolean isPersistentAllowed (String className, String fieldName) 2857 { 2858 return getModel().isPersistentAllowed(className, getClassLoader(), 2859 fieldName); 2860 } 2861 2863 2865 static abstract class ValidationComponent 2866 { 2867 2869 public ValidationComponent () 2870 { 2871 } 2872 2875 public abstract void validate () throws ModelValidationException; 2876 } 2877} 2878 | Popular Tags |