1 22 package org.jboss.ejb.plugins.cmp.jdbc.metadata; 23 24 import java.lang.reflect.Field ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Modifier ; 27 import java.util.ArrayList ; 28 import java.util.Collections ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 32 import org.jboss.deployment.DeploymentException; 33 import org.jboss.metadata.MetaData; 34 35 import org.w3c.dom.Element ; 36 37 51 public final class JDBCCMPFieldMetaData 52 { 53 public static final byte CHECK_DIRTY_AFTER_GET_TRUE = 1; 54 public static final byte CHECK_DIRTY_AFTER_GET_FALSE = 2; 55 public static final byte CHECK_DIRTY_AFTER_GET_NOT_PRESENT = 4; 56 57 58 private final JDBCEntityMetaData entity; 59 60 61 private final String fieldName; 62 63 64 private final Class fieldType; 65 66 67 private final String columnName; 68 69 73 private final int jdbcType; 74 75 76 private final String sqlType; 77 78 79 private final boolean readOnly; 80 81 82 private final int readTimeOut; 83 84 85 private final boolean primaryKeyMember; 86 87 88 private final boolean notNull; 89 90 91 private final boolean genIndex; 92 93 97 private final Field primaryKeyField; 98 99 100 private final List propertyOverrides = new ArrayList (); 101 102 103 private final boolean unknownPkField; 104 105 106 private final boolean autoIncrement; 107 108 109 private final boolean relationTableField; 110 111 112 private final byte checkDirtyAfterGet; 113 114 115 private final String stateFactory; 116 117 private static byte readCheckDirtyAfterGet(Element element, byte defaultValue) throws DeploymentException 118 { 119 byte checkDirtyAfterGet; 120 String dirtyAfterGetStr = MetaData.getOptionalChildContent(element, "check-dirty-after-get"); 121 if(dirtyAfterGetStr == null) 122 { 123 checkDirtyAfterGet = defaultValue; 124 } 125 else 126 { 127 checkDirtyAfterGet = (Boolean.valueOf(dirtyAfterGetStr).booleanValue() ? 128 CHECK_DIRTY_AFTER_GET_TRUE : CHECK_DIRTY_AFTER_GET_FALSE); 129 } 130 return checkDirtyAfterGet; 131 } 132 133 public static byte readCheckDirtyAfterGet(Element element) throws DeploymentException 134 { 135 return readCheckDirtyAfterGet(element, CHECK_DIRTY_AFTER_GET_NOT_PRESENT); 136 } 137 138 141 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity) 142 { 143 this.entity = entity; 144 fieldName = entity.getName() + "_upk"; 145 fieldType = entity.getPrimaryKeyClass(); columnName = entity.getName() + "_upk"; 147 jdbcType = Integer.MIN_VALUE; 148 sqlType = null; 149 readOnly = entity.isReadOnly(); 150 readTimeOut = entity.getReadTimeOut(); 151 primaryKeyMember = true; 152 notNull = true; 153 primaryKeyField = null; 154 genIndex = false; 155 unknownPkField = true; 156 autoIncrement = false; 157 relationTableField = false; 158 checkDirtyAfterGet = CHECK_DIRTY_AFTER_GET_NOT_PRESENT; 159 stateFactory = null; 160 } 161 162 170 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, String fieldName) 171 throws DeploymentException 172 { 173 this.entity = entity; 174 this.fieldName = fieldName; 175 176 fieldType = loadFieldType(entity, fieldName); 177 columnName = fieldName; 178 jdbcType = Integer.MIN_VALUE; 179 sqlType = null; 180 readOnly = entity.isReadOnly(); 181 readTimeOut = entity.getReadTimeOut(); 182 genIndex = false; 183 184 String pkFieldName = entity.getPrimaryKeyFieldName(); 186 if(pkFieldName != null) 187 { 188 primaryKeyField = null; 190 191 if(pkFieldName.equals(fieldName)) 193 { 194 if(!entity.getPrimaryKeyClass().equals(fieldType)) 196 { 197 throw new DeploymentException("primkey-field must be the same type as prim-key-class"); 198 } 199 primaryKeyMember = true; 201 } 202 else 203 { 204 primaryKeyMember = false; 205 } 206 } 207 else 208 { 209 Field [] fields = entity.getPrimaryKeyClass().getFields(); 211 212 boolean pkMember = false; 213 Field pkField = null; 214 for(int i = 0; i < fields.length; i++) 215 { 216 final Field field = fields[i]; 217 if(field.getName().equals(fieldName)) 218 { 219 220 if(!field.getType().equals(fieldType)) 222 { 223 throw new DeploymentException("Field " + fieldName + " in prim-key-class must be of the same type."); 224 } 225 226 if(pkField != null) 227 { 228 if(field.getDeclaringClass().equals(entity.getPrimaryKeyClass())) 229 { 230 pkField = field; 231 } 232 233 org.jboss.logging.Logger.getLogger(getClass().getName() + '.' + entity.getName()).warn( 234 "PK field " + fieldName + " was found more than once in class hierarchy of " + 235 entity.getPrimaryKeyClass().getName() + ". Will use the one from " + pkField.getDeclaringClass().getName() 236 ); 237 } 238 else 239 { 240 pkField = field; 241 } 242 243 pkMember = true; 245 } 246 } 247 primaryKeyMember = pkMember; 248 primaryKeyField = pkField; 249 } 250 notNull = fieldType.isPrimitive() || primaryKeyMember; 251 252 unknownPkField = false; 253 autoIncrement = false; 254 relationTableField = false; 255 checkDirtyAfterGet = CHECK_DIRTY_AFTER_GET_NOT_PRESENT; 256 stateFactory = null; 257 } 258 259 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, 260 JDBCCMPFieldMetaData defaultValues) 261 { 262 this.entity = entity; 263 fieldName = defaultValues.getFieldName(); 264 fieldType = defaultValues.getFieldType(); 265 columnName = defaultValues.getColumnName(); 266 jdbcType = defaultValues.getJDBCType(); 267 sqlType = defaultValues.getSQLType(); 268 readOnly = entity.isReadOnly(); 269 readTimeOut = entity.getReadTimeOut(); 270 primaryKeyMember = defaultValues.isPrimaryKeyMember(); 271 primaryKeyField = defaultValues.getPrimaryKeyField(); 272 notNull = defaultValues.isNotNull(); 273 unknownPkField = defaultValues.isUnknownPkField(); 274 autoIncrement = defaultValues.isAutoIncrement(); 275 genIndex = false; relationTableField = defaultValues.isRelationTableField(); 277 checkDirtyAfterGet = defaultValues.getCheckDirtyAfterGet(); 278 stateFactory = defaultValues.getStateFactory(); 279 } 280 281 293 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, 294 Element element, 295 JDBCCMPFieldMetaData defaultValues) 296 throws DeploymentException 297 { 298 this.entity = entity; 299 300 this.unknownPkField = defaultValues.isUnknownPkField(); 302 303 String unknownFieldName = 306 MetaData.getOptionalChildContent(element, "field-name"); 307 if(unknownPkField && unknownFieldName != null) 308 { 309 fieldName = unknownFieldName; 310 } 311 else 312 { 313 fieldName = defaultValues.getFieldName(); 314 } 315 316 String unknownPkClass = MetaData.getOptionalChildContent(element, "unknown-pk-class"); 319 if(unknownPkClass == null) 320 { 321 fieldType = defaultValues.getFieldType(); 322 } 323 else 324 { 325 try 326 { 327 fieldType = entity.getClassLoader().loadClass(unknownPkClass); 328 } 329 catch(ClassNotFoundException e) 330 { 331 throw new DeploymentException("could not load the class for " 332 + " unknown primary key: " + unknownPkClass); 333 } 334 } 335 336 String columnStr = MetaData.getOptionalChildContent(element, "column-name"); 338 if(columnStr != null) 339 { 340 columnName = columnStr; 341 } 342 else 343 { 344 columnName = defaultValues.getColumnName(); 345 } 346 347 String jdbcStr = MetaData.getOptionalChildContent(element, "jdbc-type"); 349 if(jdbcStr != null) 350 { 351 jdbcType = JDBCMappingMetaData.getJdbcTypeFromName(jdbcStr); 352 sqlType = MetaData.getUniqueChildContent(element, "sql-type"); 354 } 355 else 356 { 357 jdbcType = defaultValues.getJDBCType(); 358 sqlType = defaultValues.getSQLType(); 359 } 360 361 String readOnlyStr = MetaData.getOptionalChildContent(element, "read-only"); 363 if(readOnlyStr != null) 364 { 365 readOnly = Boolean.valueOf(readOnlyStr).booleanValue(); 366 } 367 else 368 { 369 readOnly = defaultValues.isReadOnly(); 370 } 371 372 String readTimeOutStr = MetaData.getOptionalChildContent(element, "read-time-out"); 374 if(readTimeOutStr != null) 375 { 376 try 377 { 378 readTimeOut = Integer.parseInt(readTimeOutStr); 379 } 380 catch(NumberFormatException e) 381 { 382 throw new DeploymentException("Invalid number format in " + 383 "read-time-out '" + readTimeOutStr + "': " + e); 384 } 385 } 386 else 387 { 388 readTimeOut = defaultValues.getReadTimeOut(); 389 } 390 391 this.primaryKeyMember = defaultValues.isPrimaryKeyMember(); 393 394 primaryKeyField = defaultValues.getPrimaryKeyField(); 396 397 Element notNullElement = MetaData.getOptionalChild(element, "not-null"); 399 notNull = 400 fieldType.isPrimitive() || 401 primaryKeyMember || 402 (notNullElement != null); 403 404 Iterator iterator = MetaData.getChildrenByTagName(element, "property"); 406 while(iterator.hasNext()) 407 { 408 propertyOverrides.add(new JDBCCMPFieldPropertyMetaData(this, (Element )iterator.next())); 409 } 410 411 autoIncrement = MetaData.getOptionalChild(element, "auto-increment") != null; 413 414 if(MetaData.getOptionalChild(element, "dbindex") == null) 416 genIndex = false; 417 else 418 genIndex = true; 419 420 relationTableField = defaultValues.isRelationTableField(); 421 422 checkDirtyAfterGet = readCheckDirtyAfterGet(element, defaultValues.getCheckDirtyAfterGet()); 423 424 String stateFactoryStr = MetaData.getOptionalChildContent(element, "state-factory"); 425 if(stateFactoryStr == null) 426 stateFactory = defaultValues.getStateFactory(); 427 else 428 stateFactory = stateFactoryStr; 429 } 430 431 444 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, 445 Element element, 446 JDBCCMPFieldMetaData defaultValues, 447 boolean primaryKeyMember, 448 boolean notNull, 449 boolean readOnly, 450 int readTimeOut, 451 boolean relationTableField) 452 throws DeploymentException 453 { 454 this.entity = entity; 455 fieldName = defaultValues.getFieldName(); 456 fieldType = defaultValues.getFieldType(); 457 String columnStr = MetaData.getOptionalChildContent(element, "column-name"); 458 if(columnStr != null) 459 { 460 columnName = columnStr; 461 } 462 else 463 { 464 columnName = defaultValues.getColumnName(); 465 } 466 467 String jdbcStr = MetaData.getOptionalChildContent(element, "jdbc-type"); 469 if(jdbcStr != null) 470 { 471 jdbcType = JDBCMappingMetaData.getJdbcTypeFromName(jdbcStr); 472 sqlType = MetaData.getUniqueChildContent(element, "sql-type"); 473 } 474 else 475 { 476 jdbcType = defaultValues.getJDBCType(); 477 sqlType = defaultValues.getSQLType(); 478 } 479 480 this.readOnly = readOnly; 482 483 this.readTimeOut = readTimeOut; 485 486 this.primaryKeyMember = primaryKeyMember; 488 489 this.notNull = notNull; 491 492 primaryKeyField = defaultValues.getPrimaryKeyField(); 494 495 Iterator iterator = MetaData.getChildrenByTagName(element, "property"); 497 while(iterator.hasNext()) 498 { 499 propertyOverrides.add(new JDBCCMPFieldPropertyMetaData(this, (Element )iterator.next())); 500 } 501 502 this.unknownPkField = defaultValues.isUnknownPkField(); 503 autoIncrement = MetaData.getOptionalChild(element, "auto-increment") != null; 504 505 if(MetaData.getOptionalChild(element, "dbindex") == null) 506 genIndex = false; 507 else 508 genIndex = true; 509 510 this.relationTableField = relationTableField; 511 512 String dirtyAfterGetStr = MetaData.getOptionalChildContent(element, "check-dirty-after-get"); 513 if(dirtyAfterGetStr == null) 514 { 515 checkDirtyAfterGet = defaultValues.getCheckDirtyAfterGet(); 516 } 517 else 518 { 519 checkDirtyAfterGet = (Boolean.valueOf(dirtyAfterGetStr).booleanValue() ? 520 CHECK_DIRTY_AFTER_GET_TRUE : CHECK_DIRTY_AFTER_GET_FALSE); 521 } 522 523 String stateFactoryStr = MetaData.getOptionalChildContent(element, "state-factory"); 524 if(stateFactoryStr == null) 525 stateFactory = defaultValues.getStateFactory(); 526 else 527 stateFactory = stateFactoryStr; 528 } 529 530 533 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, 534 JDBCCMPFieldMetaData defaultValues, 535 String columnName, 536 boolean primaryKeyMember, 537 boolean notNull, 538 boolean readOnly, 539 int readTimeOut, 540 boolean relationTableField) 541 { 542 this.entity = entity; 543 fieldName = defaultValues.getFieldName(); 544 fieldType = defaultValues.getFieldType(); 545 this.columnName = columnName; 546 jdbcType = defaultValues.getJDBCType(); 547 sqlType = defaultValues.getSQLType(); 548 this.readOnly = readOnly; 549 this.readTimeOut = readTimeOut; 550 this.primaryKeyMember = primaryKeyMember; 551 primaryKeyField = defaultValues.getPrimaryKeyField(); 552 this.notNull = notNull; 553 554 for(Iterator i = defaultValues.propertyOverrides.iterator(); i.hasNext();) 555 { 556 propertyOverrides.add(new JDBCCMPFieldPropertyMetaData( 557 this, (JDBCCMPFieldPropertyMetaData)i.next())); 558 } 559 560 this.unknownPkField = defaultValues.isUnknownPkField(); 561 autoIncrement = false; 562 genIndex = false; 563 564 this.relationTableField = relationTableField; 565 checkDirtyAfterGet = defaultValues.getCheckDirtyAfterGet(); 566 stateFactory = defaultValues.getStateFactory(); 567 } 568 569 570 573 public JDBCCMPFieldMetaData(JDBCEntityMetaData entity, 574 String fieldName, 575 Class fieldType, 576 String columnName, 577 int jdbcType, 578 String sqlType) 579 throws DeploymentException 580 { 581 this.entity = entity; 582 this.fieldName = fieldName; 583 this.fieldType = fieldType; 584 this.columnName = columnName; 585 this.jdbcType = jdbcType; 586 this.sqlType = sqlType; 587 readOnly = false; 588 readTimeOut = -1; 589 primaryKeyMember = false; 590 notNull = true; 591 primaryKeyField = null; 592 unknownPkField = false; 593 autoIncrement = false; 594 genIndex = false; 595 relationTableField = false; 596 checkDirtyAfterGet = CHECK_DIRTY_AFTER_GET_NOT_PRESENT; 597 stateFactory = null; 598 } 599 600 601 605 public JDBCEntityMetaData getEntity() 606 { 607 return entity; 608 } 609 610 614 public String getFieldName() 615 { 616 return fieldName; 617 } 618 619 623 public Class getFieldType() 624 { 625 return fieldType; 626 } 627 628 634 public String getColumnName() 635 { 636 return columnName; 637 } 638 639 644 public int getJDBCType() 645 { 646 return jdbcType; 647 } 648 649 654 public String getSQLType() 655 { 656 return sqlType; 657 } 658 659 665 public List getPropertyOverrides() 666 { 667 return Collections.unmodifiableList(propertyOverrides); 668 } 669 670 675 public boolean isReadOnly() 676 { 677 return readOnly; 678 } 679 680 686 public int getReadTimeOut() 687 { 688 return readTimeOut; 689 } 690 691 695 public boolean isPrimaryKeyMember() 696 { 697 return primaryKeyMember; 698 } 699 700 704 public boolean isNotNull() 705 { 706 return notNull; 707 } 708 709 716 public boolean isIndexed() 717 { 718 return genIndex; 719 } 720 721 728 public Field getPrimaryKeyField() 729 { 730 return primaryKeyField; 731 } 732 733 737 public boolean isUnknownPkField() 738 { 739 return unknownPkField; 740 } 741 742 745 public boolean isAutoIncrement() 746 { 747 return autoIncrement; 748 } 749 750 public boolean isRelationTableField() 751 { 752 return relationTableField; 753 } 754 755 public byte getCheckDirtyAfterGet() 756 { 757 return checkDirtyAfterGet; 758 } 759 760 public String getStateFactory() 761 { 762 return stateFactory; 763 } 764 765 773 public boolean equals(Object o) 774 { 775 if(o instanceof JDBCCMPFieldMetaData) 776 { 777 JDBCCMPFieldMetaData cmpField = (JDBCCMPFieldMetaData)o; 778 return fieldName.equals(cmpField.fieldName) && 779 entity.equals(cmpField.entity); 780 } 781 return false; 782 } 783 784 790 public int hashCode() 791 { 792 int result = 17; 793 result = 37 * result + entity.hashCode(); 794 result = 37 * result + fieldName.hashCode(); 795 return result; 796 } 797 798 808 public String toString() 809 { 810 return "[JDBCCMPFieldMetaData : fieldName=" + fieldName + ", " + 811 entity + "]"; 812 } 813 814 821 private Class loadFieldType(JDBCEntityMetaData entity, String fieldName) 822 throws DeploymentException 823 { 824 if(entity.isCMP1x()) 825 { 826 try 828 { 829 return entity.getEntityClass().getField(fieldName).getType(); 830 } 831 catch(NoSuchFieldException e) 832 { 833 throw new DeploymentException("No field named '" + fieldName + 834 "' found in entity class." + 835 entity.getEntityClass().getName()); 836 } 837 } 838 else 839 { 840 String baseName = Character.toUpperCase(fieldName.charAt(0)) + 842 fieldName.substring(1); 843 String getName = "get" + baseName; 844 String setName = "set" + baseName; 845 846 Method [] methods = entity.getEntityClass().getMethods(); 847 for(int i = 0; i < methods.length; i++) 848 { 849 if(Modifier.isPublic(methods[i].getModifiers()) && 851 Modifier.isAbstract(methods[i].getModifiers())) 852 { 853 854 if(getName.equals(methods[i].getName()) && 856 methods[i].getParameterTypes().length == 0 && 857 !methods[i].getReturnType().equals(Void.TYPE)) 858 { 859 return methods[i].getReturnType(); 860 } 861 862 if(setName.equals(methods[i].getName()) && 864 methods[i].getParameterTypes().length == 1 && 865 methods[i].getReturnType().equals(Void.TYPE)) 866 { 867 868 return methods[i].getParameterTypes()[0]; 869 } 870 } 871 } 872 throw new DeploymentException("No abstract accessors for field " + 873 "named '" + fieldName + "' found in entity class " + 874 entity.getEntityClass().getName()); 875 } 876 } 877 } 878 | Popular Tags |