1 29 30 package com.caucho.amber.cfg; 31 32 import com.caucho.amber.entity.Listener; 33 34 import com.caucho.amber.field.*; 35 import com.caucho.amber.idgen.IdGenerator; 36 import com.caucho.amber.manager.AmberPersistenceUnit; 37 import com.caucho.amber.table.Column; 38 import com.caucho.amber.table.ForeignColumn; 39 import com.caucho.amber.table.LinkColumns; 40 import com.caucho.amber.table.Table; 41 import com.caucho.amber.type.*; 42 import com.caucho.bytecode.*; 43 import com.caucho.config.ConfigException; 44 import com.caucho.jdbc.JdbcMetaData; 45 import com.caucho.util.L10N; 46 47 import javax.persistence.*; 48 import java.sql.SQLException ; 49 import java.util.ArrayList ; 50 import java.util.HashMap ; 51 import java.util.logging.Level ; 52 import java.util.logging.Logger ; 53 54 55 58 public class BaseConfigIntrospector extends AbstractConfigIntrospector { 59 private static final Logger log 60 = Logger.getLogger(BaseConfigIntrospector.class.getName()); 61 private static final L10N L = new L10N(BaseConfigIntrospector.class); 62 63 AmberPersistenceUnit _persistenceUnit; 64 65 ArrayList <Completion> _linkCompletions = new ArrayList <Completion>(); 66 ArrayList <Completion> _depCompletions = new ArrayList <Completion>(); 67 68 HashMap <RelatedType, ArrayList <OneToOneCompletion>> _oneToOneCompletions 69 = new HashMap <RelatedType, ArrayList <OneToOneCompletion>>(); 70 71 HashMap <String , EmbeddableConfig> _embeddableConfigMap 72 = new HashMap <String , EmbeddableConfig>(); 73 74 HashMap <String , EntityConfig> _entityConfigMap 75 = new HashMap <String , EntityConfig>(); 76 77 HashMap <String , MappedSuperclassConfig> _mappedSuperclassConfigMap 78 = new HashMap <String , MappedSuperclassConfig>(); 79 80 83 public BaseConfigIntrospector() 84 { 85 } 86 87 90 public BaseConfigIntrospector(AmberPersistenceUnit persistenceUnit) 91 { 92 _persistenceUnit = persistenceUnit; 93 } 94 95 98 public void setEntityConfigMap(HashMap <String , EntityConfig> entityConfigMap) 99 { 100 _entityConfigMap = entityConfigMap; 101 } 102 103 106 public void setMappedSuperclassConfigMap(HashMap <String , MappedSuperclassConfig> 107 mappedSuperclassConfigMap) 108 { 109 _mappedSuperclassConfigMap = mappedSuperclassConfigMap; 110 } 111 112 116 public void initMetaData(EntityMappingsConfig entityMappings, 117 AmberPersistenceUnit persistenceUnit) 118 throws ConfigException 119 { 120 PersistenceUnitMetaDataConfig metaData; 121 metaData = entityMappings.getPersistenceUnitMetaData(); 122 123 if (metaData == null) 124 return; 125 126 PersistenceUnitDefaultsConfig defaults; 127 128 defaults = metaData.getPersistenceUnitDefaults(); 129 130 if (defaults == null) 131 return; 132 133 EntityListenersConfig entityListeners; 134 entityListeners = defaults.getEntityListeners(); 135 136 if (entityListeners == null) 137 return; 138 139 ArrayList <EntityListenerConfig> listeners; 140 listeners = entityListeners.getEntityListeners(); 141 142 for (EntityListenerConfig listener : listeners) 143 introspectDefaultListener(listener, persistenceUnit); 144 } 145 146 public void introspectDefaultListener(EntityListenerConfig listener, 147 AmberPersistenceUnit persistenceUnit) 148 throws ConfigException 149 { 150 JClassLoader loader = persistenceUnit.getJClassLoader(); 151 152 String className = listener.getClassName(); 153 154 JClass type = loader.forName(className); 155 156 if (type == null) 157 throw new ConfigException(L.l("'{0}' is an unknown type for <entity-listener> in orm.xml", 158 className)); 159 160 ListenerType listenerType = persistenceUnit.addDefaultListener(type); 161 162 introspectListener(type, listenerType); 163 } 164 165 public void introspectEntityListeners(JClass type, 166 RelatedType relatedType, 167 AmberPersistenceUnit persistenceUnit) 168 throws ConfigException 169 { 170 getInternalEntityListenersConfig(type); 171 JAnnotation entityListenersAnn = _annotationCfg.getAnnotation(); 172 EntityListenersConfig entityListenersCfg 173 = _annotationCfg.getEntityListenersConfig(); 174 175 Object listeners[] = null; 176 177 if (entityListenersCfg != null) 179 listeners = entityListenersCfg.getEntityListeners().toArray(); 180 else if (entityListenersAnn != null) 181 listeners = (Object []) entityListenersAnn.get("value"); 182 else 183 return; 184 185 String relatedTypeName = relatedType.getBeanClass().getName(); 186 187 for (int i=0; i < listeners.length; i++) { 188 189 JClass cl; 190 191 if (listeners[i] instanceof JClass) 193 cl = (JClass) listeners[i]; 194 else { 195 JClassLoader loader = persistenceUnit.getJClassLoader(); 196 197 EntityListenerConfig listenerConfig 198 = (EntityListenerConfig) listeners[i]; 199 200 String className = listenerConfig.getClassName(); 201 202 cl = loader.forName(className); 203 204 if (cl == null) 205 throw new ConfigException(L.l("'{0}' is an unknown type for <entity-listener> in orm.xml", 206 className)); 207 } 208 209 if (persistenceUnit.getDefaultListener(cl.getName()) != null) 210 continue; 211 212 introspectEntityListener(cl, 213 persistenceUnit, 214 relatedType, 215 relatedTypeName); 216 } 217 } 218 219 public void introspectEntityListener(JClass type, 220 AmberPersistenceUnit persistenceUnit, 221 RelatedType sourceType, 222 String sourceClassName) 223 throws ConfigException 224 { 225 if (type == null) { 226 throw new ConfigException(L.l("'{0}' is an unknown type for @EntityListeners annotated at class '{1}'", 227 type.getName(), 228 sourceClassName)); 229 } 230 231 JClass parentClass = type.getSuperClass(); 232 233 if (parentClass == null) { 234 return; 236 } 237 else { 238 243 introspectEntityListener(parentClass, persistenceUnit, 244 sourceType, sourceClassName); 245 } 246 247 249 ListenerType listenerType 250 = persistenceUnit.getEntityListener(type.getName()); 251 252 ListenerType newListenerType 253 = persistenceUnit.addEntityListener(sourceClassName, type); 254 255 if (listenerType == null) { 256 listenerType = newListenerType; 257 introspectListener(type, listenerType); 258 } 259 260 sourceType.addListener(listenerType); 261 } 262 263 public void introspectListener(JClass type, 264 ListenerType listenerType) 265 throws ConfigException 266 { 267 listenerType.setInstanceClassName(listenerType.getName() + "__ResinExt"); 268 269 for (JMethod method : type.getMethods()) { 270 introspectCallbacks(listenerType, method); 271 } 272 } 273 274 277 public void introspectCallbacks(JClass type, 278 EntityType entityType) 279 throws ConfigException 280 { 281 getInternalExcludeDefaultListenersConfig(type); 282 283 if (! _annotationCfg.isNull()) 284 entityType.setExcludeDefaultListeners(true); 285 286 getInternalExcludeSuperclassListenersConfig(type); 287 288 if (! _annotationCfg.isNull()) 289 entityType.setExcludeSuperclassListeners(true); 290 291 for (JMethod method : type.getMethods()) { 292 introspectCallbacks(entityType, method); 293 } 294 } 295 296 299 public void introspectCallbacks(AbstractEnhancedType type, 300 JMethod method) 301 throws ConfigException 302 { 303 JClass []param = method.getParameterTypes(); 304 305 String methodName = method.getName(); 306 JClass jClass = type.getBeanClass(); 307 308 boolean isListener = type instanceof ListenerType; 309 310 int n = ListenerType.CALLBACK_CLASS.length; 311 312 for (int i=1; i < n; i++) { 313 getInternalCallbackConfig(i, jClass, method, methodName); 314 315 if (! _annotationCfg.isNull()) { 316 validateCallback(ListenerType.CALLBACK_CLASS[i].getName(), 317 method, isListener); 318 319 type.addCallback(i, method); 320 } 321 } 322 } 323 324 327 void introspectNamedQueries(JClass type, String typeName) 328 { 329 331 getInternalNamedQueryConfig(type); 332 JAnnotation namedQueryAnn = _annotationCfg.getAnnotation(); 333 NamedQueryConfig namedQueryConfig = _annotationCfg.getNamedQueryConfig(); 334 335 JAnnotation namedQueriesAnn = type.getAnnotation(NamedQueries.class); 337 339 if ((namedQueryAnn == null) && (namedQueriesAnn == null)) 340 return; 341 342 Object namedQueryArray[]; 343 344 if ((namedQueryAnn != null) && (namedQueriesAnn != null)) { 345 throw new ConfigException(L.l("{0} may not have both @NamedQuery and @NamedQueries", 346 typeName)); 347 } 348 else if (namedQueriesAnn != null) { 349 namedQueryArray = (Object []) namedQueriesAnn.get("value"); 350 } 351 else { 352 namedQueryArray = new Object [] { namedQueryAnn }; 353 } 354 355 for (int i=0; i < namedQueryArray.length; i++) { 356 namedQueryAnn = (JAnnotation) namedQueryArray[i]; 357 _persistenceUnit.addNamedQuery(namedQueryAnn.getString("name"), 358 namedQueryAnn.getString("query")); 359 } 360 } 361 362 365 void introspectNamedNativeQueries(JClass type, String typeName) 366 { 367 369 getInternalNamedNativeQueryConfig(type); 370 JAnnotation namedNativeQueryAnn = _annotationCfg.getAnnotation(); 371 NamedNativeQueryConfig namedNativeQueryConfig = _annotationCfg.getNamedNativeQueryConfig(); 372 373 JAnnotation namedNativeQueriesAnn = type.getAnnotation(NamedNativeQueries.class); 374 375 if ((namedNativeQueryAnn == null) && (namedNativeQueriesAnn == null)) 376 return; 377 378 Object namedNativeQueryArray[]; 379 380 if ((namedNativeQueryAnn != null) && (namedNativeQueriesAnn != null)) { 381 throw new ConfigException(L.l("{0} may not have both @NamedNativeQuery and @NamedNativeQueries", 382 typeName)); 383 } 384 else if (namedNativeQueriesAnn != null) { 385 namedNativeQueryArray = (Object []) namedNativeQueriesAnn.get("value"); 386 } 387 else { 388 namedNativeQueryArray = new Object [] { namedNativeQueryAnn }; 389 } 390 391 for (int i=0; i < namedNativeQueryArray.length; i++) { 392 namedNativeQueryAnn = (JAnnotation) namedNativeQueryArray[i]; 393 394 NamedNativeQueryConfig nativeQueryConfig = new NamedNativeQueryConfig(); 395 396 nativeQueryConfig.setQuery(namedNativeQueryAnn.getString("query")); 397 nativeQueryConfig.setResultClass(namedNativeQueryAnn.getClass("resultClass").getName()); 398 nativeQueryConfig.setResultSetMapping(namedNativeQueryAnn.getString("resultSetMapping")); 399 400 _persistenceUnit.addNamedNativeQuery(namedNativeQueryAnn.getString("name"), 401 nativeQueryConfig); 402 } 403 } 404 405 408 void introspectSqlResultSetMappings(JClass type, 409 RelatedType relatedType, 410 String typeName) 411 { 412 414 getInternalSqlResultSetMappingConfig(type); 415 JAnnotation sqlResultSetMappingAnn = _annotationCfg.getAnnotation(); 416 SqlResultSetMappingConfig sqlResultSetMappingConfig 417 = _annotationCfg.getSqlResultSetMappingConfig(); 418 419 JAnnotation sqlResultSetMappingsAnn = type.getAnnotation(SqlResultSetMappings.class); 420 421 if ((sqlResultSetMappingAnn == null) && (sqlResultSetMappingsAnn == null)) 422 return; 423 424 Object sqlResultSetMappingArray[]; 425 426 if ((sqlResultSetMappingAnn != null) && (sqlResultSetMappingsAnn != null)) { 427 throw new ConfigException(L.l("{0} may not have both @SqlResultSetMapping and @SqlResultSetMappings", 428 typeName)); 429 } 430 else if (sqlResultSetMappingsAnn != null) { 431 sqlResultSetMappingArray = (Object []) sqlResultSetMappingsAnn.get("value"); 432 } 433 else { 434 sqlResultSetMappingArray = new Object [] { sqlResultSetMappingAnn }; 435 } 436 437 if (sqlResultSetMappingConfig != null) { 438 _persistenceUnit.addSqlResultSetMapping(sqlResultSetMappingConfig.getName(), 439 sqlResultSetMappingConfig); 440 return; 441 } 442 443 for (int i=0; i < sqlResultSetMappingArray.length; i++) { 444 sqlResultSetMappingAnn = (JAnnotation) sqlResultSetMappingArray[i]; 445 446 String name = sqlResultSetMappingAnn.getString("name"); 447 Object entities[] = (Object []) sqlResultSetMappingAnn.get("entities"); 448 Object columns[] = (Object []) sqlResultSetMappingAnn.get("columns"); 449 450 SqlResultSetMappingCompletion completion 451 = new SqlResultSetMappingCompletion(relatedType, name, 452 entities, columns); 453 454 _depCompletions.add(completion); 455 } 456 } 457 458 461 void addSqlResultSetMapping(String resultSetName, 462 Object entities[], 463 Object columns[]) 464 throws ConfigException 465 { 466 468 SqlResultSetMappingConfig sqlResultSetMapping 469 = new SqlResultSetMappingConfig(); 470 471 for (int i=0; i < entities.length; i++) { 473 JAnnotation entityResult = (JAnnotation) entities[i]; 474 475 String className = entityResult.getClass("entityClass").getName(); 476 477 EntityType resultType = _persistenceUnit.getEntity(className); 478 479 if (resultType == null) 480 throw new ConfigException(L.l("entityClass '{0}' is not an @Entity bean for @SqlResultSetMapping '{1}'. The entityClass of an @EntityResult must be an @Entity bean.", 481 className, 482 resultSetName)); 483 484 EntityResultConfig entityResultConfig = new EntityResultConfig(); 485 486 entityResultConfig.setEntityClass(className); 487 488 Object fields[] = (Object []) entityResult.get("fields"); 490 491 for (int j=0; j < fields.length; j++) { 492 JAnnotation fieldResult = (JAnnotation) fields[j]; 493 494 String fieldName = fieldResult.getString("name"); 495 496 AmberField field = resultType.getField(fieldName); 497 498 if (field == null) 499 throw new ConfigException(L.l("@FieldResult with field name '{0}' is not a field for @EntityResult bean '{1}' in @SqlResultSetMapping '{2}'", 500 fieldName, 501 className, 502 resultSetName)); 503 504 String columnName = fieldResult.getString("column"); 505 506 if (columnName == null || columnName.length() == 0) 507 throw new ConfigException(L.l("@FieldResult must have a column name defined and it must not be empty for '{0}' in @EntityResult '{1}' @SqlResultSetMapping '{2}'", 508 fieldName, 509 className, 510 resultSetName)); 511 512 FieldResultConfig fieldResultConfig = new FieldResultConfig(); 513 514 fieldResultConfig.setName(fieldName); 515 fieldResultConfig.setColumn(columnName); 516 517 entityResultConfig.addFieldResult(fieldResultConfig); 518 } 519 520 sqlResultSetMapping.addEntityResult(entityResultConfig); 521 } 522 523 for (int i=0; i < columns.length; i++) { 525 JAnnotation columnResult = (JAnnotation) columns[i]; 526 527 String columnName = columnResult.getString("name"); 528 529 if (columnName == null || columnName.length() == 0) 530 throw new ConfigException(L.l("@ColumnResult must have a column name defined and it must not be empty in @SqlResultSetMapping '{0}'", 531 resultSetName)); 532 533 ColumnResultConfig columnResultConfig = new ColumnResultConfig(); 534 535 columnResultConfig.setName(columnName); 536 537 sqlResultSetMapping.addColumnResult(columnResultConfig); 538 } 539 540 _persistenceUnit.addSqlResultSetMapping(resultSetName, 542 sqlResultSetMapping); 543 } 544 545 548 public void configure() 549 throws ConfigException 550 { 551 ConfigException exn = null; 552 553 while (_depCompletions.size() > 0 || _linkCompletions.size() > 0) { 554 while (_linkCompletions.size() > 0) { 555 Completion completion = _linkCompletions.remove(0); 556 557 try { 558 completion.complete(); 559 } catch (Exception e) { 560 completion.getRelatedType().setConfigException(e); 561 562 if (exn == null) 563 exn = new ConfigException(e); 564 else 565 log.log(Level.WARNING, e.toString(), e); 566 } 567 } 568 569 if (_depCompletions.size() > 0) { 570 Completion completion = _depCompletions.remove(0); 571 572 573 try { 574 completion.complete(); 575 } catch (Exception e) { 576 completion.getRelatedType().setConfigException(e); 577 578 log.log(Level.WARNING, e.toString(), e); 579 580 if (exn == null) 581 exn = new ConfigException(e); 582 else 583 log.log(Level.WARNING, e.toString(), e); 584 } 585 } 586 } 587 588 if (exn != null) 589 throw exn; 590 } 591 592 595 void introspectInheritance(AmberPersistenceUnit persistenceUnit, 596 RelatedType entityType, 597 JClass type, 598 JAnnotation inheritanceAnn, 599 InheritanceConfig inheritanceConfig) 600 throws ConfigException, SQLException 601 { 602 InheritanceType strategy; 603 604 if (inheritanceAnn != null) 605 strategy = (InheritanceType) inheritanceAnn.get("strategy"); 606 else 607 strategy = inheritanceConfig.getStrategy(); 608 609 JAnnotation discValueAnn = type.getAnnotation(DiscriminatorValue.class); 610 611 String discriminatorValue = null; 612 613 if (discValueAnn != null) 614 discriminatorValue = discValueAnn.getString("value"); 615 616 if (discriminatorValue == null || discriminatorValue.equals("")) { 617 String name = entityType.getBeanClass().getName(); 618 int p = name.lastIndexOf('.'); 619 if (p > 0) 620 name = name.substring(p + 1); 621 622 discriminatorValue = name; 623 } 624 625 entityType.setDiscriminatorValue(discriminatorValue); 626 627 if (entityType instanceof SubEntityType) { 628 SubEntityType subType = (SubEntityType) entityType; 629 630 subType.getParentType().addSubClass(subType); 631 632 getInternalPrimaryKeyJoinColumnConfig(type); 633 JAnnotation joinAnn = _annotationCfg.getAnnotation(); 634 PrimaryKeyJoinColumnConfig primaryKeyJoinColumnConfig = _annotationCfg.getPrimaryKeyJoinColumnConfig(); 635 636 if (strategy == InheritanceType.JOINED) { 638 linkInheritanceTable(subType.getRootType().getTable(), 639 subType.getTable(), 640 joinAnn, 641 primaryKeyJoinColumnConfig); 642 643 subType.setId(new SubId(subType, subType.getRootType())); 644 } 645 646 return; 647 } 648 649 switch (strategy) { 650 case JOINED: 651 entityType.setJoinedSubClass(true); 652 break; 653 } 654 655 getInternalDiscriminatorColumnConfig(type); 656 JAnnotation discriminatorAnn = _annotationCfg.getAnnotation(); 657 DiscriminatorColumnConfig discriminatorConfig = _annotationCfg.getDiscriminatorColumnConfig(); 658 659 String columnName = null; 660 661 if (discriminatorAnn != null) 662 columnName = discriminatorAnn.getString("name"); 663 664 if (columnName == null || columnName.equals("")) 665 columnName = "DTYPE"; 666 667 Type columnType = null; 668 DiscriminatorType discType = DiscriminatorType.STRING; 669 670 if (discriminatorAnn != null) 671 discType = (DiscriminatorType) discriminatorAnn.get("discriminatorType"); 672 673 switch (discType) { 674 case STRING: 675 columnType = StringType.create(); 676 break; 677 case CHAR: 678 columnType = PrimitiveCharType.create(); 679 break; 680 case INTEGER: 681 columnType = PrimitiveIntType.create(); 682 break; 683 default: 684 throw new IllegalStateException (); 685 } 686 687 Column column = entityType.getTable().createColumn(columnName, 688 columnType); 689 690 if (discriminatorAnn != null) { 691 column.setNotNull(! discriminatorAnn.getBoolean("nullable")); 692 693 column.setLength(discriminatorAnn.getInt("length")); 694 695 if (! "".equals(discriminatorAnn.get("columnDefinition"))) 696 column.setSQLType(discriminatorAnn.getString("columnDefinition")); 697 } 698 else { 699 column.setNotNull(true); 700 column.setLength(10); 701 } 702 703 entityType.setDiscriminator(column); 704 } 705 706 709 void introspectIdMethod(AmberPersistenceUnit persistenceUnit, 710 RelatedType entityType, 711 RelatedType parentType, 712 JClass type, 713 JClass idClass, 714 EntityConfig entityConfig) 715 throws ConfigException, SQLException 716 { 717 ArrayList <IdField> keys = new ArrayList <IdField>(); 718 719 IdField idField = null; 720 721 AttributesConfig attributesConfig = null; 722 723 if (entityConfig != null) 724 attributesConfig = entityConfig.getAttributes(); 725 726 for (JMethod method : type.getMethods()) { 727 String methodName = method.getName(); 728 JClass []paramTypes = method.getParameterTypes(); 729 730 if (method.getDeclaringClass().getName().equals("java.lang.Object")) 731 continue; 732 733 if (! methodName.startsWith("get") || paramTypes.length != 0) { 734 continue; 735 } 736 737 String fieldName = toFieldName(methodName.substring(3)); 738 739 if (containsFieldOrCompletion(parentType, fieldName)) 740 continue; 741 742 getInternalIdConfig(type, method, fieldName); 743 JAnnotation id = _annotationCfg.getAnnotation(); 744 IdConfig idConfig = _annotationCfg.getIdConfig(); 745 746 if (! _annotationCfg.isNull()) { 747 idField = introspectId(persistenceUnit, 748 entityType, 749 method, 750 fieldName, 751 method.getReturnType(), 752 idConfig); 753 754 if (idField != null) 755 keys.add(idField); 756 } 757 else { 758 getInternalEmbeddedIdConfig(type, method, fieldName); 759 JAnnotation embeddedId = _annotationCfg.getAnnotation(); 760 EmbeddedIdConfig embeddedIdConfig = _annotationCfg.getEmbeddedIdConfig(); 761 762 if (! _annotationCfg.isNull()) { 763 idField = introspectEmbeddedId(persistenceUnit, 764 entityType, 765 method, 766 fieldName, 767 method.getReturnType()); 768 break; 769 } 770 else { 771 continue; 772 } 773 } 774 } 775 776 if (keys.size() == 0) { 777 if (idField != null) { 778 CompositeId id = new CompositeId(entityType, (EmbeddedIdField) idField); 780 entityType.setId(id); 781 } 782 } 783 else if (keys.size() == 1) 784 entityType.setId(new com.caucho.amber.field.Id(entityType, keys)); 785 else if (idClass == null) { 786 throw new ConfigException(L.l("{0} has multiple @Id methods, but no @IdClass. Compound primary keys require either an @IdClass or exactly one @EmbeddedId field or property.", 787 entityType.getName())); 788 } 789 else { 790 CompositeId id = new CompositeId(entityType, keys); 791 id.setKeyClass(idClass); 792 793 entityType.setId(id); 794 } 795 } 796 797 800 void introspectIdField(AmberPersistenceUnit persistenceUnit, 801 RelatedType entityType, 802 RelatedType parentType, 803 JClass type, 804 JClass idClass, 805 EntityConfig entityConfig) 806 throws ConfigException, SQLException 807 { 808 ArrayList <IdField> keys = new ArrayList <IdField>(); 809 810 AttributesConfig attributesConfig = null; 811 812 if (entityConfig != null) 813 attributesConfig = entityConfig.getAttributes(); 814 815 for (JField field : type.getFields()) { 816 String fieldName = field.getName(); 817 818 if (containsFieldOrCompletion(parentType, fieldName)) 819 continue; 820 821 getInternalIdConfig(type, field, fieldName); 822 JAnnotation id = _annotationCfg.getAnnotation(); 823 IdConfig idConfig = _annotationCfg.getIdConfig(); 824 825 boolean hasId = ! _annotationCfg.isNull(); 826 827 getInternalEmbeddedIdConfig(type, field, fieldName); 828 JAnnotation embeddedId = _annotationCfg.getAnnotation(); 829 EmbeddedIdConfig embeddedIdConfig = _annotationCfg.getEmbeddedIdConfig(); 830 831 boolean hasEmbeddedId = ! _annotationCfg.isNull(); 832 833 if (! (hasId || hasEmbeddedId)) 834 continue; 835 836 IdField idField = introspectId(persistenceUnit, 837 entityType, 838 field, 839 fieldName, 840 field.getType(), 841 idConfig); 842 843 if (idField != null) 844 keys.add(idField); 845 } 846 847 if (keys.size() == 0) { 848 } 849 else if (keys.size() == 1) 850 entityType.setId(new com.caucho.amber.field.Id(entityType, keys)); 851 else if (idClass == null) { 852 throw new ConfigException(L.l("{0} has multiple @Id fields, but no @IdClass. Compound primary keys require an @IdClass.", 853 entityType.getName())); 854 } 855 else { 856 CompositeId id = new CompositeId(entityType, keys); 857 id.setKeyClass(idClass); 858 859 entityType.setId(id); 860 } 861 } 862 863 866 boolean isField(JClass type, 867 AbstractEnhancedConfig typeConfig, 868 boolean isEmbeddable) 869 throws ConfigException 870 { 871 if (type == null) 872 return false; 873 874 if (isEmbeddable) { 875 876 for (JMethod method : type.getDeclaredMethods()) { 877 878 JAnnotation ann[] = method.getDeclaredAnnotations(); 879 880 if ((ann != null) && (ann.length > 0)) 881 return false; 882 } 883 884 for (JField field : type.getDeclaredFields()) { 886 887 if ((! field.isTransient()) && field.isPrivate()) 888 return false; 889 } 890 891 return true; 892 } 893 894 if (typeConfig != null) { 895 896 String access = typeConfig.getAccess(); 897 898 if (access != null) 899 return access.equals("FIELD"); 900 901 JClass parentClass = type.getSuperClass(); 902 903 if (parentClass == null) 904 return false; 905 else { 906 getInternalEntityConfig(parentClass); 907 EntityConfig superEntityConfig = _annotationCfg.getEntityConfig(); 908 909 if (superEntityConfig == null) 910 return false; 911 912 return isField(parentClass, superEntityConfig, false); 913 } 914 } 915 916 for (JField field : type.getDeclaredFields()) { 917 918 JAnnotation id = field.getAnnotation(javax.persistence.Id.class); 919 920 if (id != null) 921 return true; 922 923 id = field.getAnnotation(EmbeddedId.class); 924 925 if (id != null) 926 return true; 927 } 928 929 return isField(type.getSuperClass(), null, false); 930 } 931 932 private IdField introspectId(AmberPersistenceUnit persistenceUnit, 933 RelatedType entityType, 934 JAccessibleObject field, 935 String fieldName, 936 JClass fieldType, 937 IdConfig idConfig) 938 throws ConfigException, SQLException 939 { 940 JAnnotation id = field.getAnnotation(javax.persistence.Id.class); 941 JAnnotation column = field.getAnnotation(javax.persistence.Column.class); 942 943 ColumnConfig columnConfig = null; 944 GeneratedValueConfig generatedValueConfig = null; 945 946 if (idConfig != null) { 947 columnConfig = idConfig.getColumn(); 948 generatedValueConfig = idConfig.getGeneratedValue(); 949 } 950 951 JAnnotation gen = field.getAnnotation(GeneratedValue.class); 952 953 Type amberType = persistenceUnit.createType(fieldType); 954 955 Column keyColumn = createColumn(entityType, 956 field, 957 fieldName, 958 column, 959 amberType, 960 columnConfig); 961 962 KeyPropertyField idField; 963 idField = new KeyPropertyField(entityType, fieldName, keyColumn); 964 965 if (gen == null) { 966 } 967 else { 968 JdbcMetaData metaData = null; 969 970 try { 971 metaData = persistenceUnit.getMetaData(); 972 } catch (Exception e) { 973 throw new ConfigException(L.l("Unable to get meta data for database. Meta data is needed for generated values.")); 974 } 975 976 if (GenerationType.IDENTITY.equals(gen.get("strategy"))) { 977 if (! metaData.supportsIdentity()) 978 throw new ConfigException(L.l("'{0}' does not support identity.", 979 metaData.getDatabaseName())); 980 981 keyColumn.setGeneratorType("identity"); 982 idField.setGenerator("identity"); 983 } 984 else if (GenerationType.SEQUENCE.equals(gen.get("strategy"))) { 985 if (! metaData.supportsSequences()) 986 throw new ConfigException(L.l("'{0}' does not support sequence.", 987 metaData.getDatabaseName())); 988 989 addSequenceIdGenerator(persistenceUnit, idField, gen); 990 } 991 else if (GenerationType.TABLE.equals(gen.get("strategy"))) { 992 addTableIdGenerator(persistenceUnit, idField, id); 993 } 994 else if (GenerationType.AUTO.equals(gen.get("strategy"))) { 995 if (metaData.supportsIdentity()) { 996 keyColumn.setGeneratorType("identity"); 997 idField.setGenerator("identity"); 998 } 999 else if (metaData.supportsSequences()) { 1000 addSequenceIdGenerator(persistenceUnit, idField, gen); 1001 } 1002 else { 1003 addTableIdGenerator(persistenceUnit, idField, id); 1004 } 1005 } 1006 } 1007 1008 return idField; 1009 } 1010 1011 private IdField introspectEmbeddedId(AmberPersistenceUnit persistenceUnit, 1012 RelatedType entityType, 1013 JAccessibleObject field, 1014 String fieldName, 1015 JClass fieldType) 1016 throws ConfigException, SQLException 1017 { 1018 IdField idField; 1019 1020 idField = new EmbeddedIdField(entityType, fieldName); 1021 1022 return idField; 1023 } 1024 1025 void addSequenceIdGenerator(AmberPersistenceUnit persistenceUnit, 1026 KeyPropertyField idField, 1027 JAnnotation genAnn) 1028 throws ConfigException 1029 { 1030 idField.setGenerator("sequence"); 1031 idField.getColumn().setGeneratorType("sequence"); 1032 1033 String name = genAnn.getString("generator"); 1034 1035 if (name == null || "".equals(name)) 1036 name = idField.getEntitySourceType().getTable().getName() + "_cseq"; 1037 1038 IdGenerator gen = persistenceUnit.createSequenceGenerator(name, 1); 1039 1040 idField.getEntitySourceType().setGenerator(idField.getName(), gen); 1041 } 1042 1043 void addTableIdGenerator(AmberPersistenceUnit persistenceUnit, 1044 KeyPropertyField idField, 1045 JAnnotation idAnn) 1046 throws ConfigException 1047 { 1048 idField.setGenerator("table"); 1049 idField.getColumn().setGeneratorType("table"); 1050 1051 String name = idAnn.getString("generator"); 1052 if (name == null || "".equals(name)) 1053 name = "caucho"; 1054 1055 IdGenerator gen = persistenceUnit.getTableGenerator(name); 1056 1057 if (gen == null) { 1058 String genName = "GEN_TABLE"; 1059 1060 GeneratorTableType genTable; 1061 genTable = persistenceUnit.createGeneratorTable(genName); 1062 1063 gen = genTable.createGenerator(name); 1064 1065 persistenceUnit.putTableGenerator(name, gen); 1066 } 1067 1068 idField.getEntitySourceType().setGenerator(idField.getName(), gen); 1069 } 1070 1071 1074 void linkSecondaryTable(Table primaryTable, 1075 Table secondaryTable, 1076 JAnnotation []joinColumnsAnn) 1077 throws ConfigException 1078 { 1079 ArrayList <ForeignColumn> linkColumns = new ArrayList <ForeignColumn>(); 1080 for (Column column : primaryTable.getIdColumns()) { 1081 ForeignColumn linkColumn; 1082 1083 JAnnotation joinAnn = getJoinColumn(joinColumnsAnn, column.getName()); 1084 String name; 1085 1086 if (joinAnn == null) 1087 name = column.getName(); 1088 else 1089 name = joinAnn.getString("name"); 1090 1091 linkColumn = secondaryTable.createForeignColumn(name, column); 1092 linkColumn.setPrimaryKey(true); 1093 1094 secondaryTable.addIdColumn(linkColumn); 1095 1096 linkColumns.add(linkColumn); 1097 } 1098 1099 LinkColumns link = new LinkColumns(secondaryTable, 1100 primaryTable, 1101 linkColumns); 1102 1103 link.setSourceCascadeDelete(true); 1104 1105 secondaryTable.setDependentIdLink(link); 1106 } 1107 1108 1111 void linkInheritanceTable(Table primaryTable, 1112 Table secondaryTable, 1113 JAnnotation joinAnn, 1114 PrimaryKeyJoinColumnConfig pkJoinColumnCfg) 1115 throws ConfigException 1116 { 1117 JAnnotation joinAnns[] = null; 1118 1119 if (joinAnn != null) 1120 joinAnns = new JAnnotation[] { joinAnn }; 1121 1122 linkInheritanceTable(primaryTable, 1123 secondaryTable, 1124 joinAnns, 1125 pkJoinColumnCfg); 1126 } 1127 1128 1131 void linkInheritanceTable(Table primaryTable, 1132 Table secondaryTable, 1133 JAnnotation []joinColumnsAnn, 1134 PrimaryKeyJoinColumnConfig pkJoinColumnCfg) 1135 throws ConfigException 1136 { 1137 ArrayList <ForeignColumn> linkColumns = new ArrayList <ForeignColumn>(); 1138 for (Column column : primaryTable.getIdColumns()) { 1139 ForeignColumn linkColumn; 1140 1141 String name; 1142 1143 if (joinColumnsAnn == null) { 1144 1145 if (pkJoinColumnCfg == null) 1146 name = column.getName(); 1147 else 1148 name = pkJoinColumnCfg.getName(); 1149 } 1150 else { 1151 JAnnotation join; 1152 1153 join = getJoinColumn(joinColumnsAnn, column.getName()); 1154 1155 if (join == null) 1156 name = column.getName(); 1157 else 1158 name = join.getString("name"); 1159 } 1160 1161 linkColumn = secondaryTable.createForeignColumn(name, column); 1162 linkColumn.setPrimaryKey(true); 1163 1164 secondaryTable.addIdColumn(linkColumn); 1165 1166 linkColumns.add(linkColumn); 1167 } 1168 1169 LinkColumns link = new LinkColumns(secondaryTable, 1170 primaryTable, 1171 linkColumns); 1172 1173 link.setSourceCascadeDelete(true); 1174 1175 secondaryTable.setDependentIdLink(link); 1176 1177 } 1186 1187 1190 void introspectMethods(AmberPersistenceUnit persistenceUnit, 1191 AbstractStatefulType entityType, 1192 AbstractStatefulType parentType, 1193 JClass type, 1194 AbstractEnhancedConfig typeConfig) 1195 throws ConfigException 1196 { 1197 for (JMethod method : type.getMethods()) { 1198 String methodName = method.getName(); 1199 JClass []paramTypes = method.getParameterTypes(); 1200 1201 if (method.getDeclaringClass().getName().equals("java.lang.Object")) 1202 continue; 1203 1204 1208 String propName; 1209 1210 if (paramTypes.length != 0) { 1211 validateNonGetter(method); 1212 continue; 1213 } 1214 else if (methodName.startsWith("get")) { 1215 propName = methodName.substring(3); 1216 } 1217 else if (methodName.startsWith("is") && 1218 (method.getReturnType().getName().equals("boolean") || 1219 method.getReturnType().getName().equals("java.lang.Boolean"))) { 1220 propName = methodName.substring(2); 1221 } 1222 else { 1223 validateNonGetter(method); 1224 continue; 1225 } 1226 1227 getInternalVersionConfig(type, method, propName); 1228 JAnnotation versionAnn = _annotationCfg.getAnnotation(); 1229 VersionConfig versionConfig = _annotationCfg.getVersionConfig(); 1230 1231 if (! _annotationCfg.isNull()) { 1232 validateNonGetter(method); 1233 } 1234 else { 1235 1236 JMethod setter = type.getMethod("set" + propName, 1237 new JClass[] { method.getReturnType() }); 1238 if (method.isPrivate() || 1239 (setter == null) || setter.isPrivate()) { 1240 1241 JAnnotation ann = isAnnotatedMethod(method); 1242 1243 if (ann == null) { 1244 if (setter != null) 1245 ann = isAnnotatedMethod(setter); 1246 } 1247 else if (ann.getType().equals("javax.persistence.Transient")) 1248 continue; 1249 1250 if (ann != null) { 1251 throw new ConfigException(L.l("'{0}' is not a valid annotation for {1}. Only public persistent property getters with matching setters may have property annotations.", 1252 ann.getType(), method.getFullName())); 1253 } 1254 1255 continue; 1256 } 1257 1258 if (method.isStatic()) { validateNonGetter(method); 1261 continue; 1262 } 1263 } 1264 1265 String fieldName = toFieldName(propName); 1266 1267 if (containsFieldOrCompletion(parentType, fieldName)) 1268 continue; 1269 1270 JClass fieldType = method.getReturnType(); 1271 1272 introspectField(persistenceUnit, entityType, method, 1273 fieldName, fieldType, typeConfig); 1274 } 1275 } 1276 1277 1280 void introspectFields(AmberPersistenceUnit persistenceUnit, 1281 AbstractStatefulType entityType, 1282 AbstractStatefulType parentType, 1283 JClass type, 1284 AbstractEnhancedConfig typeConfig, 1285 boolean isEmbeddable) 1286 throws ConfigException 1287 { 1288 if (! isEmbeddable) 1289 if (((RelatedType) entityType).getId() == null) 1290 throw new IllegalStateException (L.l("{0} has no key", entityType)); 1291 1292 for (JField field : type.getFields()) { 1293 String fieldName = field.getName(); 1294 1295 if (containsFieldOrCompletion(parentType, fieldName)) 1296 continue; 1297 1298 if (field.isStatic() || field.isTransient()) 1299 continue; 1300 1301 JClass fieldType = field.getType(); 1302 1303 introspectField(persistenceUnit, entityType, field, 1304 fieldName, fieldType, typeConfig); 1305 } 1306 } 1307 1308 void introspectField(AmberPersistenceUnit persistenceUnit, 1309 AbstractStatefulType sourceType, 1310 JAccessibleObject field, 1311 String fieldName, 1312 JClass fieldType, 1313 AbstractEnhancedConfig typeConfig) 1314 throws ConfigException 1315 { 1316 EmbeddableConfig embeddableConfig = null; 1317 EntityConfig entityConfig = null; 1318 MappedSuperclassConfig mappedSuperConfig = null; 1319 1320 if (typeConfig instanceof EmbeddableConfig) 1321 embeddableConfig = (EmbeddableConfig) typeConfig; 1322 else if (typeConfig instanceof EntityConfig) 1323 entityConfig = (EntityConfig) typeConfig; 1324 else if (typeConfig instanceof MappedSuperclassConfig) 1325 mappedSuperConfig = (MappedSuperclassConfig) typeConfig; 1326 1327 1329 JClass jClass = field.getDeclaringClass(); 1330 1331 if (jClass.isInterface()) 1332 return; 1333 1334 1337 AbstractStatefulType declaringType; 1338 1339 declaringType = _persistenceUnit.getEntity(jClass.getName()); 1340 1341 if (declaringType == null) 1342 declaringType = _persistenceUnit.getEmbeddable(jClass.getName()); 1343 1344 if (declaringType == null) 1345 return; 1346 1347 AttributesConfig attributesConfig = null; 1348 IdConfig idConfig = null; 1349 BasicConfig basicConfig = null; 1350 OneToOneConfig oneToOneConfig = null; 1351 OneToManyConfig oneToManyConfig = null; 1352 ManyToOneConfig manyToOneConfig = null; 1353 ManyToManyConfig manyToManyConfig = null; 1354 VersionConfig versionConfig = null; 1355 1356 if (entityConfig != null) { 1357 attributesConfig = entityConfig.getAttributes(); 1358 1359 if (attributesConfig != null) { 1360 idConfig = attributesConfig.getId(fieldName); 1361 1362 basicConfig = attributesConfig.getBasic(fieldName); 1363 1364 oneToOneConfig = attributesConfig.getOneToOne(fieldName); 1365 1366 oneToManyConfig = attributesConfig.getOneToMany(fieldName); 1367 1368 manyToOneConfig = attributesConfig.getManyToOne(fieldName); 1369 1370 manyToManyConfig = attributesConfig.getManyToMany(fieldName); 1371 1372 versionConfig = attributesConfig.getVersion(fieldName); 1373 } 1374 } 1375 1376 if ((idConfig != null) || 1377 field.isAnnotationPresent(javax.persistence.Id.class)) { 1378 validateAnnotations(field, _idAnnotations); 1379 1380 if (! _idTypes.contains(fieldType.getName())) { 1381 throw error(field, L.l("{0} is an invalid @Id type for {1}.", 1382 fieldType.getName(), field.getName())); 1383 } 1384 } 1385 else if ((basicConfig != null) || 1386 field.isAnnotationPresent(javax.persistence.Basic.class)) { 1387 validateAnnotations(field, _basicAnnotations); 1388 1389 addBasic(sourceType, field, fieldName, fieldType, basicConfig); 1390 } 1391 else if ((versionConfig != null) || 1392 field.isAnnotationPresent(javax.persistence.Version.class)) { 1393 validateAnnotations(field, _versionAnnotations); 1394 1395 addVersion((RelatedType) sourceType, field, 1396 fieldName, fieldType, versionConfig); 1397 } 1398 else if ((manyToOneConfig != null) || 1399 field.isAnnotationPresent(javax.persistence.ManyToOne.class)) { 1400 validateAnnotations(field, _manyToOneAnnotations); 1401 1402 JAnnotation ann = field.getAnnotation(ManyToOne.class); 1403 1404 JClass targetEntity = null; 1405 1406 if (ann != null) 1407 targetEntity = ann.getClass("targetEntity"); 1408 else { 1409 1410 String s = manyToOneConfig.getTargetEntity(); 1411 1412 if ((s != null) && (s.length() > 0)) 1413 targetEntity = _persistenceUnit.getJClassLoader().forName(s); 1414 } 1415 1416 if (targetEntity == null || 1417 targetEntity.getName().equals("void")) { 1418 targetEntity = fieldType; 1419 } 1420 1421 getInternalEntityConfig(targetEntity); 1422 JAnnotation targetEntityAnn = _annotationCfg.getAnnotation(); 1423 EntityConfig targetEntityConfig = _annotationCfg.getEntityConfig(); 1424 1425 if (_annotationCfg.isNull()) { 1426 throw error(field, L.l("'{0}' is an illegal targetEntity for {1}. @ManyToOne relations must target a valid @Entity.", 1427 targetEntity.getName(), field.getName())); 1428 } 1429 1430 if (! fieldType.isAssignableFrom(targetEntity)) { 1431 throw error(field, L.l("'{0}' is an illegal targetEntity for {1}. @ManyToOne targetEntity must be assignable to the field type '{2}'.", 1432 targetEntity.getName(), 1433 field.getName(), 1434 fieldType.getName())); 1435 } 1436 1437 RelatedType relatedType = (RelatedType) sourceType; 1438 1439 relatedType.setHasDependent(true); 1440 1441 _linkCompletions.add(new ManyToOneCompletion(relatedType, 1442 field, 1443 fieldName, 1444 fieldType)); 1445 } 1446 else if ((oneToManyConfig != null) || 1447 field.isAnnotationPresent(javax.persistence.OneToMany.class)) { 1448 validateAnnotations(field, _oneToManyAnnotations); 1449 1450 if (field.isAnnotationPresent(javax.persistence.MapKey.class)) { 1451 if (!fieldType.getName().equals("java.util.Map")) { 1452 throw error(field, L.l("'{0}' is an illegal @OneToMany/@MapKey type for {1}. @MapKey must be a java.util.Map", 1453 fieldType.getName(), 1454 field.getName())); 1455 } 1456 } 1457 else if (! _oneToManyTypes.contains(fieldType.getName())) { 1458 throw error(field, L.l("'{0}' is an illegal @OneToMany type for {1}. @OneToMany must be a java.util.Collection, java.util.List or java.util.Map", 1459 fieldType.getName(), 1460 field.getName())); 1461 } 1462 1463 RelatedType relatedType = (RelatedType) sourceType; 1464 1465 _depCompletions.add(new OneToManyCompletion(relatedType, 1466 field, 1467 fieldName, 1468 fieldType, 1469 oneToManyConfig)); 1470 } 1471 else if ((oneToOneConfig != null) || 1472 field.isAnnotationPresent(javax.persistence.OneToOne.class)) { 1473 validateAnnotations(field, _oneToOneAnnotations); 1474 1475 RelatedType relatedType = (RelatedType) sourceType; 1476 1477 relatedType.setHasDependent(true); 1478 1479 OneToOneCompletion oneToOne = new OneToOneCompletion(relatedType, 1480 field, 1481 fieldName, 1482 fieldType); 1483 1484 String mappedBy; 1487 1488 if (oneToOneConfig != null) 1489 mappedBy = oneToOneConfig.getMappedBy(); 1490 else { 1491 JAnnotation oneToOneAnn = field.getAnnotation(OneToOne.class); 1492 mappedBy = oneToOneAnn.getString("mappedBy"); 1493 } 1494 1495 boolean isOwner = (mappedBy == null || mappedBy.equals("")); 1496 1497 if (isOwner) 1498 _depCompletions.add(oneToOne); 1499 else 1500 _depCompletions.add(0, oneToOne); 1501 1502 ArrayList <OneToOneCompletion> oneToOneList 1503 = _oneToOneCompletions.get(relatedType); 1504 1505 if (oneToOneList == null) { 1506 oneToOneList = new ArrayList <OneToOneCompletion>(); 1507 _oneToOneCompletions.put(relatedType, oneToOneList); 1508 } 1509 1510 oneToOneList.add(oneToOne); 1511 } 1512 else if ((manyToManyConfig != null) || 1513 field.isAnnotationPresent(javax.persistence.ManyToMany.class)) { 1514 1515 if (field.isAnnotationPresent(javax.persistence.MapKey.class)) { 1516 if (! fieldType.getName().equals("java.util.Map")) { 1517 throw error(field, L.l("'{0}' is an illegal @ManyToMany/@MapKey type for {1}. @MapKey must be a java.util.Map", 1518 fieldType.getName(), 1519 field.getName())); 1520 } 1521 } 1522 1523 RelatedType relatedType = (RelatedType) sourceType; 1524 1525 Completion completion = new ManyToManyCompletion(relatedType, 1526 field, 1527 fieldName, 1528 fieldType); 1529 1530 JAnnotation ann = field.getAnnotation(ManyToMany.class); 1531 1532 String mappedBy; 1533 1534 if (ann != null) 1535 mappedBy = ann.getString("mappedBy"); 1536 else 1537 mappedBy = manyToManyConfig.getMappedBy(); 1538 1539 if ("".equals(mappedBy)) 1540 _linkCompletions.add(completion); 1541 else 1542 _depCompletions.add(completion); 1543 } 1544 else if (field.isAnnotationPresent(javax.persistence.Embedded.class)) { 1545 validateAnnotations(field, _embeddedAnnotations); 1546 1547 RelatedType relatedType = (RelatedType) sourceType; 1548 1549 relatedType.setHasDependent(true); 1550 1551 _depCompletions.add(new EmbeddedCompletion(relatedType, 1552 field, 1553 fieldName, 1554 fieldType, 1555 false)); 1556 } 1557 else if (field.isAnnotationPresent(javax.persistence.EmbeddedId.class)) { 1558 validateAnnotations(field, _embeddedIdAnnotations); 1559 1560 _depCompletions.add(new EmbeddedCompletion((RelatedType) sourceType, 1561 field, 1562 fieldName, 1563 fieldType, 1564 true)); 1565 } 1566 else if (field.isAnnotationPresent(javax.persistence.Transient.class)) { 1567 } 1568 else { 1569 addBasic(sourceType, field, fieldName, fieldType, basicConfig); 1570 } 1571 } 1572 1573 void addBasic(AbstractStatefulType sourceType, 1574 JAccessibleObject field, 1575 String fieldName, 1576 JClass fieldType, 1577 BasicConfig basicConfig) 1578 throws ConfigException 1579 { 1580 AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit(); 1581 1582 JAnnotation basicAnn = field.getAnnotation(Basic.class); 1583 JAnnotation columnAnn = field.getAnnotation(javax.persistence.Column.class); 1584 JAnnotation enumeratedAnn = field.getAnnotation(Enumerated.class); 1585 1586 ColumnConfig columnConfig = null; 1587 1588 if (basicConfig != null) 1589 columnConfig = basicConfig.getColumn(); 1590 1591 if (_basicTypes.contains(fieldType.getName())) { 1592 } 1593 else if (fieldType.isAssignableTo(java.io.Serializable .class)) { 1594 } 1595 else 1596 throw error(field, L.l("{0} is an invalid @Basic type for {1}.", 1597 fieldType.getName(), field.getName())); 1598 1599 Type amberType; 1600 1601 if (enumeratedAnn == null) 1602 amberType = persistenceUnit.createType(fieldType); 1603 else { 1604 com.caucho.amber.type.EnumType enumType; 1605 1606 enumType = persistenceUnit.createEnum(fieldType.getName(), 1607 fieldType); 1608 1609 enumType.setOrdinal(enumeratedAnn.get("value") == 1610 javax.persistence.EnumType.ORDINAL); 1611 1612 amberType = enumType; 1613 } 1614 1615 Column fieldColumn = null; 1616 1617 if (sourceType instanceof RelatedType) 1618 fieldColumn = createColumn((RelatedType) sourceType, field, fieldName, 1619 columnAnn, amberType, columnConfig); 1620 1621 PropertyField property = new PropertyField(sourceType, fieldName); 1622 property.setColumn(fieldColumn); 1623 1624 property.setType(amberType); 1626 1627 if (basicAnn != null) 1628 property.setLazy(basicAnn.get("fetch") == FetchType.LAZY); 1629 else if (basicConfig != null) 1630 property.setLazy(basicConfig.getFetch() == FetchType.LAZY); 1631 else 1632 property.setLazy(false); 1633 1634 1638 1639 sourceType.addField(property); 1640 } 1641 1642 void addVersion(RelatedType sourceType, 1643 JAccessibleObject field, 1644 String fieldName, 1645 JClass fieldType, 1646 VersionConfig versionConfig) 1647 throws ConfigException 1648 { 1649 AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit(); 1650 1651 JAnnotation columnAnn = field.getAnnotation(javax.persistence.Column.class); 1652 1653 ColumnConfig columnConfig = null; 1654 1655 if (versionConfig != null) 1656 columnConfig = versionConfig.getColumn(); 1657 1658 if (! _versionTypes.contains(fieldType.getName())) { 1659 throw error(field, L.l("{0} is an invalid @Version type for {1}.", 1660 fieldType.getName(), field.getName())); 1661 } 1662 1663 Type amberType = persistenceUnit.createType(fieldType); 1664 1665 Column fieldColumn = createColumn(sourceType, field, fieldName, 1666 columnAnn, amberType, columnConfig); 1667 1668 VersionField version = new VersionField(sourceType, fieldName); 1669 version.setColumn(fieldColumn); 1670 1671 sourceType.setVersionField(version); 1672 } 1673 1674 private Column createColumn(RelatedType entityType, 1675 JAccessibleObject field, 1676 String fieldName, 1677 JAnnotation columnAnn, 1678 Type amberType, 1679 ColumnConfig columnConfig) 1680 throws ConfigException 1681 { 1682 String name; 1683 1684 if (columnAnn != null && ! columnAnn.get("name").equals("")) 1685 name = (String ) columnAnn.get("name"); 1686 else if (columnConfig != null && ! columnConfig.getName().equals("")) 1687 name = columnConfig.getName(); 1688 else 1689 name = toSqlName(fieldName); 1690 1691 Column column = null; 1692 1693 if (columnAnn != null && ! columnAnn.get("table").equals("")) { 1694 String tableName = columnAnn.getString("table"); 1695 Table table; 1696 1697 table = entityType.getSecondaryTable(tableName); 1698 1699 if (table == null) 1700 throw error(field, L.l("{0} @Column(table='{1}') is an unknown secondary table.", 1701 fieldName, 1702 tableName)); 1703 1704 column = table.createColumn(name, amberType); 1705 } 1706 else 1707 column = entityType.getTable().createColumn(name, amberType); 1708 1709 if ((column != null) && (columnAnn != null)) { 1710 column.setUnique(columnAnn.getBoolean("unique")); 1712 column.setNotNull(! columnAnn.getBoolean("nullable")); 1713 if (! "".equals(columnAnn.getString("columnDefinition"))) 1716 column.setSQLType(columnAnn.getString("columnDefinition")); 1717 column.setLength(columnAnn.getInt("length")); 1718 int precision = columnAnn.getInt("precision"); 1719 if (precision < 0) { 1720 throw error(field, L.l("{0} @Column precision cannot be less than 0.", 1721 fieldName)); 1722 } 1723 1724 int scale = columnAnn.getInt("scale"); 1725 if (scale < 0) { 1726 throw error(field, L.l("{0} @Column scale cannot be less than 0.", 1727 fieldName)); 1728 } 1729 1730 if (scale > precision) { 1734 throw error(field, L.l("{0} @Column scale cannot be greater than precision. Must set precision to a non-zero value before setting scale.", 1735 fieldName)); 1736 } 1737 1738 if (precision > 0) { 1739 column.setPrecision(precision); 1740 column.setScale(scale); 1741 } 1742 } 1743 1744 return column; 1745 } 1746 1747 void addManyToOne(RelatedType sourceType, 1748 JAccessibleObject field, 1749 String fieldName, 1750 JClass fieldType) 1751 throws ConfigException 1752 { 1753 AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit(); 1754 1755 getInternalManyToOneConfig(sourceType.getBeanClass(), field, fieldName); 1756 JAnnotation manyToOneAnn = _annotationCfg.getAnnotation(); 1757 Object manyToOneConfig = _annotationCfg.getManyToOneConfig(); 1758 HashMap <String , JoinColumnConfig> joinColumnMap = null; 1759 CascadeType cascadeTypes[] = null; 1760 1761 JClass parentClass = sourceType.getBeanClass(); 1762 1763 do { 1764 getInternalEntityConfig(parentClass); 1765 JAnnotation parentEntity = _annotationCfg.getAnnotation(); 1766 EntityConfig superEntityConfig = _annotationCfg.getEntityConfig(); 1767 1768 if (superEntityConfig != null) { 1769 AttributesConfig attributesConfig = superEntityConfig.getAttributes(); 1770 1771 if (attributesConfig != null) { 1772 if (manyToOneConfig == null) 1773 manyToOneConfig = attributesConfig.getManyToOne(fieldName); 1774 } 1775 } 1776 1777 parentClass = parentClass.getSuperClass(); 1778 } 1779 while ((parentClass != null) && (manyToOneConfig == null)); 1780 1781 FetchType fetchType = FetchType.EAGER; 1782 JClass targetClass = null; 1783 1784 if ((manyToOneAnn == null) && (manyToOneConfig == null)) { 1785 1787 getInternalOneToOneConfig(sourceType.getBeanClass(), field, fieldName); 1788 manyToOneAnn = _annotationCfg.getAnnotation(); 1789 manyToOneConfig = _annotationCfg.getOneToOneConfig(); 1790 1791 if (manyToOneConfig != null) { 1792 fetchType = ((OneToOneConfig) manyToOneConfig).getFetch(); 1793 joinColumnMap = ((OneToOneConfig) manyToOneConfig).getJoinColumnMap(); 1794 1795 String s = ((OneToOneConfig) manyToOneConfig).getTargetEntity(); 1796 if (s != null) 1797 targetClass = _persistenceUnit.getJClassLoader().forName(s); 1798 } 1799 } 1800 else { 1801 if (manyToOneConfig != null) { 1802 fetchType = ((ManyToOneConfig) manyToOneConfig).getFetch(); 1803 joinColumnMap = ((ManyToOneConfig) manyToOneConfig).getJoinColumnMap(); 1804 CascadeConfig cascade = ((ManyToOneConfig) manyToOneConfig).getCascade(); 1805 1806 if (cascade != null) { 1807 cascadeTypes = cascade.getCascadeTypes(); 1808 } 1809 1810 String s = ((ManyToOneConfig) manyToOneConfig).getTargetEntity(); 1811 if (s != null) 1812 targetClass = _persistenceUnit.getJClassLoader().forName(s); 1813 } 1814 } 1815 1816 if (manyToOneAnn != null) { 1817 fetchType = (FetchType) manyToOneAnn.get("fetch"); 1818 1819 targetClass = manyToOneAnn.getClass("targetEntity"); 1820 1821 Object cascade[] = (Object []) manyToOneAnn.get("cascade"); 1824 1825 cascadeTypes = new CascadeType[cascade.length]; 1826 1827 for (int i=0; i < cascade.length; i++) 1828 cascadeTypes[i] = (CascadeType) cascade[i]; 1829 } 1830 1831 if (fetchType == FetchType.EAGER) { 1832 if (sourceType.getBeanClass().getName().equals(fieldType.getName())) { 1833 throw error(field, L.l("'{0}': '{1}' is an illegal recursive type for @OneToOne/@ManyToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.", 1834 field.getName(), 1835 fieldType.getName())); 1836 } 1837 } 1838 1839 JAnnotation joinColumns = field.getAnnotation(JoinColumns.class); 1840 1841 Object []joinColumnsAnn = null; 1842 1843 if (joinColumns != null) 1844 joinColumnsAnn = (Object []) joinColumns.get("value"); 1845 1846 JAnnotation joinColumnAnn = field.getAnnotation(JoinColumn.class); 1847 1848 if (joinColumnsAnn != null && joinColumnAnn != null) { 1849 throw error(field, L.l("{0} may not have both @JoinColumn and @JoinColumns", 1850 field.getName())); 1851 } 1852 1853 if (joinColumnAnn != null) 1854 joinColumnsAnn = new Object [] { joinColumnAnn }; 1855 1856 String targetName = ""; 1857 if (targetClass != null) 1858 targetName = targetClass.getName(); 1859 1860 if (targetName.equals("") || targetName.equals("void")) 1861 targetName = fieldType.getName(); 1862 1863 EntityManyToOneField manyToOneField; 1864 manyToOneField = new EntityManyToOneField(sourceType, fieldName, cascadeTypes); 1865 1866 EntityType targetType = persistenceUnit.createEntity(targetName, fieldType); 1867 1868 manyToOneField.setType(targetType); 1869 1870 manyToOneField.setLazy(fetchType == FetchType.LAZY); 1871 1872 sourceType.addField(manyToOneField); 1873 1874 Table sourceTable = sourceType.getTable(); 1875 1876 validateJoinColumns(field, joinColumnsAnn, joinColumnMap, targetType); 1877 1878 int n = 0; 1879 1880 if (joinColumnMap != null) 1881 n = joinColumnMap.size(); 1882 1883 ArrayList <ForeignColumn> foreignColumns = new ArrayList <ForeignColumn>(); 1884 1885 RelatedType parentType = targetType; 1886 1887 ArrayList <Column> targetIdColumns = targetType.getId().getColumns(); 1888 1889 while (targetIdColumns.size() == 0) { 1890 1891 parentType = parentType.getParentType(); 1892 1893 if (parentType == null) 1894 break; 1895 1896 targetIdColumns = parentType.getId().getColumns(); 1897 } 1898 1899 for (Column keyColumn : targetIdColumns) { 1900 1901 String columnName = fieldName.toUpperCase() + '_' + keyColumn.getName(); 1902 boolean nullable = true; 1903 boolean unique = false; 1904 1905 if (n > 0) { 1906 1907 JoinColumnConfig joinColumn; 1908 1909 if (n == 1) { 1910 joinColumn = (JoinColumnConfig) joinColumnMap.values().toArray()[0]; 1911 } else 1912 joinColumn = joinColumnMap.get(keyColumn.getName()); 1913 1914 if (joinColumn != null) { 1915 columnName = joinColumn.getName(); 1916 1917 nullable = joinColumn.getNullable(); 1918 unique = joinColumn.getUnique(); 1919 } 1920 } 1921 else { 1922 JAnnotation joinAnn = getJoinColumn(joinColumnsAnn, keyColumn.getName()); 1923 1924 if (joinAnn != null) { 1925 columnName = joinAnn.getString("name"); 1926 1927 nullable = joinAnn.getBoolean("nullable"); 1928 unique = joinAnn.getBoolean("unique"); 1929 } 1930 } 1931 1932 ForeignColumn foreignColumn; 1933 1934 foreignColumn = sourceTable.createForeignColumn(columnName, keyColumn); 1935 1936 foreignColumn.setNotNull(! nullable); 1937 foreignColumn.setUnique(unique); 1938 1939 foreignColumns.add(foreignColumn); 1940 } 1941 1942 LinkColumns linkColumns = new LinkColumns(sourceType.getTable(), 1943 targetType.getTable(), 1944 foreignColumns); 1945 1946 manyToOneField.setLinkColumns(linkColumns); 1947 1948 manyToOneField.init(); 1949 } 1950 1951 private JAnnotation getJoinColumn(JAnnotation joinColumns, 1952 String keyName) 1953 { 1954 if (joinColumns == null) 1955 return null; 1956 1957 return getJoinColumn((Object []) joinColumns.get("value"), keyName); 1958 } 1959 1960 void validateJoinColumns(JAccessibleObject field, 1961 Object []columnsAnn, 1962 HashMap <String , JoinColumnConfig> joinColumnMap, 1963 RelatedType targetType) 1964 throws ConfigException 1965 { 1966 if ((joinColumnMap == null) && (columnsAnn == null)) 1967 return; 1968 1969 com.caucho.amber.field.Id id = targetType.getId(); 1970 1971 int size; 1972 Object joinColumnCfg[] = null; 1973 1974 if (columnsAnn != null) 1975 size = columnsAnn.length; 1976 else { 1977 size = joinColumnMap.size(); 1978 joinColumnCfg = joinColumnMap.values().toArray(); 1979 } 1980 1981 if (id.getColumns().size() != size) { 1982 throw error(field, L.l("Number of @JoinColumns for '{1}' ({0}) does not match the number of primary key columns for '{3}' ({2}).", 1983 "" + size, 1984 field.getName(), 1985 id.getColumns().size(), 1986 targetType.getName())); 1987 } 1988 1989 for (int i = 0; i < size; i++) { 1990 String ref; 1991 1992 if (joinColumnCfg != null) { 1993 ref = ((JoinColumnConfig) joinColumnCfg[i]).getReferencedColumnName(); 1994 } 1995 else { 1996 JAnnotation ann = (JAnnotation) columnsAnn[i]; 1997 1998 ref = ann.getString("referencedColumnName"); 1999 } 2000 2001 if (((ref == null) || ref.equals("")) && size > 1) 2002 throw error(field, L.l("referencedColumnName is required when more than one @JoinColumn is specified.")); 2003 2004 Column column = findColumn(id.getColumns(), ref); 2005 2006 if (column == null) 2007 throw error(field, L.l("referencedColumnName '{0}' does not match any key column in '{1}'.", 2008 ref, targetType.getName())); 2009 } 2010 } 2011 2012 private Column findColumn(ArrayList <Column> columns, String ref) 2013 { 2014 if (((ref == null) || ref.equals("")) && columns.size() == 1) 2015 return columns.get(0); 2016 2017 for (Column column : columns) { 2018 if (column.getName().equals(ref)) 2019 return column; 2020 } 2021 2022 return null; 2023 } 2024 2025 JAnnotation getJoinColumn(Object []columnsAnn, String keyName) 2026 { 2027 if (columnsAnn == null || columnsAnn.length == 0) 2028 return null; 2029 2030 for (int i = 0; i < columnsAnn.length; i++) { 2031 JAnnotation ann = (JAnnotation) columnsAnn[i]; 2032 2033 String ref = ann.getString("referencedColumnName"); 2034 2035 if (ref.equals("") || ref.equals(keyName)) 2036 return ann; 2037 } 2038 2039 return null; 2040 } 2041 2042 void addManyToMany(RelatedType sourceType, 2043 JAccessibleObject field, 2044 String fieldName, 2045 JClass fieldType) 2046 throws ConfigException 2047 { 2048 getInternalManyToManyConfig(sourceType.getBeanClass(), field, fieldName); 2049 JAnnotation manyToManyAnn = _annotationCfg.getAnnotation(); 2050 ManyToManyConfig manyToManyConfig = _annotationCfg.getManyToManyConfig(); 2051 2052 JType retType; 2053 2054 if (field instanceof JField) 2055 retType = ((JField) field).getGenericType(); 2056 else 2057 retType = ((JMethod) field).getGenericReturnType(); 2058 2059 JType []typeArgs = retType.getActualTypeArguments(); 2060 2061 String targetName = ""; 2062 2063 if (manyToManyAnn != null) { 2064 JClass targetEntity = manyToManyAnn.getClass("targetEntity"); 2065 2066 if (targetEntity != null) 2067 targetName = targetEntity.getName(); 2068 } 2069 else 2070 targetName = manyToManyConfig.getTargetEntity(); 2071 2072 if (! targetName.equals("") && ! targetName.equals("void")) { 2073 } 2074 else if (typeArgs.length > 0) 2075 targetName = typeArgs[0].getName(); 2076 else 2077 throw error(field, L.l("Can't determine targetEntity for {0}. @OneToMany properties must target @Entity beans.", 2078 field.getName())); 2079 2080 EntityType targetType = _persistenceUnit.getEntity(targetName); 2081 2082 if (targetType == null) 2083 throw error(field, 2084 L.l("targetEntity '{0}' is not an @Entity bean for {1}. The targetEntity of a @ManyToMany collection must be an @Entity bean.", 2085 targetName, 2086 field.getName())); 2087 2088 CascadeType[] cascadeTypes = null; 2090 2091 String mappedBy; 2092 2093 if (manyToManyAnn != null) { 2094 mappedBy = manyToManyAnn.getString("mappedBy"); 2095 2096 Object cascade[] = (Object []) manyToManyAnn.get("cascade"); 2099 2100 cascadeTypes = new CascadeType[cascade.length]; 2101 2102 for (int i=0; i < cascade.length; i++) 2103 cascadeTypes[i] = (CascadeType) cascade[i]; 2104 } 2105 else { 2106 mappedBy = manyToManyConfig.getMappedBy(); 2107 2108 CascadeConfig cascade = ((ManyToManyConfig) manyToManyConfig).getCascade(); 2109 2110 if (cascade != null) { 2111 cascadeTypes = cascade.getCascadeTypes(); 2112 } 2113 } 2114 2115 if (! ((mappedBy == null) || "".equals(mappedBy))) { 2116 EntityManyToManyField sourceField 2117 = (EntityManyToManyField) targetType.getField(mappedBy); 2118 2119 EntityManyToManyField manyToManyField; 2120 2121 if (sourceField == null) 2122 throw error(field, 2123 L.l("Unable to find the associated field in '{0}' for a @ManyToMany relationship from '{1}'", 2124 targetName, 2125 field.getName())); 2126 2127 manyToManyField = new EntityManyToManyField(sourceType, 2128 fieldName, 2129 sourceField, 2130 cascadeTypes); 2131 manyToManyField.setType(targetType); 2132 sourceType.addField(manyToManyField); 2133 2134 2137 if (! sourceField.hasJoinColumns()) { 2138 LinkColumns sourceLink = sourceField.getSourceLink(); 2139 ArrayList <ForeignColumn> columns = sourceLink.getColumns(); 2140 for (ForeignColumn column : columns) { 2141 String columnName = column.getName(); 2142 columnName = columnName.substring(columnName.indexOf('_')); 2143 columnName = manyToManyField.getName().toUpperCase() + columnName; 2144 column.setName(columnName); 2145 } 2146 } 2147 2148 if (! sourceField.hasInverseJoinColumns()) { 2149 LinkColumns targetLink = sourceField.getTargetLink(); 2150 ArrayList <ForeignColumn> columns = targetLink.getColumns(); 2151 for (ForeignColumn column : columns) { 2152 String columnName = column.getName(); 2153 columnName = columnName.substring(columnName.indexOf('_')); 2154 columnName = sourceField.getName().toUpperCase() + columnName; 2155 column.setName(columnName); 2156 } 2157 } 2158 2159 return; 2160 } 2161 2162 EntityManyToManyField manyToManyField; 2163 2164 manyToManyField = new EntityManyToManyField(sourceType, fieldName, cascadeTypes); 2165 manyToManyField.setType(targetType); 2166 2167 String sqlTable = sourceType.getTable().getName() + "_" + 2168 targetType.getTable().getName(); 2169 2170 JAnnotation joinTableAnn = field.getAnnotation(javax.persistence.JoinTable.class); 2171 2172 JoinTableConfig joinTableConfig = null; 2173 2174 if (manyToManyConfig != null) 2175 joinTableConfig = manyToManyConfig.getJoinTable(); 2176 2177 Table mapTable = null; 2178 2179 ArrayList <ForeignColumn> sourceColumns = null; 2180 ArrayList <ForeignColumn> targetColumns = null; 2181 2182 if ((joinTableAnn != null) || (joinTableConfig != null)) { 2183 2184 Object joinColumns[] = null; 2185 Object inverseJoinColumns[] = null; 2186 2187 HashMap <String , JoinColumnConfig> joinColumnsConfig = null; 2188 HashMap <String , JoinColumnConfig> inverseJoinColumnsConfig = null; 2189 2190 String joinTableName; 2191 2192 if (joinTableAnn != null) { 2193 joinTableName = joinTableAnn.getString("name"); 2194 joinColumns = (Object []) joinTableAnn.get("joinColumns"); 2195 inverseJoinColumns = (Object []) joinTableAnn.get("inverseJoinColumns"); 2196 2197 if ((joinColumns != null) && 2198 (joinColumns.length > 0)) 2199 manyToManyField.setJoinColumns(true); 2200 2201 if ((inverseJoinColumns != null) && 2202 (inverseJoinColumns.length > 0)) 2203 manyToManyField.setInverseJoinColumns(true); 2204 } 2205 else { 2206 joinTableName = joinTableConfig.getName(); 2207 joinColumnsConfig = joinTableConfig.getJoinColumnMap(); 2208 inverseJoinColumnsConfig = joinTableConfig.getInverseJoinColumnMap(); 2209 2210 if ((joinColumnsConfig != null) && 2211 (joinColumnsConfig.size() > 0)) 2212 manyToManyField.setJoinColumns(true); 2213 2214 if ((inverseJoinColumnsConfig != null) && 2215 (inverseJoinColumnsConfig.size() > 0)) 2216 manyToManyField.setInverseJoinColumns(true); 2217 } 2218 2219 if (! joinTableName.equals("")) 2220 sqlTable = joinTableName; 2221 2222 mapTable = _persistenceUnit.createTable(sqlTable); 2223 2224 sourceColumns = AbstractConfigIntrospector.calculateColumns(field, 2225 mapTable, 2226 sourceType.getTable().getName() + "_", 2227 sourceType, 2228 joinColumns, 2229 joinColumnsConfig); 2230 2231 targetColumns = AbstractConfigIntrospector.calculateColumns(field, 2232 mapTable, 2233 targetType.getTable().getName() + "_", 2234 targetType, 2235 inverseJoinColumns, 2236 inverseJoinColumnsConfig); 2237 } 2238 else { 2239 mapTable = _persistenceUnit.createTable(sqlTable); 2240 2241 sourceColumns = AbstractConfigIntrospector.calculateColumns(mapTable, 2242 sourceType.getTable().getName() + "_", 2243 sourceType); 2244 2245 targetColumns = AbstractConfigIntrospector.calculateColumns(mapTable, 2246 targetType.getTable().getName() + "_", 2247 targetType); 2248 } 2249 2250 manyToManyField.setAssociationTable(mapTable); 2251 manyToManyField.setTable(sqlTable); 2252 2253 manyToManyField.setSourceLink(new LinkColumns(mapTable, 2254 sourceType.getTable(), 2255 sourceColumns)); 2256 2257 manyToManyField.setTargetLink(new LinkColumns(mapTable, 2258 targetType.getTable(), 2259 targetColumns)); 2260 2261 getInternalMapKeyConfig(sourceType.getBeanClass(), field, fieldName); 2262 JAnnotation mapKeyAnn = _annotationCfg.getAnnotation(); 2263 MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig(); 2264 2265 if (! _annotationCfg.isNull()) { 2266 2267 String key; 2268 2269 if (mapKeyAnn != null) 2270 key = mapKeyAnn.getString("name"); 2271 else 2272 key = mapKeyConfig.getName(); 2273 2274 String getter = "get" + 2275 Character.toUpperCase(key.charAt(0)) + key.substring(1); 2276 2277 JMethod method = targetType.getGetter(getter); 2278 2279 if (method == null) { 2280 throw error(field, 2281 L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.", 2282 targetName, key)); 2283 } 2284 2285 manyToManyField.setMapKey(key); 2286 } 2287 2288 sourceType.addField(manyToManyField); 2289 } 2290 2291 EntityManyToOneField getSourceField(RelatedType targetType, 2292 String mappedBy, 2293 RelatedType sourceType) 2294 { 2295 ArrayList <AmberField> fields = targetType.getFields(); 2296 2297 for (AmberField field : fields) { 2298 if ("".equals(mappedBy) || mappedBy == null) { 2300 if (field.getJavaType().isAssignableFrom(sourceType.getBeanClass())) 2301 return (EntityManyToOneField) field; 2302 } 2303 else if (field.getName().equals(mappedBy)) 2304 return (EntityManyToOneField) field; 2305 } 2306 2307 return null; 2308 } 2309 2310 OneToOneCompletion getSourceCompletion(RelatedType targetType, 2311 String mappedBy) 2312 { 2313 ArrayList <OneToOneCompletion> sourceCompletions 2314 = _oneToOneCompletions.get(targetType); 2315 2316 if (sourceCompletions == null) 2317 return null; 2318 2319 if (sourceCompletions.size() == 1) 2321 return sourceCompletions.get(0); 2322 2323 for (OneToOneCompletion oneToOne : sourceCompletions) { 2324 2325 if (oneToOne.getFieldName().equals(mappedBy)) { 2326 return oneToOne; 2327 } 2328 } 2329 2330 return null; 2331 } 2332 2333 2336 class Completion { 2337 protected RelatedType _relatedType; 2338 2339 protected Completion(RelatedType relatedType, 2340 String fieldName) 2341 { 2342 _relatedType = relatedType; 2343 _relatedType.addCompletionField(fieldName); 2344 } 2345 2346 protected Completion(RelatedType relatedType) 2347 { 2348 _relatedType = relatedType; 2349 } 2350 2351 RelatedType getRelatedType() 2352 { 2353 return _relatedType; 2354 } 2355 2356 void complete() 2357 throws ConfigException 2358 { 2359 } 2360 } 2361 2362 2365 class OneToManyCompletion extends Completion { 2366 private JAccessibleObject _field; 2367 private String _fieldName; 2368 private JClass _fieldType; 2369 private OneToManyConfig _oneToManyConfig; 2370 2371 OneToManyCompletion(RelatedType type, 2372 JAccessibleObject field, 2373 String fieldName, 2374 JClass fieldType, 2375 OneToManyConfig oneToManyConfig) 2376 { 2377 super(type, fieldName); 2378 2379 _field = field; 2380 _fieldName = fieldName; 2381 _fieldType = fieldType; 2382 _oneToManyConfig = oneToManyConfig; 2383 } 2384 2385 void complete() 2386 throws ConfigException 2387 { 2388 getInternalOneToManyConfig(_relatedType.getBeanClass(), _field, _fieldName); 2389 JAnnotation oneToManyAnn = _annotationCfg.getAnnotation(); 2390 OneToManyConfig oneToManyConfig = _annotationCfg.getOneToManyConfig(); 2391 2392 AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit(); 2393 2394 JType retType; 2395 2396 if (_field instanceof JField) 2397 retType = ((JField) _field).getGenericType(); 2398 else 2399 retType = ((JMethod) _field).getGenericReturnType(); 2400 2401 JType []typeArgs = retType.getActualTypeArguments(); 2402 2403 JClass targetEntity = null; 2404 2405 if (oneToManyAnn != null) 2406 targetEntity = oneToManyAnn.getClass("targetEntity"); 2407 else { 2408 String s = oneToManyConfig.getTargetEntity(); 2409 2410 if (s != null) 2411 targetEntity = _persistenceUnit.getJClassLoader().forName(s); 2412 } 2413 2414 String targetName = ""; 2415 2416 if (targetEntity != null) 2417 targetName = targetEntity.getName(); 2418 2419 if (! targetName.equals("") && ! targetName.equals("void")) { 2420 } 2421 else if (typeArgs.length > 0) 2422 targetName = typeArgs[typeArgs.length-1].getName(); 2423 else 2424 throw error(_field, L.l("Can't determine targetEntity for {0}. @OneToMany properties must target @Entity beans.", 2425 _field.getName())); 2426 2427 EntityType targetType = persistenceUnit.getEntity(targetName); 2428 if (targetType == null) { 2429 2430 EntityConfig entityConfig = null; 2431 2432 if (_entityConfigMap != null) { 2433 entityConfig = _entityConfigMap.get(targetName); 2434 } 2435 2436 if (entityConfig == null) 2437 throw error(_field, 2438 L.l("targetEntity '{0}' is not an @Entity bean for {1}. The targetEntity of a @OneToMany collection must be an @Entity bean.", 2439 targetName, 2440 _field.getName())); 2441 } 2442 2443 CascadeType[] cascadeTypes = null; 2444 2445 String mappedBy; 2446 2447 if (oneToManyAnn != null) { 2448 mappedBy = oneToManyAnn.getString("mappedBy"); 2449 2450 Object cascade[] = (Object []) oneToManyAnn.get("cascade"); 2453 2454 cascadeTypes = new CascadeType[cascade.length]; 2455 2456 for (int i=0; i < cascade.length; i++) 2457 cascadeTypes[i] = (CascadeType) cascade[i]; 2458 } 2459 else { 2460 mappedBy = oneToManyConfig.getMappedBy(); 2461 2462 CascadeConfig cascade = ((OneToManyConfig) oneToManyConfig).getCascade(); 2463 2464 if (cascade != null) { 2465 cascadeTypes = cascade.getCascadeTypes(); 2466 } 2467 } 2468 2469 if (mappedBy != null && ! mappedBy.equals("")) { 2470 oneToManyBidirectional(targetType, targetName, mappedBy, cascadeTypes); 2471 } 2472 else { 2473 oneToManyUnidirectional(targetType, targetName, cascadeTypes); 2474 } 2475 } 2476 2477 private void oneToManyBidirectional(RelatedType targetType, 2478 String targetName, 2479 String mappedBy, 2480 CascadeType[] cascadeTypes) 2481 throws ConfigException 2482 { 2483 JAnnotation joinTableAnn = _field.getAnnotation(javax.persistence.JoinTable.class); 2484 2485 JoinTableConfig joinTableConfig = null; 2486 2487 if (_oneToManyConfig != null) 2488 joinTableConfig = _oneToManyConfig.getJoinTable(); 2489 2490 if ((joinTableAnn != null) || (joinTableConfig != null)) { 2491 throw error(_field, 2492 L.l("Bidirectional @ManyToOne property {0} may not have a @JoinTable annotation.", 2493 _field.getName())); 2494 } 2495 2496 EntityManyToOneField sourceField = getSourceField(targetType, 2497 mappedBy, 2498 null); 2499 2500 if (sourceField == null) 2501 throw error(_field, L.l("'{0}' does not have matching field for @ManyToOne(mappedBy={1}).", 2502 targetType.getName(), 2503 mappedBy)); 2504 2505 JAnnotation orderByAnn = _field.getAnnotation(javax.persistence.OrderBy.class); 2506 2507 String orderBy = null; 2508 ArrayList <String > orderByFields = null; 2509 ArrayList <Boolean > orderByAscending = null; 2510 2511 if (orderByAnn != null) { 2512 orderBy = (String ) orderByAnn.get("value"); 2513 2514 if (orderBy == null) 2515 orderBy = ""; 2516 2517 if ("".equals(orderBy)) { 2518 if (targetType instanceof RelatedType) { 2519 RelatedType targetRelatedType = (RelatedType) targetType; 2520 orderBy = targetRelatedType.getId().generateJavaSelect(null); 2521 } 2522 } 2523 2524 orderByFields = new ArrayList <String >(); 2525 orderByAscending = new ArrayList <Boolean >(); 2526 2527 int len = orderBy.length(); 2528 2529 int i = 0; 2530 2531 while (i < len) { 2532 2533 int index = orderBy.indexOf(",", i); 2534 2535 if (index < 0) 2536 index = len; 2537 2538 String orderByField = orderBy.substring(i, index); 2539 2540 i += index; 2541 2542 index = orderByField.toUpperCase().lastIndexOf("SC"); 2544 2545 Boolean asc = Boolean.TRUE; 2546 2547 if (index > 1) { 2548 if (orderByField.charAt(index - 1) != 'E') { 2549 if (orderByField.charAt(index - 1) == 'A' && 2551 Character.isSpaceChar(orderByField.charAt(index - 2))) { 2552 index -= 2; 2553 } 2554 } 2555 else if (index > 2 && 2556 orderByField.charAt(index - 2) == 'D' && 2557 Character.isSpaceChar(orderByField.charAt(index - 3))) { 2558 2559 asc = Boolean.FALSE; 2560 index -= 3; 2561 } 2562 } 2563 2564 if (index > 0) 2565 orderByField = orderByField.substring(0, index).trim(); 2566 2567 AmberField amberField = targetType.getField(orderByField); 2568 2569 if (amberField == null) 2570 throw error(_field, L.l("'{0}' has no field named '{1}' in @OrderBy", 2571 targetType.getName(), 2572 orderByField)); 2573 2574 2580 2581 orderByFields.add(orderByField); 2582 orderByAscending.add(asc); 2583 } 2584 } 2585 2586 EntityOneToManyField oneToMany; 2587 2588 oneToMany = new EntityOneToManyField(_relatedType, _fieldName, cascadeTypes); 2589 oneToMany.setSourceField(sourceField); 2590 oneToMany.setOrderBy(orderByFields, orderByAscending); 2591 2592 getInternalMapKeyConfig(_relatedType.getBeanClass(), _field, _fieldName); 2593 JAnnotation mapKeyAnn = _annotationCfg.getAnnotation(); 2594 MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig(); 2595 2596 if (! _annotationCfg.isNull()) { 2597 2598 String key = mapKeyAnn.getString("name"); 2599 2600 String getter = "get" + 2601 Character.toUpperCase(key.charAt(0)) + key.substring(1); 2602 2603 JMethod method = targetType.getGetter(getter); 2604 2605 if (method == null) { 2606 throw error(_field, 2607 L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @OneToMany targetEntity is incorrect.", 2608 targetName, key)); 2609 } 2610 2611 oneToMany.setMapKey(key); 2612 } 2613 2614 _relatedType.addField(oneToMany); 2615 } 2616 2617 private void oneToManyUnidirectional(RelatedType targetType, 2618 String targetName, 2619 CascadeType[] cascadeTypes) 2620 throws ConfigException 2621 { 2622 EntityManyToManyField manyToManyField; 2623 2624 manyToManyField = new EntityManyToManyField(_relatedType, _fieldName, cascadeTypes); 2625 manyToManyField.setType(targetType); 2626 2627 String sqlTable = _relatedType.getTable().getName() + "_" + targetType.getTable().getName(); 2628 2629 JAnnotation joinTableAnn = _field.getAnnotation(javax.persistence.JoinTable.class); 2630 2631 JoinTableConfig joinTableConfig = null; 2632 2633 if (_oneToManyConfig != null) 2634 joinTableConfig = _oneToManyConfig.getJoinTable(); 2635 2636 Table mapTable = null; 2637 2638 ArrayList <ForeignColumn> sourceColumns = null; 2639 ArrayList <ForeignColumn> targetColumns = null; 2640 2641 if ((joinTableAnn != null) || (joinTableConfig != null)) { 2642 2643 Object joinColumns[] = null; 2644 Object inverseJoinColumns[] = null; 2645 2646 HashMap <String , JoinColumnConfig> joinColumnsConfig = null; 2647 HashMap <String , JoinColumnConfig> inverseJoinColumnsConfig = null; 2648 2649 if (joinTableAnn != null) { 2650 if (! joinTableAnn.getString("name").equals("")) 2651 sqlTable = joinTableAnn.getString("name"); 2652 joinColumns = (Object []) joinTableAnn.get("joinColumns"); 2653 inverseJoinColumns = (Object []) joinTableAnn.get("inverseJoinColumns"); 2654 } 2655 else { 2656 if (! joinTableConfig.getName().equals("")) 2657 sqlTable = joinTableConfig.getName(); 2658 joinColumnsConfig = joinTableConfig.getJoinColumnMap(); 2659 inverseJoinColumnsConfig = joinTableConfig.getInverseJoinColumnMap(); 2660 } 2661 2662 mapTable = _persistenceUnit.createTable(sqlTable); 2663 2664 sourceColumns = AbstractConfigIntrospector.calculateColumns(_field, 2665 mapTable, 2666 _relatedType.getTable().getName() + "_", 2667 _relatedType, 2668 joinColumns, 2669 joinColumnsConfig); 2670 2671 targetColumns = AbstractConfigIntrospector.calculateColumns(_field, 2672 mapTable, 2673 targetType.getTable().getName() + "_", 2674 targetType, 2675 inverseJoinColumns, 2676 inverseJoinColumnsConfig); 2677 } 2678 else { 2679 mapTable = _persistenceUnit.createTable(sqlTable); 2680 2681 sourceColumns = AbstractConfigIntrospector.calculateColumns(mapTable, 2682 _relatedType.getTable().getName() + "_", 2683 _relatedType); 2684 2685 targetColumns = AbstractConfigIntrospector.calculateColumns(mapTable, 2686 _fieldName.toUpperCase() + "_", 2688 targetType); 2689 } 2690 2691 manyToManyField.setAssociationTable(mapTable); 2692 manyToManyField.setTable(sqlTable); 2693 2694 manyToManyField.setSourceLink(new LinkColumns(mapTable, 2695 _relatedType.getTable(), 2696 sourceColumns)); 2697 2698 manyToManyField.setTargetLink(new LinkColumns(mapTable, 2699 targetType.getTable(), 2700 targetColumns)); 2701 2702 getInternalMapKeyConfig(_relatedType.getBeanClass(), _field, _field.getName()); 2703 JAnnotation mapKeyAnn = _annotationCfg.getAnnotation(); 2704 MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig(); 2705 2706 if (! _annotationCfg.isNull()) { 2707 2708 String key; 2709 2710 if (mapKeyAnn != null) 2711 key = mapKeyAnn.getString("name"); 2712 else 2713 key = mapKeyConfig.getName(); 2714 2715 String getter = "get" + 2716 Character.toUpperCase(key.charAt(0)) + key.substring(1); 2717 2718 JMethod method = targetType.getGetter(getter); 2719 2720 if (method == null) { 2721 throw error(_field, 2722 L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.", 2723 targetName, key)); 2724 } 2725 2726 manyToManyField.setMapKey(key); 2727 } 2728 2729 _relatedType.addField(manyToManyField); 2730 } 2731 } 2732 2733 2736 class OneToOneCompletion extends Completion { 2737 private JAccessibleObject _field; 2738 private String _fieldName; 2739 private JClass _fieldType; 2740 2741 OneToOneCompletion(RelatedType type, 2742 JAccessibleObject field, 2743 String fieldName, 2744 JClass fieldType) 2745 { 2746 super(type, fieldName); 2747 2748 _field = field; 2749 _fieldName = fieldName; 2750 _fieldType = fieldType; 2751 } 2752 2753 String getFieldName() 2754 { 2755 return _fieldName; 2756 } 2757 2758 void complete() 2759 throws ConfigException 2760 { 2761 getInternalOneToOneConfig(_relatedType.getBeanClass(), _field, _fieldName); 2762 JAnnotation oneToOneAnn = _annotationCfg.getAnnotation(); 2763 OneToOneConfig oneToOneConfig = _annotationCfg.getOneToOneConfig(); 2764 2765 boolean isLazy; 2766 2767 if (oneToOneAnn != null) 2768 isLazy = oneToOneAnn.get("fetch") == FetchType.LAZY; 2769 else 2770 isLazy = oneToOneConfig.getFetch() == FetchType.LAZY; 2771 2772 if (! isLazy) { 2773 if (_relatedType.getBeanClass().getName().equals(_fieldType.getName())) { 2774 throw error(_field, L.l("'{0}': '{1}' is an illegal recursive type for @OneToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.", 2775 _field.getName(), 2776 _fieldType.getName())); 2777 } 2778 } 2779 2780 AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit(); 2781 2782 JClass targetEntity = null; 2783 String targetName = ""; 2784 2785 if (oneToOneAnn != null) { 2786 targetEntity = oneToOneAnn.getClass("targetEntity"); 2787 2788 if (targetEntity != null) 2789 targetEntity.getName(); 2790 } 2791 else { 2792 targetName = oneToOneConfig.getTargetEntity(); 2793 2794 if (! ((targetName == null) || "".equals(targetName))) 2795 targetEntity = _persistenceUnit.getJClassLoader().forName(targetName); 2796 } 2797 2798 if (targetEntity == null || targetEntity.getName().equals("void")) 2799 targetEntity = _fieldType; 2800 2801 getInternalEntityConfig(targetEntity); 2802 JAnnotation targetEntityAnn = _annotationCfg.getAnnotation(); 2803 EntityConfig targetEntityConfig = _annotationCfg.getEntityConfig(); 2804 2805 if (_annotationCfg.isNull()) { 2806 throw error(_field, L.l("'{0}' is an illegal targetEntity for {1}. @OneToOne relations must target a valid @Entity.", 2807 targetEntity.getName(), _field.getName())); 2808 } 2809 2810 if (! _fieldType.isAssignableFrom(targetEntity)) { 2811 throw error(_field, L.l("'{0}' is an illegal targetEntity for {1}. @OneToOne targetEntity must be assignable to the field type '{2}'.", 2812 targetEntity.getName(), 2813 _field.getName(), 2814 _fieldType.getName())); 2815 } 2816 2817 String mappedBy; 2818 2819 if (oneToOneAnn != null) 2820 mappedBy = oneToOneAnn.getString("mappedBy"); 2821 else 2822 mappedBy = oneToOneConfig.getMappedBy(); 2823 2824 RelatedType targetType = null; 2825 2826 if (targetName != null && ! targetName.equals("")) { 2827 targetType = persistenceUnit.getEntity(targetName); 2828 2829 if (targetType == null) 2830 throw new ConfigException(L.l("{0}: '{1}' is an unknown entity for '{2}'.", 2831 _field.getDeclaringClass().getName(), 2832 targetName, 2833 _field.getName())); 2834 } 2835 else { 2836 targetType = persistenceUnit.getEntity(_field.getReturnType().getName()); 2837 2838 if (targetType == null) 2839 throw new ConfigException(L.l("{0} can't determine target name for '{1}'", 2840 _field.getDeclaringClass().getName(), 2841 _field.getName())); 2842 } 2843 2844 2846 boolean isManyToOne = (mappedBy == null) || "".equals(mappedBy); 2848 2849 if (isManyToOne) { 2851 2852 getInternalJoinColumnConfig(_relatedType.getBeanClass(), _field, _fieldName); 2853 JAnnotation joinColumnAnn = _annotationCfg.getAnnotation(); 2854 JoinColumnConfig joinColumnConfig = _annotationCfg.getJoinColumnConfig(); 2855 2856 if (! _annotationCfg.isNull()) { 2857 } 2860 else { 2861 OneToOneCompletion otherSide 2863 = getSourceCompletion(targetType, mappedBy); 2864 2865 if (otherSide != null) { 2866 getInternalJoinColumnConfig(targetType.getBeanClass(), 2867 otherSide._field, 2868 otherSide._fieldName); 2869 if (! _annotationCfg.isNull()) 2871 isManyToOne = false; 2872 } 2873 } 2874 } 2875 2876 if (isManyToOne) { 2877 2878 addManyToOne(_relatedType, _field, _fieldName, _field.getReturnType()); 2879 2880 } 2882 else { 2883 2884 if (! (mappedBy == null || "".equals(mappedBy))) { 2885 2886 2888 OneToOneCompletion otherSide 2889 = getSourceCompletion(targetType, mappedBy); 2890 2891 if (otherSide != null) { 2892 if (_depCompletions.remove(otherSide)) { 2894 otherSide.complete(); 2895 } 2896 } 2897 } 2898 2899 EntityManyToOneField sourceField 2901 = getSourceField(targetType, mappedBy, _relatedType); 2902 2903 if (sourceField == null) 2904 throw new ConfigException(L.l("{0}: OneToOne target '{1}' does not have a matching ManyToOne relation.", 2905 _field.getDeclaringClass().getName(), 2906 targetType.getName())); 2907 2908 DependentEntityOneToOneField oneToOne; 2909 2910 oneToOne = new DependentEntityOneToOneField(_relatedType, _fieldName); 2911 oneToOne.setTargetField(sourceField); 2912 sourceField.setTargetField(oneToOne); 2913 oneToOne.setLazy(isLazy); 2914 2915 _relatedType.addField(oneToOne); 2916 } 2917 } 2918 } 2919 2920 2923 class ManyToManyCompletion extends Completion { 2924 private JAccessibleObject _field; 2925 private String _fieldName; 2926 private JClass _fieldType; 2927 2928 ManyToManyCompletion(RelatedType type, 2929 JAccessibleObject field, 2930 String fieldName, 2931 JClass fieldType) 2932 { 2933 super(type, fieldName); 2934 2935 _field = field; 2936 _fieldName = fieldName; 2937 _fieldType = fieldType; 2938 } 2939 2940 void complete() 2941 throws ConfigException 2942 { 2943 addManyToMany(_relatedType, _field, _fieldName, _fieldType); 2944 } 2945 } 2946 2947 2950 class ManyToOneCompletion extends Completion { 2951 private JAccessibleObject _field; 2952 private String _fieldName; 2953 private JClass _fieldType; 2954 2955 ManyToOneCompletion(RelatedType type, 2956 JAccessibleObject field, 2957 String fieldName, 2958 JClass fieldType) 2959 { 2960 super(type, fieldName); 2961 2962 _field = field; 2963 _fieldName = fieldName; 2964 _fieldType = fieldType; 2965 } 2966 2967 void complete() 2968 throws ConfigException 2969 { 2970 addManyToOne(_relatedType, _field, _fieldName, _fieldType); 2971 } 2972 } 2973 2974 2977 class EmbeddedCompletion extends Completion { 2978 private JAccessibleObject _field; 2979 private String _fieldName; 2980 private JClass _fieldType; 2981 private boolean _embeddedId; 2984 2985 EmbeddedCompletion(RelatedType type, 2986 JAccessibleObject field, 2987 String fieldName, 2988 JClass fieldType, 2989 boolean embeddedId) 2990 { 2991 super(type, fieldName); 2992 2993 _field = field; 2994 _fieldName = fieldName; 2995 _fieldType = fieldType; 2996 _embeddedId = embeddedId; 2997 } 2998 2999 void complete() 3000 throws ConfigException 3001 { 3002 getInternalAttributeOverrideConfig(_relatedType.getBeanClass(), _field, _fieldName); 3003 JAnnotation attributeOverrideAnn = _annotationCfg.getAnnotation(); 3004 AttributeOverrideConfig attributeOverrideConfig = _annotationCfg.getAttributeOverrideConfig(); 3005 3006 boolean hasAttributeOverride = ! _annotationCfg.isNull(); 3007 3008 JAnnotation attributeOverridesAnn = _field.getAnnotation(AttributeOverrides.class); 3009 3010 boolean hasAttributeOverrides = (attributeOverridesAnn != null); 3011 3012 if (hasAttributeOverride && hasAttributeOverrides) { 3013 throw error(_field, L.l("{0} may not have both @AttributeOverride and @AttributeOverrides", 3014 _field.getName())); 3015 } 3016 3017 Object attOverridesAnn[] = null; 3018 3019 if (attributeOverrideAnn != null) { 3020 attOverridesAnn = new Object [] { attributeOverrideAnn }; 3021 } 3022 else if (attributeOverridesAnn != null) { 3023 attOverridesAnn = (Object []) attributeOverridesAnn.get("value"); 3024 } 3025 3026 EntityEmbeddedField embeddedField; 3027 3028 if (_embeddedId) { 3029 embeddedField = _relatedType.getId().getEmbeddedIdField(); 3030 } else { 3031 embeddedField = new EntityEmbeddedField(_relatedType, _fieldName); 3032 } 3033 3034 embeddedField.setEmbeddedId(_embeddedId); 3035 3036 embeddedField.setLazy(false); 3037 3038 AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit(); 3039 3040 EmbeddableType type = persistenceUnit.createEmbeddable(_fieldType.getName(), _fieldType); 3041 3042 embeddedField.setType(type); 3043 3044 _relatedType.addField(embeddedField); 3045 3046 3049 Table sourceTable = _relatedType.getTable(); 3050 3051 HashMap <String , Column> embeddedColumns = new HashMap <String , Column>(); 3052 HashMap <String , String > fieldNameByColumn = new HashMap <String , String >(); 3053 3054 ArrayList <AmberField> fields = type.getFields(); 3055 3056 for (int i=0; i < fields.size(); i++) { 3057 3058 String embeddedFieldName = fields.get(i).getName(); 3059 3060 String columnName = toSqlName(embeddedFieldName); 3061 boolean notNull = false; 3062 boolean unique = false; 3063 3064 if (attOverridesAnn != null) { 3065 for (int j=0; j<attOverridesAnn.length; j++) { 3066 3067 if (embeddedFieldName.equals(((JAnnotation) attOverridesAnn[j]).getString("name"))) { 3068 3069 JAnnotation columnAnn = ((JAnnotation) attOverridesAnn[j]).getAnnotation("column"); 3070 3071 if (columnAnn != null) { 3072 columnName = columnAnn.getString("name"); 3073 notNull = ! columnAnn.getBoolean("nullable"); 3074 unique = columnAnn.getBoolean("unique"); 3075 } 3076 } 3077 } 3078 } 3079 3080 Type amberType = _persistenceUnit.createType(fields.get(i).getJavaType().getName()); 3081 3082 Column column = sourceTable.createColumn(columnName, amberType); 3083 3084 column.setNotNull(notNull); 3085 column.setUnique(unique); 3086 3087 embeddedColumns.put(columnName, column); 3088 fieldNameByColumn.put(columnName, embeddedFieldName); 3089 } 3090 3091 embeddedField.setEmbeddedColumns(embeddedColumns); 3092 embeddedField.setFieldNameByColumn(fieldNameByColumn); 3093 3094 embeddedField.init(); 3095 } 3096 } 3097 3098 3101 class SqlResultSetMappingCompletion extends Completion { 3102 private String _name; 3103 private Object _entities[]; 3104 private Object _columns[]; 3105 3106 SqlResultSetMappingCompletion(RelatedType type, 3107 String name, 3108 Object entities[], 3109 Object columns[]) 3110 { 3111 super(type); 3112 3113 _name = name; 3114 _entities = entities; 3115 _columns = columns; 3116 } 3117 3118 void complete() 3119 throws ConfigException 3120 { 3121 addSqlResultSetMapping(_name, 3122 _entities, 3123 _columns); 3124 } 3125 } 3126 3127 void getInternalEmbeddableConfig(JClass type) 3128 { 3129 _annotationCfg.reset(type, Embeddable.class); 3130 3131 EmbeddableConfig embeddableConfig = null; 3132 3133 if (_embeddableConfigMap != null) 3134 embeddableConfig = _embeddableConfigMap.get(type.getName()); 3135 3136 _annotationCfg.setConfig(embeddableConfig); 3137 } 3138 3139 void getInternalEntityConfig(JClass type) 3140 { 3141 _annotationCfg.reset(type, Entity.class); 3142 3143 EntityConfig entityConfig = null; 3144 3145 if (_entityConfigMap != null) 3146 entityConfig = _entityConfigMap.get(type.getName()); 3147 3148 _annotationCfg.setConfig(entityConfig); 3149 } 3150 3151 void getInternalMappedSuperclassConfig(JClass type) 3152 { 3153 _annotationCfg.reset(type, MappedSuperclass.class); 3154 3155 if (_mappedSuperclassConfigMap == null) 3156 return; 3157 3158 MappedSuperclassConfig mappedSuperConfig = null; 3159 3160 mappedSuperConfig = _mappedSuperclassConfigMap.get(type.getName()); 3161 3162 _annotationCfg.setConfig(mappedSuperConfig); 3163 } 3164 3165 void getInternalEntityListenersConfig(JClass type) 3166 { 3167 _annotationCfg.reset(type, EntityListeners.class); 3168 3169 if (_entityConfigMap == null) 3170 return; 3171 3172 EntityConfig entityConfig; 3173 3174 entityConfig = _entityConfigMap.get(type.getName()); 3175 3176 if (entityConfig == null) 3177 return; 3178 3179 _annotationCfg.setConfig(entityConfig.getEntityListeners()); 3180 } 3181 3182 void getInternalExcludeDefaultListenersConfig(JClass type) 3183 { 3184 _annotationCfg.reset(type, ExcludeDefaultListeners.class); 3185 3186 if (_entityConfigMap == null) 3187 return; 3188 3189 EntityConfig entityConfig; 3190 3191 entityConfig = _entityConfigMap.get(type.getName()); 3192 3193 if (entityConfig == null) 3194 return; 3195 3196 if (entityConfig.getExcludeDefaultListeners()) 3197 _annotationCfg.setConfig(entityConfig.getExcludeDefaultListeners()); 3198 } 3199 3200 void getInternalExcludeSuperclassListenersConfig(JClass type) 3201 { 3202 _annotationCfg.reset(type, ExcludeSuperclassListeners.class); 3203 3204 if (_entityConfigMap == null) 3205 return; 3206 3207 EntityConfig entityConfig; 3208 3209 entityConfig = _entityConfigMap.get(type.getName()); 3210 3211 if (entityConfig == null) 3212 return; 3213 3214 if (entityConfig.getExcludeSuperclassListeners()) 3215 _annotationCfg.setConfig(entityConfig.getExcludeSuperclassListeners()); 3216 } 3217 3218 void getInternalInheritanceConfig(JClass type) 3219 { 3220 _annotationCfg.reset(type, Inheritance.class); 3221 3222 EntityConfig entityConfig = null; 3223 3224 if (_entityConfigMap != null) 3225 entityConfig = _entityConfigMap.get(type.getName()); 3226 3227 if (entityConfig != null) { 3228 _annotationCfg.setConfig(entityConfig.getInheritance()); 3229 } 3230 } 3231 3232 void getInternalNamedQueryConfig(JClass type) 3233 { 3234 _annotationCfg.reset(type, NamedQuery.class); 3235 3236 EntityConfig entityConfig = null; 3237 3238 if (_entityConfigMap != null) 3239 entityConfig = _entityConfigMap.get(type.getName()); 3240 3241 if (entityConfig != null) { 3242 _annotationCfg.setConfig(entityConfig.getNamedQuery()); 3243 } 3244 } 3245 3246 void getInternalNamedNativeQueryConfig(JClass type) 3247 { 3248 _annotationCfg.reset(type, NamedNativeQuery.class); 3249 3250 EntityConfig entityConfig = null; 3251 3252 if (_entityConfigMap != null) 3253 entityConfig = _entityConfigMap.get(type.getName()); 3254 3255 if (entityConfig != null) { 3256 _annotationCfg.setConfig(entityConfig.getNamedNativeQuery()); 3257 } 3258 } 3259 3260 void getInternalSqlResultSetMappingConfig(JClass type) 3261 { 3262 _annotationCfg.reset(type, SqlResultSetMapping.class); 3263 3264 EntityConfig entityConfig = null; 3265 3266 if (_entityConfigMap != null) 3267 entityConfig = _entityConfigMap.get(type.getName()); 3268 3269 if (entityConfig != null) { 3270 _annotationCfg.setConfig(entityConfig.getSqlResultSetMapping()); 3271 } 3272 } 3273 3274 void getInternalTableConfig(JClass type) 3275 { 3276 _annotationCfg.reset(type, javax.persistence.Table.class); 3277 3278 EntityConfig entityConfig = null; 3279 3280 if (_entityConfigMap != null) 3281 entityConfig = _entityConfigMap.get(type.getName()); 3282 3283 if (entityConfig != null) { 3284 _annotationCfg.setConfig(entityConfig.getTable()); 3285 } 3286 } 3287 3288 void getInternalSecondaryTableConfig(JClass type) 3289 { 3290 _annotationCfg.reset(type, SecondaryTable.class); 3291 3292 EntityConfig entityConfig = null; 3293 3294 if (_entityConfigMap != null) 3295 entityConfig = _entityConfigMap.get(type.getName()); 3296 3297 if (entityConfig != null) { 3298 _annotationCfg.setConfig(entityConfig.getSecondaryTable()); 3299 } 3300 } 3301 3302 void getInternalIdClassConfig(JClass type) 3303 { 3304 _annotationCfg.reset(type, IdClass.class); 3305 3306 EntityConfig entityConfig = null; 3307 3308 if (_entityConfigMap != null) 3309 entityConfig = _entityConfigMap.get(type.getName()); 3310 3311 if (entityConfig != null) { 3312 _annotationCfg.setConfig(entityConfig.getIdClass()); 3313 } 3314 } 3315 3316 void getInternalPrimaryKeyJoinColumnConfig(JClass type) 3317 { 3318 _annotationCfg.reset(type, PrimaryKeyJoinColumn.class); 3319 3320 EntityConfig entityConfig = null; 3321 3322 if (_entityConfigMap != null) 3323 entityConfig = _entityConfigMap.get(type.getName()); 3324 3325 if (entityConfig != null) { 3326 _annotationCfg.setConfig(entityConfig.getPrimaryKeyJoinColumn()); 3327 } 3328 } 3329 3330 void getInternalDiscriminatorColumnConfig(JClass type) 3331 { 3332 _annotationCfg.reset(type, DiscriminatorColumn.class); 3333 3334 EntityConfig entityConfig = null; 3335 3336 if (_entityConfigMap != null) 3337 entityConfig = _entityConfigMap.get(type.getName()); 3338 3339 if (entityConfig != null) { 3340 _annotationCfg.setConfig(entityConfig.getDiscriminatorColumn()); 3341 } 3342 } 3343 3344 void getInternalOneToOneConfig(JClass type, 3345 JAccessibleObject field, 3346 String fieldName) 3347 { 3348 _annotationCfg.reset(field, OneToOne.class); 3349 3350 EntityConfig entityConfig = null; 3351 3352 if (_entityConfigMap != null) 3353 entityConfig = _entityConfigMap.get(type.getName()); 3354 3355 if (entityConfig != null) { 3356 3357 AttributesConfig attributes = entityConfig.getAttributes(); 3358 3359 if (attributes != null) { 3360 OneToOneConfig oneToOne = attributes.getOneToOne(fieldName); 3361 3362 _annotationCfg.setConfig(oneToOne); 3363 } 3364 } 3365 } 3366 3367 void getInternalOneToManyConfig(JClass type, 3368 JAccessibleObject field, 3369 String fieldName) 3370 { 3371 _annotationCfg.reset(field, OneToMany.class); 3372 3373 EntityConfig entityConfig = null; 3374 3375 if (_entityConfigMap != null) 3376 entityConfig = _entityConfigMap.get(type.getName()); 3377 3378 if (entityConfig != null) { 3379 3380 AttributesConfig attributes = entityConfig.getAttributes(); 3381 3382 if (attributes != null) { 3383 OneToManyConfig oneToMany = attributes.getOneToMany(fieldName); 3384 3385 _annotationCfg.setConfig(oneToMany); 3386 } 3387 } 3388 } 3389 3390 void getInternalManyToOneConfig(JClass type, 3391 JAccessibleObject field, 3392 String fieldName) 3393 { 3394 _annotationCfg.reset(field, ManyToOne.class); 3395 3396 EntityConfig entityConfig = null; 3397 3398 if (_entityConfigMap != null) 3399 entityConfig = _entityConfigMap.get(type.getName()); 3400 3401 if (entityConfig != null) { 3402 3403 AttributesConfig attributes = entityConfig.getAttributes(); 3404 3405 if (attributes != null) { 3406 ManyToOneConfig manyToOne = attributes.getManyToOne(fieldName); 3407 3408 _annotationCfg.setConfig(manyToOne); 3409 } 3410 } 3411 } 3412 3413 void getInternalManyToManyConfig(JClass type, 3414 JAccessibleObject field, 3415 String fieldName) 3416 { 3417 _annotationCfg.reset(field, ManyToMany.class); 3418 3419 EntityConfig entityConfig = null; 3420 3421 if (_entityConfigMap != null) 3422 entityConfig = _entityConfigMap.get(type.getName()); 3423 3424 if (entityConfig != null) { 3425 3426 AttributesConfig attributes = entityConfig.getAttributes(); 3427 3428 if (attributes != null) { 3429 ManyToManyConfig manyToMany = attributes.getManyToMany(fieldName); 3430 3431 _annotationCfg.setConfig(manyToMany); 3432 } 3433 } 3434 } 3435 3436 void getInternalIdConfig(JClass type, 3437 JAccessibleObject method, 3438 String fieldName) 3439 { 3440 _annotationCfg.reset(method, javax.persistence.Id.class); 3441 3442 EntityConfig entityConfig = null; 3443 3444 if (_entityConfigMap != null) 3445 entityConfig = _entityConfigMap.get(type.getName()); 3446 3447 if (entityConfig != null) { 3448 3449 AttributesConfig attributes = entityConfig.getAttributes(); 3450 3451 if (attributes != null) { 3452 IdConfig id = attributes.getId(fieldName); 3453 3454 _annotationCfg.setConfig(id); 3455 } 3456 } 3457 } 3458 3459 void getInternalCallbackConfig(int callback, 3460 JClass type, 3461 JAccessibleObject method, 3462 String fieldName) 3463 { 3464 _annotationCfg.reset(method, ListenerType.CALLBACK_CLASS[callback]); 3465 3466 if (_entityConfigMap == null) 3467 return; 3468 3469 EntityConfig entityConfig; 3470 3471 entityConfig = _entityConfigMap.get(type.getName()); 3472 3473 if (entityConfig == null) 3474 return; 3475 3476 AbstractListenerConfig callbackConfig; 3477 3478 switch (callback) { 3479 case Listener.PRE_PERSIST: 3480 callbackConfig = entityConfig.getPrePersist(); 3481 break; 3482 case Listener.POST_PERSIST: 3483 callbackConfig = entityConfig.getPostPersist(); 3484 break; 3485 case Listener.PRE_REMOVE: 3486 callbackConfig = entityConfig.getPreRemove(); 3487 break; 3488 case Listener.POST_REMOVE: 3489 callbackConfig = entityConfig.getPostRemove(); 3490 break; 3491 case Listener.PRE_UPDATE: 3492 callbackConfig = entityConfig.getPreUpdate(); 3493 break; 3494 case Listener.POST_UPDATE: 3495 callbackConfig = entityConfig.getPostUpdate(); 3496 break; 3497 case Listener.POST_LOAD: 3498 callbackConfig = entityConfig.getPostLoad(); 3499 break; 3500 default: 3501 return; 3502 } 3503 3504 if (callbackConfig == null) 3505 return; 3506 3507 if (callbackConfig.getMethodName().equals(method.getName())) 3508 _annotationCfg.setConfig(callbackConfig); 3509 } 3510 3511 void getInternalEmbeddedIdConfig(JClass type, 3512 JAccessibleObject method, 3513 String fieldName) 3514 { 3515 _annotationCfg.reset(method, EmbeddedId.class); 3516 } 3517 3518 void getInternalVersionConfig(JClass type, 3519 JAccessibleObject method, 3520 String fieldName) 3521 { 3522 _annotationCfg.reset(method, Version.class); 3523 } 3524 3525 void getInternalJoinColumnConfig(JClass type, 3526 JAccessibleObject field, 3527 String fieldName) 3528 { 3529 _annotationCfg.reset(field, JoinColumn.class); 3530 } 3531 3532 void getInternalJoinTableConfig(JClass type, 3533 JAccessibleObject field, 3534 String fieldName) 3535 { 3536 _annotationCfg.reset(field, JoinTable.class); 3537 } 3538 3539 void getInternalMapKeyConfig(JClass type, 3540 JAccessibleObject field, 3541 String fieldName) 3542 { 3543 _annotationCfg.reset(field, MapKey.class); 3544 } 3545 3546 void getInternalAttributeOverrideConfig(JClass type, 3547 JAccessibleObject field, 3548 String fieldName) 3549 { 3550 _annotationCfg.reset(field, AttributeOverride.class); 3551 } 3552 3553 void getInternalAttributeOverrideConfig(JClass type) 3554 { 3555 _annotationCfg.reset(type, AttributeOverride.class); 3556 } 3557} 3558 | Popular Tags |