From 513f8ca8698d305961ef3ecd8f6e470ee016c520 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Mon, 27 Jan 2014 05:47:54 -0800 Subject: [PATCH] HHH-8897 : Integrate org.hibernate.metamodel from metamodel branch into master --- build.gradle | 4 + hibernate-core/hibernate-core.gradle | 20 +- .../hibernate/InvalidMappingException.java | 2 +- .../java/org/hibernate/SessionFactory.java | 8 + .../main/java/org/hibernate/TruthValue.java | 48 + .../hibernate/annotations/MultiTenancy.java | 54 + .../hibernate/annotations/TenantColumn.java | 71 + .../hibernate/annotations/TenantFormula.java | 44 + .../StandardServiceRegistryBuilder.java | 2 +- .../internal/StrategySelectorBuilder.java | 3 +- .../internal/StrategySelectorImpl.java | 6 +- .../spi/StrategySelectionException.java | 17 +- .../boot/spi/CacheRegionDefinition.java | 81 + .../internal/CacheDataDescriptionImpl.java | 6 +- .../internal/CollectionCacheInvalidator.java | 2 +- .../org/hibernate/cfg/AvailableSettings.java | 55 +- .../hibernate/cfg/DefaultNamingStrategy.java | 19 + .../org/hibernate/cfg/EJB3NamingStrategy.java | 19 + .../java/org/hibernate/cfg/HbmBinder.java | 4 +- .../hibernate/cfg/ImprovedNamingStrategy.java | 19 + .../org/hibernate/cfg/NamingStrategy.java | 30 + .../hibernate/cfg/ObjectNameNormalizer.java | 5 +- .../org/hibernate/cfg/OneToOneSecondPass.java | 4 +- .../org/hibernate/cfg/SettingsFactory.java | 2 +- .../BeanValidationIntegrator.java | 2 +- .../java/org/hibernate/dialect/Dialect.java | 52 + .../java/org/hibernate/dialect/H2Dialect.java | 5 + .../hibernate/dialect/Oracle8iDialect.java | 5 + .../dialect/unique/DB2UniqueDelegate.java | 41 +- .../dialect/unique/DefaultUniqueDelegate.java | 25 +- .../unique/InformixUniqueDelegate.java | 2 +- .../dialect/unique/UniqueDelegate.java | 6 +- .../engine/config/spi/StandardConverters.java | 64 + .../hibernate/engine/internal/Cascade.java | 2 +- .../UserSuppliedConnectionException.java | 35 + .../UserSuppliedConnectionProviderImpl.java | 4 +- .../connections/spi/JdbcConnectionAccess.java | 63 + .../internal/DefaultSchemaNameResolver.java | 69 + .../ExtractedDatabaseMetaDataImpl.java | 142 + .../env/internal/JdbcEnvironmentImpl.java | 339 ++ .../internal/JdbcEnvironmentInitiator.java | 214 + .../internal/LobCreatorBuilderImpl.java} | 32 +- .../NormalizingIdentifierHelperImpl.java | 217 + .../spi/ExtractedDatabaseMetaData.java | 55 +- .../engine/jdbc/env/spi/IdentifierHelper.java | 61 + .../engine/jdbc/env/spi/JdbcEnvironment.java | 124 + .../jdbc/env/spi/LobCreatorBuilder.java | 34 + .../env/spi/QualifiedObjectNameSupport.java | 55 + .../engine/jdbc/env/spi/SQLStateType.java | 46 + .../jdbc/env/spi/SchemaNameResolver.java | 46 + ...tandardQualifiedObjectNameSupportImpl.java | 144 + .../jdbc/internal/JdbcServicesImpl.java | 428 +- .../engine/jdbc/spi/JdbcServices.java | 4 + .../hibernate/engine/spi/CacheInitiator.java | 2 +- .../engine/spi/SyntheticAttributeHelper.java | 63 + .../internal/DefaultMergeEventListener.java | 6 +- .../EventListenerServiceInitiator.java | 2 +- .../main/java/org/hibernate/id/Assigned.java | 3 +- ...ompositeNestedGeneratedValueGenerator.java | 12 +- .../java/org/hibernate/id/Configurable.java | 4 +- .../hibernate/id/EntityIdentifierNature.java | 75 + .../org/hibernate/id/ForeignGenerator.java | 3 +- .../org/hibernate/id/IncrementGenerator.java | 3 +- .../id/MultipleHiLoPerTableGenerator.java | 64 +- .../id/PersistentIdentifierGenerator.java | 3 +- .../org/hibernate/id/SelectGenerator.java | 3 +- .../org/hibernate/id/SequenceGenerator.java | 43 +- .../hibernate/id/SequenceHiLoGenerator.java | 5 +- .../id/SequenceIdentityGenerator.java | 12 +- .../java/org/hibernate/id/TableGenerator.java | 50 +- .../org/hibernate/id/TableHiLoGenerator.java | 5 +- .../java/org/hibernate/id/UUIDGenerator.java | 19 +- .../org/hibernate/id/UUIDHexGenerator.java | 3 +- .../id/enhanced/DatabaseStructure.java | 3 +- .../id/enhanced/OptimizerFactory.java | 14 +- .../id/enhanced/SequenceStructure.java | 30 +- .../id/enhanced/SequenceStyleGenerator.java | 63 +- .../hibernate/id/enhanced/TableGenerator.java | 237 +- .../hibernate/id/enhanced/TableStructure.java | 47 +- .../DefaultIdentifierGeneratorFactory.java | 21 +- .../hibernate/integrator/spi/Integrator.java | 2 +- .../hibernate/internal/CoreMessageLogger.java | 42 + .../DefaultCustomEntityDirtinessStrategy.java | 59 + .../internal/FilterConfiguration.java | 86 +- .../internal/SessionFactoryImpl.java | 322 +- .../internal/util/ReflectHelper.java | 103 + .../hibernate/internal/util/StringHelper.java | 5 + .../util/collections/ArrayHelper.java | 11 + .../util/collections/CollectionHelper.java | 23 +- .../internal/util/xml/MappingReader.java | 24 +- .../jaxb/internal/AbstractJaxbProcessor.java | 190 + .../internal/JaxbConfigurationProcessor.java | 85 + .../jaxb/internal/JaxbMappingProcessor.java | 184 + .../jaxb/internal/LegacyJPAEventReader.java | 140 + .../internal/NamespaceAddingEventReader.java | 93 + .../java/org/hibernate/jaxb/package-info.java | 5 + .../{internal/jaxb => jaxb/spi}/JaxbRoot.java | 6 +- .../{internal/jaxb => jaxb/spi}/Origin.java | 38 +- .../jaxb => jaxb/spi}/SourceType.java | 2 +- .../spi/hbm/ComponentSourceElement.java} | 12 +- .../spi}/hbm/EntityElement.java | 30 +- .../IdBagPluralAttributeElementAdapter.java | 2 +- .../spi}/hbm/JoinElementSource.java | 2 +- .../spi}/hbm/MetaAttributeContainer.java | 2 +- .../spi}/hbm/PluralAttributeElement.java | 19 +- .../jaxb/spi/hbm/QuerySourceElement.java | 45 + .../hibernate/jaxb/spi/hbm/ReturnElement.java | 35 + .../spi}/hbm/SingularAttributeSource.java | 2 +- .../spi}/hbm/SubEntityElement.java | 2 +- .../jaxb/spi/hbm/TableInformationSource.java | 39 + .../metamodel/internal/AbstractAttribute.java | 131 + .../internal/AbstractIdentifiableType.java | 302 ++ .../internal/AbstractManagedType.java | 480 +++ .../metamodel/internal/AbstractType.java} | 41 +- .../jpa/metamodel/internal/BasicTypeImpl.java | 47 + .../internal/EmbeddableTypeImpl.java | 57 + .../metamodel/internal/EntityTypeImpl.java | 71 + .../JpaMetaModelPopulationSetting.java | 45 + .../internal/MappedSuperclassTypeImpl.java | 48 + .../jpa/metamodel/internal/MetamodelImpl.java | 128 + .../internal/PluralAttributeImpl.java | 223 + .../internal/SingularAttributeImpl.java | 128 + .../internal/UnsupportedFeature.java | 45 + .../internal/builder/AttributeBuilder.java | 704 ++++ .../internal/builder/AttributeMetadata.java | 93 + .../builder/AttributeTypeDescriptor.java | 60 + .../builder/BaseAttributeMetadata.java | 100 + .../internal/builder/MemberResolver.java | 47 + .../internal/builder/MetamodelBuilder.java | 532 +++ .../builder/PluralAttributeMetadata.java | 58 + .../builder/PluralAttributeMetadataImpl.java | 184 + .../builder/SingularAttributeMetadata.java | 41 + .../SingularAttributeMetadataImpl.java | 82 + .../internal/legacy/AbstractAttribute.java | 142 + .../legacy/AbstractIdentifiableType.java | 318 ++ .../internal/legacy/AbstractManagedType.java | 529 +++ .../internal/legacy/AbstractType.java | 44 + .../internal/legacy/AttributeFactory.java | 1016 +++++ .../internal/legacy/AttributeImplementor.java | 33 + .../internal/legacy/BasicTypeImpl.java | 46 + .../internal/legacy/EmbeddableTypeImpl.java | 56 + .../internal/legacy/EntityTypeImpl.java | 68 + .../legacy/MappedSuperclassTypeImpl.java | 24 + .../internal/legacy/MetadataContext.java | 510 +++ .../internal/legacy/MetamodelImpl.java | 238 ++ .../internal/legacy/PluralAttributeImpl.java | 260 ++ .../legacy/SingularAttributeImpl.java | 145 + .../hibernate/jpa/metamodel/package-info.java | 1 + .../java/org/hibernate/loader/JoinWalker.java | 2 +- .../org/hibernate/mapping/Collection.java | 4 +- .../org/hibernate/metamodel/Metadata.java | 101 +- .../hibernate/metamodel/MetadataBuilder.java | 106 + .../hibernate/metamodel/MetadataSources.java | 332 +- .../metamodel/SessionFactoryBuilder.java | 81 + .../AbstractPluralAttributeBinding.java | 394 -- .../AbstractSingularAttributeBinding.java | 113 - .../binding/AssociationAttributeBinding.java | 66 - .../binding/AttributeBindingContainer.java | 136 - .../binding/BasicAttributeBinding.java | 197 - .../metamodel/binding/CollectionKey.java | 74 - .../binding/ComponentAttributeBinding.java | 164 - .../metamodel/binding/EntityBinding.java | 605 --- .../metamodel/binding/EntityIdentifier.java | 95 - .../metamodel/binding/IdGenerator.java | 75 - .../binding/ManyToManyCollectionElement.java | 86 - .../binding/ManyToOneAttributeBinding.java | 241 -- .../metamodel/binding/SimpleValueBinding.java | 100 - .../binding/SingularAttributeBinding.java | 81 - .../hibernate/metamodel/internal/Binder.java | 3078 ++++++++++++++ .../CollectionTableNamingStrategyHelper.java | 69 + .../internal/ColumnNamingStrategyHelper.java | 57 + .../ConstraintNamingStrategyHelper.java | 109 + .../DefaultColumnNamingStrategyHelper.java} | 46 +- .../internal/EntityHierarchyHelper.java | 121 + .../metamodel/internal/ForeignKeyHelper.java | 343 ++ .../metamodel/internal/HashedNameUtil.java | 108 + .../metamodel/internal/HelperContext.java | 39 + .../internal/HibernateTypeHelper.java | 874 ++++ .../LocalBindingContextManagerImpl.java | 176 + ...nyCollectionTableNamingStrategyHelper.java | 86 + .../internal/MetadataBuilderImpl.java | 114 +- .../metamodel/internal/MetadataImpl.java | 977 +++++ .../internal/NaturalIdUniqueKeyHelper.java | 69 + .../internal/RelationalIdentifierHelper.java | 65 + .../RelationalValueBindingHelper.java | 194 + .../internal/SessionFactoryBuilderImpl.java | 202 + .../metamodel/internal/SourceIndex.java | 474 +++ .../metamodel/internal/TableHelper.java | 258 ++ .../internal/TableNamingStrategyHelper.java | 65 + .../AssociationRelationalBindingResolver.java | 113 + ...ociationRelationalBindingResolverImpl.java | 359 ++ ...ociationRelationalBindingResolverImpl.java | 428 ++ .../source}/OverriddenMappingDefaults.java | 12 +- .../AbstractConstraintSource.java} | 39 +- ...oManyPluralAttributeElementSourceImpl.java | 86 + ...actPluralAssociationElementSourceImpl.java | 100 + ...tractPluralAttributeElementSourceImpl.java | 61 + ...bstractPluralAttributeIndexSourceImpl.java | 84 + .../AbstractToOneAttributeSourceImpl.java | 138 + .../AnnotationAttributeSource.java | 38 + .../annotations/AnnotationBindingContext.java | 74 + .../AnnotationBindingContextImpl.java | 73 +- ...AnnotationMetadataSourceProcessorImpl.java | 125 + ...BasicPluralAttributeElementSourceImpl.java | 89 + .../BasicPluralAttributeIndexSourceImpl.java | 101 + .../source/annotations/ColumnSourceImpl.java | 164 + .../ComponentAttributeSourceImpl.java | 237 ++ ...ositePluralAttributeElementSourceImpl.java | 173 + ...mpositePluralAttributeIndexSourceImpl.java | 113 + .../annotations}/DerivedValueSourceImpl.java | 13 +- .../annotations}/DiscriminatorSourceImpl.java | 24 +- .../annotations/EntityHierarchyImpl.java | 18 +- .../source/annotations/EntitySourceImpl.java | 579 +++ .../annotations/FetchProfileSourceImpl.java | 104 + .../FilterDefinitionSourceImpl.java | 94 + .../source/annotations/FilterSourceImpl.java | 94 + .../annotations/HibernateTypeSourceImpl.java | 77 + .../IdentifierGeneratorSourceContainer.java} | 30 +- ...dentifierGeneratorSourceContainerImpl.java | 107 + .../annotations/InLineViewSourceImpl.java | 122 + .../IndexConstraintSourceImpl.java | 52 + .../IndexedPluralAttributeSourceImpl.java | 226 + .../JoinedSubclassEntitySourceImpl.java | 120 + .../annotations/JpaCallbackSourceImpl.java | 73 + ...ToAnyPluralAttributeElementSourceImpl.java | 20 + ...pedByPluralAttributeElementSourceImpl.java | 57 + ...oManyPluralAttributeElementSourceImpl.java | 161 + .../MapKeyPluralAttributeIndexSourceImpl.java | 75 + .../annotations/MutliTenancySourceImpl.java | 107 + ...pedByPluralAttributeElementSourceImpl.java | 53 + ...oManyPluralAttributeElementSourceImpl.java | 46 + .../PluralAttributeKeySourceImpl.java | 134 + .../PluralAttributeSourceImpl.java | 421 ++ .../annotations/RootEntitySourceImpl.java | 313 ++ .../annotations/SecondaryTableSourceImpl.java | 161 + ...uentialPluralAttributeIndexSourceImpl.java | 90 + .../SimpleIdentifierSourceImpl.java | 45 +- .../SingularAttributeSourceImpl.java | 190 + .../source/annotations/SizeSourceImpl.java | 66 + .../source/annotations/SourceHelper.java | 177 + .../SubclassEntitySourceImpl.java} | 37 +- .../source/annotations/TableSourceImpl.java | 186 + .../annotations/ToOneAttributeSourceImpl.java | 314 ++ .../ToOneMappedByAttributeSourceImpl.java | 119 + .../annotations/TypeDescriptorSourceImpl.java | 114 + .../UniqueConstraintSourceImpl.java} | 49 +- .../UnknownInheritanceTypeException.java | 2 +- .../VersionAttributeSourceImpl.java | 51 + .../attribute/AbstractOverrideDefinition.java | 122 + .../attribute/AssociationAttribute.java | 577 +++ .../attribute/AssociationOverride.java} | 43 +- .../attribute/AttributeOverride.java | 107 + .../annotations/attribute/BasicAttribute.java | 191 +- .../source/annotations/attribute/Column.java} | 101 +- .../annotations/attribute/FormulaValue.java | 45 + .../attribute/MappedAttribute.java | 338 ++ .../attribute/PluralAssociationAttribute.java | 594 +++ .../attribute/PrimaryKeyJoinColumn.java | 53 + .../SingularAssociationAttribute.java | 82 + .../source/annotations/attribute/package.html | 34 + .../type/AbstractAttributeTypeResolver.java | 131 + .../attribute/type/AttributeTypeResolver.java | 19 +- .../type/CompositeAttributeTypeResolver.java | 68 +- .../type/EnumeratedTypeResolver.java | 141 + .../attribute/type/HibernateTypeResolver.java | 145 + .../attribute/type/LobTypeResolver.java | 120 + .../attribute/type/TemporalTypeResolver.java | 158 + .../annotations/attribute/type/package.html | 33 + .../annotations/entity/ConfiguredClass.java | 841 ++++ .../annotations/entity/EmbeddableClass.java | 116 + .../entity/EmbeddableHierarchy.java | 127 +- .../entity/EntityBindingContext.java | 51 +- .../annotations/entity/EntityClass.java | 594 +++ .../source/annotations/entity/IdType.java | 55 + .../annotations/entity/MappedSuperclass.java | 57 + .../annotations/entity/RootEntityClass.java | 395 ++ .../source/annotations/entity/package.html | 33 + .../global/FetchProfileProcessor.java} | 46 +- .../global/IdGeneratorProcessor.java | 280 ++ .../annotations/global/QueryProcessor.java | 437 ++ .../global/SqlResultSetProcessor.java | 344 ++ .../annotations/global/TableProcessor.java | 162 + .../internal/source/annotations/package.html | 34 + .../util/AnnotationParserHelper.java | 242 ++ .../annotations/util/ClassmateHelper.java | 121 + .../util}/EntityHierarchyBuilder.java | 204 +- .../util}/EnumConversionHelper.java | 88 +- .../annotations/util}/HibernateDotNames.java | 31 +- .../source/annotations/util}/JPADotNames.java | 24 +- .../annotations/util/JPAListenerHelper.java | 365 ++ .../annotations/util}/JandexHelper.java | 363 +- .../annotations/util/MappingAssertion.java | 86 + .../source/annotations/util/package.html | 33 + .../annotations/xml/PseudoJpaDotNames.java | 2 +- .../xml/filter/AbstractAnnotationFilter.java | 8 +- .../xml/filter/ExclusiveAnnotationFilter.java | 19 +- .../xml/filter/IndexedAnnotationFilter.java | 8 +- .../xml/filter/NameAnnotationFilter.java | 28 +- .../filter/NameTargetAnnotationFilter.java | 85 +- .../xml/mocker/AbstractAttributesBuilder.java | 69 +- .../mocker/AbstractEntityObjectMocker.java | 89 +- .../xml/mocker/AbstractMocker.java | 57 +- .../annotations/xml/mocker/AccessHelper.java | 34 +- .../xml/mocker/AnnotationMocker.java | 109 +- .../xml/mocker/AttributesBuilder.java | 66 + .../xml/mocker/AttributesContainer.java | 35 + .../annotations/xml/mocker/BasicMocker.java | 33 +- .../mocker/DefaultConfigurationHelper.java | 145 +- .../xml/mocker/ElementCollectionMocker.java | 57 +- .../mocker/EmbeddableAttributesBuilder.java | 65 + .../xml/mocker/EmbeddableMocker.java | 61 +- .../xml/mocker/EmbeddedIdMocker.java | 23 +- .../xml/mocker/EmbeddedMocker.java | 27 +- .../annotations/xml/mocker/EntityElement.java | 17 + .../xml/mocker/EntityMappingsMocker.java | 30 +- .../annotations/xml/mocker/EntityMocker.java | 129 +- .../xml/mocker/GlobalAnnotationMocker.java | 90 +- .../xml/mocker/GlobalAnnotations.java | 127 +- .../annotations/xml/mocker/IdMocker.java | 43 +- .../annotations/xml/mocker/IndexBuilder.java | 83 +- .../annotations/xml/mocker/Listener.java | 8 + .../xml/mocker/ListenerMocker.java | 101 +- .../xml/mocker/ManyToManyMocker.java | 41 +- .../xml/mocker/ManyToOneMocker.java | 27 +- .../xml/mocker/MappedSuperclassMocker.java | 48 +- .../annotations/xml/mocker/MockHelper.java | 81 +- .../xml/mocker/OneToManyMocker.java | 46 +- .../xml/mocker/OneToOneMocker.java | 27 +- .../xml/mocker/PersistenceMetadataMocker.java | 12 +- .../xml/mocker/PropertyElement.java | 14 + .../xml/mocker/PropertyMocker.java | 63 +- .../annotations/xml/mocker/SchemaAware.java} | 16 +- .../xml/mocker/TransientMocker.java | 42 +- .../annotations/xml/mocker/VersionMocker.java | 28 +- .../AbstractComponentAttributeSourceImpl.java | 254 ++ .../source/hbm/AbstractConstraintSource.java} | 78 +- .../source/hbm/AbstractEntitySourceImpl.java | 596 +++ .../source/hbm/AbstractHbmSourceNode.java | 73 + ...actPluralAssociationElementSourceImpl.java | 72 + .../AbstractPluralAttributeSourceImpl.java | 207 +- .../source/hbm/AbstractReturnBinder.java | 135 + .../hbm/AbstractToOneAttributeSourceImpl.java | 266 ++ .../internal/source/hbm/ArraySourceImpl.java | 82 + .../source/hbm/BagSourceImpl.java} | 22 +- ...BasicPluralAttributeElementSourceImpl.java | 92 +- .../source/hbm/ColumnAttributeSourceImpl.java | 66 +- .../source/hbm/ColumnSourceImpl.java | 71 +- .../hbm/ComponentAttributeSourceImpl.java | 164 + ...ositePluralAttributeElementSourceImpl.java | 186 + ...mpositePluralAttributeIndexSourceImpl.java | 180 + .../source/hbm/EntityHierarchyImpl.java | 11 +- .../source/hbm/FetchProfileSourceImpl.java | 94 + .../hbm/FilterDefinitionSourceImpl.java | 97 + .../internal/source/hbm/FilterSourceImpl.java | 110 + .../source/hbm/FormulaImpl.java | 16 +- .../source/hbm/HbmBindingContext.java | 14 +- .../hbm/HbmMetadataSourceProcessorImpl.java | 120 + .../metamodel/internal/source/hbm/Helper.java | 525 +++ .../source/hbm/HibernateMappingProcessor.java | 333 ++ .../internal/source/hbm/HierarchyBuilder.java | 228 + .../hbm/IdentifierKeyAttributeSourceImpl.java | 44 + .../hbm/IdentifierKeyManyToOneSourceImpl.java | 44 + .../source/hbm/InLineViewSourceImpl.java | 70 + .../source/hbm/IndexConstraintSourceImpl.java | 52 + .../hbm/JoinedSubclassEntitySourceImpl.java | 124 + .../source/hbm/KeyAttributeSourceImpl.java | 198 + .../source/hbm/KeyManyToOneSourceImpl.java | 200 + .../internal/source/hbm/ListSourceImpl.java | 87 + .../source/hbm/LoadCollectionBinder.java | 62 + ...oManyPluralAttributeElementSourceImpl.java | 256 ++ .../hbm/ManyToOneAttributeSourceImpl.java | 204 + .../internal/source/hbm/MapKeySourceImpl.java | 225 + .../internal/source/hbm/MapSourceImpl.java | 105 + .../source/hbm/MappingDocument.java | 37 +- .../source/hbm/NamedQueryBindingHelper.java | 212 + ...oManyPluralAttributeElementSourceImpl.java | 38 +- .../hbm/OneToOneAttributeSourceImpl.java | 199 + .../hbm/PluralAttributeKeySourceImpl.java | 88 +- .../hbm/PropertyAttributeSourceImpl.java | 121 +- .../source/hbm/ResultSetMappingBinder.java | 60 + .../internal/source/hbm/ReturnBinder.java | 140 + .../internal/source/hbm/ReturnJoinBinder.java | 59 + .../source/hbm/RootEntitySourceImpl.java | 593 +++ .../source/hbm/SecondaryTableSourceImpl.java | 193 + ...uentialPluralAttributeIndexSourceImpl.java | 195 + .../source/hbm/SetSourceImpl.java} | 28 +- ...SingularIdentifierAttributeSourceImpl.java | 94 +- .../internal/source/hbm/SizeSourceImpl.java | 75 + .../source/hbm/SubclassEntitySourceImpl.java | 69 + .../internal/source/hbm/TableSourceImpl.java | 59 + .../hbm/TimestampAttributeSourceImpl.java | 98 +- .../source/hbm/TypeDescriptorSourceImpl.java} | 48 +- ...nexpectedAttributeSourceTypeException.java | 35 + .../hbm/UniqueConstraintSourceImpl.java | 58 + .../hbm/VersionAttributeSourceImpl.java | 100 +- .../AbstractQueryElementContentsParser.java | 228 + .../BasicQueryElementContentParser.java | 37 + .../parser/SQLQueryElementContentParser.java | 118 + .../relational/AbstractConstraint.java | 122 - .../AbstractTableSpecification.java | 101 - .../metamodel/relational/Column.java | 195 - .../metamodel/relational/Database.java | 224 - .../metamodel/relational/Schema.java | 174 - .../hibernate/metamodel/relational/Table.java | 278 -- .../hibernate/metamodel/relational/Tuple.java | 91 - .../metamodel/source/MetadataImplementor.java | 77 - ...AnnotationMetadataSourceProcessorImpl.java | 167 - .../source/annotations/ReflectionHelper.java | 87 - .../attribute/AssociationAttribute.java | 316 -- .../attribute/AttributeOverride.java | 107 - .../attribute/ColumnSourceImpl.java | 90 - .../attribute/ColumnValuesSourceImpl.java | 124 - .../ExplicitHibernateTypeSourceImpl.java | 51 - .../annotations/attribute/FormulaValue.java | 22 - .../attribute/MappedAttribute.java | 183 - .../SingularAttributeSourceImpl.java | 136 - .../attribute/ToOneAttributeSourceImpl.java | 87 - .../type/AttributeTypeResolverImpl.java | 79 - .../type/EnumeratedTypeResolver.java | 102 - .../attribute/type/LobTypeResolver.java | 111 - .../attribute/type/TemporalTypeResolver.java | 107 - .../attribute/type/package-info.java | 28 - .../entity/ComponentAttributeSourceImpl.java | 236 -- .../annotations/entity/ConfiguredClass.java | 708 ---- .../annotations/entity/EmbeddableClass.java | 77 - .../annotations/entity/EntityClass.java | 986 ----- .../annotations/entity/EntitySourceImpl.java | 225 - .../entity/RootEntitySourceImpl.java | 123 - .../annotations/global/FilterDefBinder.java | 100 - .../annotations/global/IdGeneratorBinder.java | 214 - .../annotations/global/QueryBinder.java | 366 -- .../annotations/global/TableBinder.java | 130 - .../annotations/global/TypeDefBinder.java | 126 - .../xml/mocker/AttributesBuilder.java | 109 - .../mocker/EmbeddableAttributesBuilder.java | 110 - .../annotations/xml/mocker/SchemaAware.java | 154 - .../metamodel/source/binder/Binder.java | 1123 ----- .../source/hbm/AbstractEntitySourceImpl.java | 311 -- .../hbm/ComponentAttributeSourceImpl.java | 239 -- ...ositePluralAttributeElementSourceImpl.java | 108 - .../hbm/HbmMetadataSourceProcessorImpl.java | 98 - .../metamodel/source/hbm/Helper.java | 378 -- .../source/hbm/HibernateMappingProcessor.java | 287 -- .../source/hbm/HierarchyBuilder.java | 169 - ...oManyPluralAttributeElementSourceImpl.java | 159 - .../hbm/ManyToOneAttributeSourceImpl.java | 271 -- .../source/hbm/RootEntitySourceImpl.java | 249 -- .../source/hbm/SubclassEntitySourceImpl.java | 100 - .../source/internal/AssociationResolver.java | 82 - .../internal/HibernateTypeResolver.java | 287 -- .../internal/IdentifierGeneratorResolver.java | 97 - .../metamodel/source/internal/JaxbHelper.java | 314 -- .../source/internal/MetadataImpl.java | 600 --- .../internal/SessionFactoryBuilderImpl.java | 99 - .../spi/AdditionalJaxbRootProducer.java | 48 + .../metamodel/spi/MetadataContributor.java | 42 + .../metamodel/spi/MetadataImplementor.java | 85 + .../MetadataSourceProcessor.java | 47 +- .../spi/MetadataSourcesContributor.java | 44 + .../metamodel/spi/TypeContributor.java | 3 - .../binding/AbstractAttributeBinding.java | 73 +- .../AbstractAttributeBindingContainer.java | 323 ++ ...actCompositeAttributeBindingContainer.java | 320 ++ ...ralAttributeAssociationElementBinding.java | 56 + .../AbstractPluralAttributeBinding.java | 309 ++ ...AbstractPluralAttributeElementBinding.java | 80 + .../AbstractPluralAttributeIndexBinding.java | 56 + ...ctSingularAssociationAttributeBinding.java | 188 + .../AbstractSingularAttributeBinding.java | 132 + .../metamodel/spi/binding/ArrayBinding.java | 65 + .../{ => spi}/binding/AttributeBinding.java | 26 +- .../binding/AttributeBindingContainer.java | 334 ++ .../spi/binding/BackRefAttributeBinding.java | 108 + .../binding/BagBinding.java} | 42 +- .../spi/binding/BasicAttributeBinding.java | 85 + .../BasicPluralAttributeElementBinding.java | 62 + .../BasicPluralAttributeIndexBinding.java | 62 + .../metamodel/{ => spi}/binding/Caching.java | 2 +- .../{ => spi}/binding/CascadeType.java | 2 +- .../binding/Cascadeable.java} | 20 +- .../{ => spi}/binding/CollectionLaziness.java | 2 +- .../binding/CompositeAttributeBinding.java | 556 +++ .../CompositeAttributeBindingContainer.java} | 20 +- ...ompositePluralAttributeElementBinding.java | 109 + .../CompositePluralAttributeIndexBinding.java | 95 + .../{ => spi}/binding/CustomSQL.java | 2 +- .../metamodel/spi/binding/EntityBinding.java | 847 ++++ .../binding/EntityDiscriminator.java | 33 +- .../spi/binding/EntityIdentifier.java | 537 +++ .../metamodel/spi/binding/EntityVersion.java | 54 + .../{ => spi}/binding/FetchProfile.java | 2 +- .../binding/Fetchable.java} | 25 +- .../binding/Filterable.java} | 19 +- .../metamodel/{ => spi}/binding/Helper.java | 7 +- .../binding/HibernateTypeDescriptor.java | 25 +- .../{ => spi}/binding/HierarchyDetails.java | 29 +- .../IdentifierGeneratorDefinition.java | 118 + .../IndexedPluralAttributeBinding.java | 38 + .../{ => spi}/binding/InheritanceType.java | 2 +- .../JoinRelationalValueBindingContainer.java | 80 + .../{ => spi}/binding/KeyValueBinding.java | 2 +- .../metamodel/spi/binding/ListBinding.java | 71 + ...anyToAnyPluralAttributeElementBinding.java | 47 + ...nyToManyPluralAttributeElementBinding.java | 108 + .../binding/ManyToOneAttributeBinding.java | 64 + .../metamodel/spi/binding/MapBinding.java | 92 + .../{ => spi}/binding/MetaAttribute.java | 2 +- ...neToManyPluralAttributeElementBinding.java | 61 + .../spi/binding/OneToOneAttributeBinding.java | 70 + ...ralAttributeAssociationElementBinding.java | 33 + .../binding/PluralAttributeBinding.java | 44 +- .../PluralAttributeElementBinding.java | 122 + .../binding/PluralAttributeIndexBinding.java | 73 + .../binding/PluralAttributeKeyBinding.java | 151 + .../spi/binding/RelationalValueBinding.java | 111 + .../RelationalValueBindingContainer.java | 125 + .../metamodel/spi/binding/SecondaryTable.java | 116 + .../{ => spi}/binding/SetBinding.java | 34 +- .../SingularAssociationAttributeBinding.java | 40 +- .../spi/binding/SingularAttributeBinding.java | 97 + ...ngularNonAssociationAttributeBinding.java} | 8 +- .../spi/binding/TenantDiscrimination.java | 59 + .../metamodel/spi/binding/TypeDefinition.java | 116 + .../domain/AbstractAttributeContainer.java | 150 +- .../domain/Aggregate.java} | 14 +- .../metamodel/{ => spi}/domain/Attribute.java | 13 +- .../{ => spi}/domain/AttributeContainer.java | 44 +- .../metamodel/{ => spi}/domain/BasicType.java | 4 +- .../metamodel/{ => spi}/domain/Entity.java | 4 +- .../{ => spi}/domain/Hierarchical.java | 2 +- .../domain/IndexedPluralAttribute.java | 2 +- .../metamodel/{ => spi}/domain/JavaType.java | 2 +- .../metamodel/{ => spi}/domain/NonEntity.java | 4 +- .../metamodel/spi/domain/PluralAttribute.java | 79 + .../{ => spi}/domain/SingularAttribute.java | 2 +- .../{ => spi}/domain/Superclass.java | 4 +- .../metamodel/{ => spi}/domain/Type.java | 10 +- .../{ => spi}/domain/TypeNature.java | 6 +- .../metamodel/{ => spi}/domain/package.html | 0 .../AbstractAuxiliaryDatabaseObject.java | 13 +- .../spi/relational/AbstractConstraint.java | 193 + .../AbstractTableSpecification.java | 226 + .../relational/AbstractValue.java} | 48 +- .../relational/AuxiliaryDatabaseObject.java | 76 + .../BasicAuxiliaryDatabaseObjectImpl.java | 7 +- .../{ => spi}/relational/CheckConstraint.java | 2 +- .../metamodel/spi/relational/Column.java | 240 ++ .../{ => spi}/relational/Constraint.java | 10 +- .../metamodel/spi/relational/Database.java | 121 + .../spi/relational/DenormalizedTable.java | 128 + .../{ => spi}/relational/DerivedValue.java | 24 +- .../{ => spi}/relational/Exportable.java | 25 +- .../relational/ExportableProducer.java} | 19 +- .../{ => spi}/relational/ForeignKey.java | 94 +- .../{ => spi}/relational/Identifier.java | 113 +- .../IllegalIdentifierException.java | 2 +- .../{ => spi}/relational/InLineView.java | 22 +- .../metamodel/{ => spi}/relational/Index.java | 100 +- .../metamodel/spi/relational/InitCommand.java | 41 + .../relational/JdbcDataType.java} | 46 +- .../{ => spi}/relational/Loggable.java | 2 +- .../{ => spi}/relational/ObjectName.java | 140 +- .../{ => spi}/relational/PrimaryKey.java | 34 +- .../metamodel/spi/relational/Schema.java | 213 + .../{ => spi}/relational/Sequence.java | 58 +- .../metamodel/{ => spi}/relational/Size.java | 3 +- .../metamodel/spi/relational/Table.java | 314 ++ .../relational/TableSpecification.java | 65 +- .../{ => spi}/relational/UniqueKey.java | 39 +- .../metamodel/{ => spi}/relational/Value.java | 63 +- .../{ => spi}/relational/ValueContainer.java | 13 +- .../{ => spi}/relational/package.html | 0 .../AggregatedCompositeIdentifierSource.java} | 10 +- ...ociationPluralAttributeElementSource.java} | 14 +- .../spi/source/AssociationSource.java | 58 + ...tributeRelationalValueSourceContainer.java | 40 + .../source}/AttributeSource.java | 13 +- .../source}/AttributeSourceContainer.java | 6 +- .../AttributeSourceResolutionContext.java} | 22 +- .../BasicPluralAttributeElementSource.java | 10 +- .../BasicPluralAttributeIndexSource.java} | 6 +- .../{ => spi}/source/BindingContext.java | 5 +- .../spi/source/CascadeStyleSource.java | 42 + .../spi/source/ColumnBindingDefaults.java | 56 + .../binder => spi/source}/ColumnSource.java | 37 +- .../source}/ComponentAttributeSource.java | 2 +- .../spi/source/CompositeIdentifierSource.java | 43 + ...CompositePluralAttributeElementSource.java | 5 +- .../CompositePluralAttributeIndexSource.java | 36 + .../source}/ConstraintSource.java | 14 +- .../source}/DerivedValueSource.java | 2 +- .../source}/DiscriminatorSource.java | 2 +- ...tyAttributePluralAttributeIndexSource.java | 35 + .../source}/EntityHierarchy.java | 6 +- .../binder => spi/source}/EntitySource.java | 34 +- .../spi/source/FetchProfileSource.java | 71 + .../spi/source/FetchableAttributeSource.java | 38 + .../spi/source/FilterDefinitionSource.java | 58 + .../spi/source/FilterParameterSource.java | 45 + .../metamodel/spi/source/FilterSource.java | 73 + .../source/ForeignKeyContributingSource.java | 122 + .../source/HibernateTypeSource.java} | 15 +- .../spi/source/IdentifierGeneratorSource.java | 56 + .../source}/IdentifierSource.java | 46 +- .../spi/source/InLineViewSource.java | 41 + .../source/IndexConstraintSource.java} | 10 +- .../source/IndexedPluralAttributeSource.java} | 15 +- .../source/InvalidMappingException.java} | 50 +- .../source/JoinedSubclassEntitySource.java | 39 + .../source/JpaCallbackSource.java} | 4 +- .../{ => spi}/source/LocalBindingContext.java | 7 +- ...ManyToAnyPluralAttributeElementSource.java | 5 +- ...anyToManyPluralAttributeElementSource.java | 20 +- .../source/MappedByAssociationSource.java} | 8 +- .../{ => spi}/source/MappingDefaults.java | 9 +- .../{ => spi}/source/MappingException.java | 7 +- .../source/MappingNotFoundException.java | 4 +- .../source/MetaAttributeContext.java | 6 +- .../source}/MetaAttributeSource.java | 2 +- .../metamodel/spi/source/MetaSource.java | 36 + .../spi/source/MultiTenancySource.java | 40 + ...onAggregatedCompositeIdentifierSource.java | 55 + ...OneToManyPluralAttributeElementSource.java | 5 +- .../metamodel/spi/source/Orderable.java | 51 + .../source/PluralAttributeElementSource.java} | 33 +- .../PluralAttributeElementSourceResolver.java | 31 + .../source/PluralAttributeIndexSource.java | 56 + .../PluralAttributeIndexSourceResolver.java} | 10 +- .../source}/PluralAttributeKeySource.java | 13 +- .../source}/PluralAttributeSource.java | 63 +- .../spi/source/RelationalValueSource.java | 61 + .../RelationalValueSourceContainer.java | 53 + .../source}/RootEntitySource.java | 23 +- .../spi/source/SecondaryTableSource.java | 81 + ...SequentialPluralAttributeIndexSource.java} | 8 +- .../source}/SimpleIdentifierSource.java | 5 +- .../source}/SingularAttributeSource.java | 48 +- .../metamodel/spi/source/SizeSource.java | 116 + .../source/Sortable.java} | 26 +- .../source}/SubclassEntityContainer.java | 2 +- .../source}/SubclassEntitySource.java | 7 +- .../source/TableSource.java} | 17 +- .../source/TableSpecificationSource.java} | 27 +- .../source}/ToOneAttributeSource.java | 33 +- .../ToOneAttributeSourceNatureResolver.java | 46 + .../spi/source/TypeDescriptorSource.java | 70 + .../source}/UniqueConstraintSource.java | 3 +- .../source/VersionAttributeSource.java} | 9 +- .../{ => spi}/source/XsdException.java | 2 +- .../AbstractCollectionPersister.java | 432 ++ .../collection/BasicCollectionPersister.java | 11 + .../collection/OneToManyPersister.java | 27 + .../entity/AbstractEntityPersister.java | 369 +- .../persister/entity/DiscriminatorType.java | 2 +- .../entity/JoinedSubclassEntityPersister.java | 529 ++- .../entity/SingleTableEntityPersister.java | 179 +- .../entity/UnionSubclassEntityPersister.java | 234 +- .../internal/PersisterFactoryImpl.java | 30 +- .../StandardPersisterClassResolver.java | 8 +- .../persister/spi/PersisterClassResolver.java | 4 +- .../persister/spi/PersisterFactory.java | 8 +- .../procedure/internal/ProcedureCallImpl.java | 2 +- .../property/PropertyAccessorFactory.java | 2 +- .../hibernate/secure/spi/JaccIntegrator.java | 2 +- .../org/hibernate/service/ConfigLoader.java | 6 +- .../service/StandardServiceInitiators.java | 5 + .../service/internal/JaxbProcessor.java | 8 +- ...sionFactoryServiceRegistryFactoryImpl.java | 2 +- .../SessionFactoryServiceRegistryImpl.java | 2 +- .../spi/SessionFactoryServiceInitiator.java | 2 +- .../SessionFactoryServiceRegistryFactory.java | 2 +- .../stat/internal/StatisticsInitiator.java | 2 +- .../hibernate/tool/hbm2ddl/SchemaExport.java | 171 +- .../internal/ColumnInformationImpl.java | 109 + .../internal/DatabaseInformationImpl.java | 77 + .../internal/ExtractionContextImpl.java | 103 + .../internal/ForeignKeyInformationImpl.java | 75 + .../internal/IndexInformationImpl.java | 83 + .../internal/PrimaryKeyInformationImpl.java | 51 + .../internal/SequenceInformationImpl.java | 52 + ...StandardJdbcDatabaseMetaDataExtractor.java | 429 ++ .../internal/TableInformationImpl.java | 163 + ...TemporarySequenceInformationExtractor.java | 91 + .../schema/extract}/package-info.java | 6 +- .../schema/extract/spi/ColumnInformation.java | 92 + .../extract/spi/DatabaseInformation.java | 53 + .../spi/DatabaseInformationBuilder.java | 148 + .../schema/extract/spi/ExtractionContext.java | 49 + .../extract/spi/ForeignKeyInformation.java | 62 + .../schema/extract/spi/IndexInformation.java | 50 + .../extract/spi/PrimaryKeyInformation.java | 47 + .../spi/SchemaExtractionException.java | 39 + .../extract/spi/SchemaMetaDataExtractor.java | 111 + .../extract/spi/SequenceInformation.java | 47 + .../spi/SequenceInformationExtractor.java | 46 + .../schema/extract/spi/TableInformation.java | 108 + .../HibernateSchemaManagementTool.java | 73 + .../schema/internal/SchemaCreatorImpl.java | 175 + .../schema/internal/SchemaDropperImpl.java | 169 + .../SchemaManagementToolInitiator.java | 54 + .../schema/internal/SchemaMigratorImpl.java | 189 + .../schema/internal/SchemaValidatorImpl.java | 146 + ...andardAuxiliaryDatabaseObjectExporter.java | 50 + .../internal/StandardForeignKeyExporter.java | 106 + .../internal/StandardIndexExporter.java | 86 + .../internal/StandardSequenceExporter.java | 54 + .../internal/StandardTableExporter.java | 183 + .../internal/TemporaryTableExporter.java | 100 + .../hibernate/tool/schema/package-info.java | 1 + .../hibernate/tool/schema/spi/Exporter.java | 51 + .../tool/schema/spi/SchemaCreator.java | 58 + .../tool/schema/spi/SchemaDropper.java | 57 + .../spi/SchemaManagementException.java} | 20 +- .../tool/schema/spi/SchemaManagementTool.java | 40 + .../tool/schema/spi/SchemaMigrator.java | 52 + .../schema/spi/SchemaValidator.java} | 25 +- .../org/hibernate/tool/schema/spi/Target.java | 64 + .../tuple/DynamicMapInstantiator.java | 2 +- .../org/hibernate/tuple/PojoInstantiator.java | 35 +- .../org/hibernate/tuple/PropertyFactory.java | 258 +- .../component/AbstractComponentTuplizer.java | 45 + .../AbstractCompositionAttribute.java | 2 +- .../tuple/component/ComponentMetamodel.java | 34 + .../tuple/component/ComponentTuplizer.java | 5 +- .../component/ComponentTuplizerFactory.java | 94 +- .../DynamicMapComponentTuplizer.java | 37 +- .../component/PojoComponentTuplizer.java | 138 +- .../tuple/entity/AbstractEntityTuplizer.java | 35 +- .../entity/DynamicMapEntityTuplizer.java | 15 +- .../EntityBasedAssociationAttribute.java | 2 +- .../tuple/entity/EntityMetamodel.java | 103 +- .../tuple/entity/EntityTuplizer.java | 2 +- .../tuple/entity/EntityTuplizerFactory.java | 2 +- .../tuple/entity/PojoEntityTuplizer.java | 37 +- .../org/hibernate/type/AbstractLobType.java | 2 +- .../type/AbstractStandardBasicType.java | 4 +- .../java/org/hibernate/type/AbstractType.java | 4 +- .../main/java/org/hibernate/type/AnyType.java | 4 +- .../org/hibernate/type/CollectionType.java | 4 +- .../org/hibernate/type/ComponentType.java | 2 +- .../hibernate/type/CompositeCustomType.java | 2 +- .../java/org/hibernate/type/CustomType.java | 2 +- .../java/org/hibernate/type/EnumType.java | 4 + .../hibernate/type/ForeignKeyDirection.java | 64 +- .../org/hibernate/type/ManyToOneType.java | 4 +- .../java/org/hibernate/type/MetaType.java | 2 +- .../java/org/hibernate/type/NullableType.java | 2 +- .../java/org/hibernate/type/OneToOneType.java | 4 +- .../hibernate/type/SpecialOneToOneType.java | 2 +- .../main/java/org/hibernate/type/Type.java | 2 +- .../java/org/hibernate/usertype/Sized.java | 2 +- .../org/hibernate/hibernate-mapping-4.0.xsd | 3710 +++++++++-------- .../main/xjb/hbm-configuration-bindings.xjb | 9 +- .../src/main/xjb/hbm-mapping-bindings.xjb | 203 +- hibernate-core/src/main/xjb/orm-bindings.xjb | 98 +- .../connection/ConnectionCreatorTest.java | 11 + .../SequenceHiLoGeneratorNoIncrementTest.java | 4 +- .../id/SequenceHiLoGeneratorTest.java | 4 +- .../id/enhanced/OptimizerUnitTest.java | 9 +- .../enhanced/SequenceStyleConfigUnitTest.java | 36 +- .../org/hibernate/jdbc/LobCreatorTest.java | 10 +- .../binding/AbstractBasicBindingTests.java | 206 - .../EntityWithBasicCollections.hbm.xml | 24 - .../metamodel/binding/package-info.java | 4 - .../internal/source/AssertSourcesTest.java | 227 + .../internal => internal/source}/Foo.java | 2 +- .../source}/MetadataImplTest.java | 31 +- .../metamodel/internal/source/Order.java | 75 + .../source/OrderWithNonEmbeddedId.java | 64 + .../SessionFactoryBuilderImplTest.java | 5 +- .../source}/SimpleEntity.java | 2 +- .../metamodel/internal/source/User.java | 140 + .../annotations/entity/AccessBindingTest.java | 53 +- .../entity/BatchSizeBindingTest.java | 6 +- .../annotations/entity/CacheBindingTest.java | 8 +- .../entity/CustomSQLBindingTest.java | 8 +- .../entity/ElementCollectionBindingTest.java | 241 ++ .../entity/EmbeddableBindingTest.java | 128 +- .../annotations/entity/EmbeddedIdTest.java | 53 +- .../entity/EnumeratedBindingTest.java | 15 +- .../annotations/entity/GenericTest.java | 105 + .../entity/IdentifierGeneratorTest.java | 29 +- .../entity/InheritanceBindingTest.java | 174 +- .../annotations/entity/LobBindingTests.java | 11 +- .../entity/MappedSuperclassTest.java | 62 +- .../source/annotations/entity/MapsIdTest.java | 20 +- .../entity/NaturalIdBindingTests.java | 192 + .../entity/OneToManyBindingTest.java | 63 + .../annotations/entity/ProxyBindingTest.java | 8 +- .../entity/QuotedIdentifierTest.java | 14 +- .../annotations/entity/RowIdBindingTests.java | 6 +- .../entity/SecondaryTableTest.java | 43 +- .../entity/SynchronizeBindingTest.java | 26 +- .../annotations/entity/TableNameTest.java | 20 +- .../entity/TemporalBindingTest.java | 29 +- .../entity/UniqueConstraintBindingTest.java | 129 + .../entity/VersionBindingTests.java | 140 + .../annotations/entity/WhereClauseTest.java | 6 +- .../global/FetchProfileBinderTest.java | 39 +- .../annotations/global/QueryBinderTest.java | 51 +- .../util/BaseAnnotationIndexTestCase.java | 29 +- .../util/EmbeddableHierarchyTest.java | 12 +- .../annotations/util/EntityHierarchyTest.java | 10 +- .../util/GenericTypeDiscoveryTest.java | 4 +- .../annotations/util/JandexHelperTest.java | 119 +- .../annotations/util/TypeDiscoveryTest.java | 4 +- .../source/annotations/xml/Father.java | 2 +- .../annotations/xml/OrmXmlParserTests.java | 22 +- .../source/annotations/xml/Star.java | 2 +- .../xml/mocker/AbstractMockerTest.java | 37 +- .../source/annotations/xml/mocker/Author.java | 2 +- .../xml/mocker/BasicMockerTest.java | 12 +- .../source/annotations/xml/mocker/Book.java | 2 +- .../DefaultConfigurationHelperTest.java | 9 +- .../xml/mocker/EntityListenerTest.java | 8 +- .../xml/mocker/IndexBuilderTest.java | 2 +- .../source/annotations/xml/mocker/Item.java | 2 +- .../annotations/xml/mocker/ItemListener.java | 2 +- .../annotations/xml/mocker/OverrideTest.java | 6 +- .../mocker/PersistenceMetadataMockerTest.java | 4 +- .../source/annotations/xml/mocker/Topic.java | 2 +- .../annotations/xml/mocker/XmlHelper.java | 8 +- .../source}/package-info.java | 2 +- .../entity/UniqueConstraintBindingTest.java | 79 - .../binding/AbstractBasicBindingTests.java | 310 ++ .../binding/AbstractUnsavedValueTests.java | 209 + .../binding/BasicAnnotationBindingTests.java | 12 +- .../binding/BasicHbmBindingTests.java | 19 +- .../binding/EntityWithManyToOnes.java} | 29 +- .../EntityWithUnidirectionalManyToMany.java} | 39 +- .../binding/JoinedSubclassBindingTests.java | 79 + .../{ => spi}/binding/SimpleEntity.java | 2 +- .../binding/SimpleEntitySubClass.java | 2 +- .../SimpleEntityWithSimpleComponent.java | 2 +- .../binding/SimpleValueBindingTests.java | 69 +- .../binding/SimpleVersionedEntity.java | 2 +- ...UnidirectionalManyToManyBindingTests.java} | 46 +- .../binding/UnsavedValueAnnotationsTests.java | 50 + .../spi/binding/UnsavedValueHbmTests.java | 108 + .../AbstractBasicCollectionBindingTests.java | 234 ++ ...nnotationBasicCollectionBindingTests.java} | 22 +- .../EntityWithBasicCollections.java | 131 + .../HbmBasicCollectionBindingTests.java} | 12 +- ...ctUnidirectionalOneToManyBindingTests.java | 252 ++ ...nUnidirectionalOneToManyBindingTests.java} | 21 +- .../EntityWithUnidirectionalOneToMany.java | 105 + ...bmUnidirectionalOneToManyBindingTests.java | 37 + .../binding/onetomany/ReferencedEntity.java | 56 + .../metamodel/spi/binding/package-info.java | 4 + .../AbstractGeneratedIdColumnTests.java | 187 + .../spi/relational/ColumnAliasTest.java | 278 ++ .../GeneratedIdColumnAnnotationsTests.java | 63 + .../relational/GeneratedIdColumnHbmTests.java | 55 + .../{ => spi}/relational/ObjectNameTests.java | 23 +- .../relational/TableManipulationTests.java | 112 +- .../SessionFactorySerializationTest.java | 11 + .../AbstractComponentPropertyRefTest.java | 2 + .../test/annotations/EntityTest.java | 29 +- .../test/annotations/access/Closet.java | 2 +- .../access/jpa/AccessMappingTest.java | 6 + .../annotations/access/jpa/Gardenshed.java | 2 +- .../annotations/access/xml/XmlAccessTest.java | 6 + .../test/annotations/any/AnyTest.java | 2 + .../BeanValidationAutoTest.java | 2 + .../BeanValidationDisabledTest.java | 23 +- .../BeanValidationGroupsTest.java | 3 + .../BeanValidationProvidedFactoryTest.java | 2 + .../annotations/beanvalidation/DDLTest.java | 115 +- .../DDLWithoutCallbackTest.java | 2 + .../HibernateTraversableResolverTest.java | 2 + .../test/annotations/cid/CompositeIdTest.java | 6 + .../test/annotations/cid/ParentPk.java | 3 +- .../CollectionElementTest.java | 72 +- .../EntityWithAnElementCollection.java | 3 +- .../collectionelement/OrderByTest.java | 9 +- .../collectionelement/Widgets.java | 18 +- .../IndexedCollectionOfElementsTest.java | 2 + .../indexedCollection/Sale.java | 3 +- .../collectionelement/ordered/Person.java | 14 +- .../derivedidentities/MedicalHistory.java | 2 +- ...ntityWithBidirectionalAssociationTest.java | 10 +- ...vedIdentitySimpleParentIdClassDepTest.java | 13 +- ...IdentitySimpleParentEmbeddedIdDepTest.java | 23 +- .../b/specjmapid/IdMapManyToOneSpecjTest.java | 2 + .../lazy/CompositeKeyDeleteTest.java | 2 + .../IdClassGeneratedValueManyToOneTest.java | 2 + ...edIdentitySimpleParentEmbeddedDepTest.java | 10 +- ...edIdentityIdClassParentIdClassDepTest.java | 31 +- ...dentityIdClassParentEmbeddedIdDepTest.java | 25 +- ...edIdentityEmbeddedIdParentIdClassTest.java | 24 +- ...tityEmbeddedIdParentEmbeddedIdDepTest.java | 23 +- ...ivedIdentitySimpleParentSimpleDepTest.java | 20 +- ...entitySimpleParentSimpleDepMapsIdTest.java | 22 +- ...IdClassParentSameIdTypeIdClassDepTest.java | 28 +- ...lassParentSameIdTypeEmbeddedIdDepTest.java | 19 +- .../derivedidentities/e5/b/PersonId.java | 2 + .../e5/c/ForeignGeneratorViaMapsIdTest.java | 10 +- ...eddedIdParentSameIdTypeIdClassDepTest.java | 18 +- ...edIdParentSameIdTypeEmbeddedIdDepTest.java | 18 +- .../embeddables/InvestorIntegrator.java | 2 +- .../annotations/embedded/EmbeddedTest.java | 30 +- .../embedded/InternetFavorites.java | 6 +- ...NestedEmbeddableAttributeOverrideTest.java | 2 +- .../entity/BasicHibernateAnnotationsTest.java | 4 + ...NewCustomEntityMappingAnnotationsTest.java | 30 +- .../entitynonentity/EntityNonEntityTest.java | 2 + .../enumerated/EnumeratedTypeTest.java | 93 +- .../enumerated/ormXml/OrmXmlEnumTypeTest.java | 17 +- .../test/annotations/generics/Classes.java | 4 +- .../generics/EmbeddedGenericsTest.java | 3 +- .../annotations/generics/GenericsTest.java | 3 + .../GenericsInheritanceTest.java | 2 + .../hibernate/test/annotations/id/IdTest.java | 14 +- .../id/JoinColumnOverrideTest.java | 7 + .../test/annotations/id/sequences/IdTest.java | 19 +- .../id/sequences/JoinColumnOverrideTest.java | 7 + .../IdClassGeneratedValueTest.java | 3 + .../IdentifierCollectionTest.java | 2 + .../AlphabeticalIdManyToOneTest.java | 2 + .../index/jpa/AbstractJPAIndexTest.java | 202 +- .../indexcoll/IndexedCollectionTest.java | 37 +- .../annotations/indexcoll/MapKeyTest.java | 2 + .../JoinedSubclassAndSecondaryTable.java | 2 +- .../test/annotations/join/JoinTest.java | 49 +- .../lob/SerializableToBlobTypeTest.java | 66 +- .../test/annotations/manytomany/CatPk.java | 2 + .../manytomany/ManyToManyTest.java | 3 + .../annotations/manytoone/ManyToOneTest.java | 2 + .../ManyToOneReferencedColumnNameTest.java | 2 + .../ManyToOneWithFormulaTest.java | 4 + .../IntermediateMappedSuperclassTest.java | 2 + .../namingstrategy/NamingStrategyTest.java | 2 + .../annotations/notfound/NotFoundTest.java | 2 + .../annotations/onetomany/OneToManyTest.java | 32 +- .../annotations/onetomany/OrderByTest.java | 2 + .../onetoone/OneToOneErrorTest.java | 2 + .../annotations/onetoone/OneToOneTest.java | 48 +- .../OptionalOneToOneMappedByTest.java | 2 + .../AssociationOverrideSchemaTest.java | 40 +- .../override/AssociationOverrideTest.java | 33 +- .../override/AttributeOverrideTest.java | 9 +- .../annotations/persister/PersisterTest.java | 57 +- .../annotations/query/QueryAndSQLTest.java | 3 + .../ReferencedColumnNameTest.java | 5 +- .../test/annotations/strategy/Location.java | 3 + .../test/annotations/strategy/Storm.java | 2 + .../annotations/strategy/StrategyTest.java | 4 +- .../test/annotations/target/TargetTest.java | 4 +- .../tuplizer/DynamicComponentTuplizer.java | 17 +- .../tuplizer/DynamicEntityTuplizer.java | 29 +- .../annotations/tuplizer/TuplizerTest.java | 2 +- .../UniqueConstraintValidationTest.java | 7 + .../annotations/various/TimestampTest.java | 24 +- .../annotations/xml/ejb3/Ejb3XmlTest.java | 2 + .../org/hibernate/test/bidi/AuctionTest.java | 2 + .../cfg/cache/CacheConfigurationTest.java | 7 + .../GoofyPersisterClassProvider.java | 4 +- .../cid/CompositeIdWithGeneratorTest.java | 2 + ...rCollectionTypeAnnotationsVariantTest.java | 3 + .../UserCollectionTypeHbmVariantTest.java | 3 + ...rCollectionTypeAnnotationsVariantTest.java | 3 + ...rizedUserCollectionTypeHbmVariantTest.java | 3 + .../collection/idbag/PersistentIdBagTest.java | 2 + .../LazyAssociationNoCascadeTest.java | 2 + .../collection/map/PersistentMapTest.java | 2 + .../collection/map/hhh7557/EntityMapTest.java | 2 + .../collection/original/CollectionTest.java | 2 + .../common/BasicTestingJdbcServiceImpl.java | 114 +- .../component/basic2/ComponentJoinsTest.java | 1 + .../connections/SuppliedConnectionTest.java | 49 + .../test/constraint/ConstraintTest.java | 59 +- .../test/cuk/CompositePropertyRefTest.java | 2 + .../discriminator/SimpleInheritanceTest.java | 4 +- .../tuplizer/MyEntityTuplizer.java | 16 + .../ImprovedTuplizerDynamicEntityTest.java | 2 + .../tuplizer2/MyEntityTuplizer.java | 14 +- .../map/basic/DynamicClassTest.java | 2 + .../map/subclass/SubclassDynamicMapTest.java | 2 + .../AggregatedCollectionEventListener.java | 2 +- .../hibernate/test/events/CallbackTest.java | 2 +- .../test/events/ClearEventListenerTest.java | 2 +- .../TestAutoFlushBeforeQueryExecution.java | 2 +- ...TestCollectionInitializingDuringFlush.java | 2 +- .../test/formulajoin/FormulaJoinTest.java | 2 + .../test/hql/ASTParserLoadingTest.java | 2 + .../test/hql/BulkManipulationTest.java | 4 + .../test/hql/ClassicTranslatorTest.java | 2 + .../CriteriaClassicAggregationReturnTest.java | 2 + .../org/hibernate/test/hql/EJBQLTest.java | 2 + .../java/org/hibernate/test/hql/HQLTest.java | 2 + .../hibernate/test/hql/WithClauseTest.java | 3 + .../org/hibernate/test/idbag/IdBagTest.java | 2 + .../IdentifierPropertyReferencesTest.java | 2 + .../test/immutable/ImmutableTest.java | 2 + ...sformingClassLoaderInstrumentTestCase.java | 1 + ...SubclassWithExplicitDiscriminatorTest.java | 2 + ...SubclassWithImplicitDiscriminatorTest.java | 2 + .../hibernate/test/jpa/AbstractJPATest.java | 2 +- .../component/EagerKeyManyToOneTest.java | 4 +- .../bidir/component/LazyKeyManyToOneTest.java | 2 + .../bidir/embedded/KeyManyToOneTest.java | 2 + .../KeyManyToOneCascadeDeleteTest.java | 2 + .../KeyManyToOneCascadeDeleteTest.java | 2 + .../org/hibernate/test/legacy/ABCTest.java | 32 +- .../test/legacy/ComponentNotNullTest.java | 2 + .../hibernate/test/legacy/CustomSQLTest.java | 2 + .../org/hibernate/test/legacy/FooBarTest.java | 2 + .../org/hibernate/test/legacy/FumTest.java | 2 + .../org/hibernate/test/legacy/MapTest.java | 2 + .../test/legacy/MasterDetailTest.java | 23 +- .../test/legacy/ParentChildTest.java | 3 +- ...positeAttributeResultSetProcessorTest.java | 11 +- ...atedCompositeIdResultSetProcessorTest.java | 2 + ...nLazyCollectionResultSetProcessorTest.java | 2 + ...zyOneToManyListResultSetProcessorTest.java | 2 + ...azyOneToManySetResultSetProcessorTest.java | 2 + ...atedCompositeIdResultSetProcessorTest.java | 2 + .../walking/KeyManyToOneWalkingTest.java | 2 + .../walking/NestedCompositeElementTest.java | 10 +- .../org/hibernate/test/locale/LocaleTest.java | 22 +- ...ToManyAssociationClassGeneratedIdTest.java | 4 + .../org/hibernate/test/mapping/AliasTest.java | 37 +- .../mapping/MappingReorderedAliasTest.java | 3 + .../namingstrategy/NamingStrategyTest.java | 64 +- .../nationalized/SimpleNationalizedTest.java | 6 + .../spread/SpreadNaturalIdTest.java | 6 + .../onetoone/formula/OneToOneFormulaTest.java | 2 + .../nopojo/DynamicMapOneToOneTest.java | 2 + .../org/hibernate/test/ops/SimpleOpsTest.java | 3 +- .../test/propertyref/DoesNotWorkTest.java | 2 +- .../propertyref/DoesNotWorkWithHbmTest.java | 2 + .../propertyref/basic/PropertyRefTest.java | 47 +- .../joined/JoinedSubclassPropertyRefTest.java | 2 + .../hibernate/test/quote/QuoteGlobalTest.java | 59 +- .../org/hibernate/test/quote/QuoteTest.java | 13 +- .../test/service/TestIntegrator.java | 2 +- .../sql/hand/query/NativeSQLQueriesTest.java | 2 + .../hibernate/test/ternary/TernaryTest.java | 2 + .../java/org/hibernate/test/tm/CMTTest.java | 2 + .../test/type/AttributeConverterTest.java | 30 + .../typedmanytoone/TypedManyToOneTest.java | 2 + .../test/unconstrained/UnconstrainedTest.java | 2 + .../org/hibernate/test/util/SchemaUtil.java | 117 +- .../metamodel/internal/source/User.hbm.xml | 44 + .../xml/mocker/AttributeOverride.xml | 6 +- .../annotations/xml/mocker/default-schema.xml | 4 +- .../xml/mocker/default-schema2.xml | 6 +- .../xml/mocker/entity-metadata-complete.xml | 6 +- .../annotations/xml/mocker/listener.xml | 6 +- .../mocker/override-to-mappedsuperclass.xml | 2 +- .../xml/mocker/persistence-metadata.xml | 2 +- .../source/annotations/xml/orm-father.xml | 2 +- .../source/annotations/xml/orm-invalid.xml | 2 +- .../annotations/xml/orm-quote-identifier.xml | 0 .../source/annotations/xml/orm-star.xml | 2 +- .../spi/binding/EntityWithManyToOnes.hbm.xml} | 7 +- ...ntityWithUnidirectionalManyToManys.hbm.xml | 26 + .../spi}/binding/SimpleEntity.hbm.xml | 13 +- .../SimpleEntityWithSimpleComponent.hbm.xml | 2 +- .../binding/SimpleVersionedEntity.hbm.xml | 2 +- .../spi}/binding/SimpleVersionedEntity.xml | 2 +- .../spi/binding/UnsavedDefaultValues.hbm.xml | 26 + .../binding/UnsavedNonDefaultValues.hbm.xml | 27 + .../EntityWithBasicCollections.hbm.xml | 43 + .../EntityWithUnidirectionalOneToMany.hbm.xml | 36 + .../onetomany/ReferencedEntity.hbm.xml | 13 + .../spi/relational/GeneratedIdColumn.hbm.xml | 27 + .../EntityManagerFactoryBuilderImpl.java | 6 +- .../boot/internal/PersistenceXmlParser.java | 2 +- .../internal/jpa/CallbackProcessorImpl.java | 60 +- .../jpa/event/spi/JpaIntegrator.java | 4 +- .../internal/EntityManagerMessageLogger.java | 12 - .../PersisterClassProviderTest.java | 4 +- .../FailureExpectedWithNewMetamodel.java | 49 + .../BaseAnnotationBindingTestCase.java | 47 +- .../junit4/BaseCoreFunctionalTestCase.java | 71 +- .../testing/junit4/BaseUnitTestCase.java | 11 + .../junit4/BeforeClassCallbackHandler.java | 16 +- .../testing/junit4/CustomRunner.java | 65 +- .../junit4/FailureExpectedHandler.java | 6 + .../hibernate/testing/junit4}/Resources.java | 2 +- libraries.gradle | 8 +- 1082 files changed, 69831 insertions(+), 22634 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/TruthValue.java create mode 100644 hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java create mode 100644 hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java create mode 100644 hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java create mode 100644 hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/{internal/LobCreatorBuilder.java => env/internal/LobCreatorBuilderImpl.java} (81%) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/{ => env}/spi/ExtractedDatabaseMetaData.java (77%) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java create mode 100644 hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/internal/AbstractJaxbProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbConfigurationProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbMappingProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/internal/LegacyJPAEventReader.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/internal/NamespaceAddingEventReader.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/package-info.java rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb => jaxb/spi}/JaxbRoot.java (93%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb => jaxb/spi}/Origin.java (71%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb => jaxb/spi}/SourceType.java (97%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping/hbm/CustomSqlElement.java => jaxb/spi/hbm/ComponentSourceElement.java} (79%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/EntityElement.java (63%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/IdBagPluralAttributeElementAdapter.java (97%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/JoinElementSource.java (96%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/MetaAttributeContainer.java (96%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/PluralAttributeElement.java (82%) create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/QuerySourceElement.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ReturnElement.java rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/SingularAttributeSource.java (96%) rename hibernate-core/src/main/java/org/hibernate/{internal/jaxb/mapping => jaxb/spi}/hbm/SubEntityElement.java (95%) create mode 100644 hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/TableInformationSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractAttribute.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractIdentifiableType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractManagedType.java rename hibernate-core/src/main/java/org/hibernate/{metamodel/relational/SimpleValue.java => jpa/metamodel/internal/AbstractType.java} (56%) create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/BasicTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EmbeddableTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EntityTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/JpaMetaModelPopulationSetting.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MappedSuperclassTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MetamodelImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/PluralAttributeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/SingularAttributeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/UnsupportedFeature.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeMetadata.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeTypeDescriptor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/BaseAttributeMetadata.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MemberResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MetamodelBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadata.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadataImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadata.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadataImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractAttribute.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractIdentifiableType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractManagedType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeFactory.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeImplementor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/BasicTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EmbeddableTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EntityTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MappedSuperclassTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetadataContext.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetamodelImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/PluralAttributeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/SingularAttributeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/jpa/metamodel/package-info.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/CollectionTableNamingStrategyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/ColumnNamingStrategyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/ColumnRelationalState.java => internal/DefaultColumnNamingStrategyHelper.java} (59%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityHierarchyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/HelperContext.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/HibernateTypeHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/LocalBindingContextManagerImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManyToManyCollectionTableNamingStrategyHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source => }/internal/MetadataBuilderImpl.java (71%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalIdentifierHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalValueBindingHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/SourceIndex.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableNamingStrategyHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/internal => internal/source}/OverriddenMappingDefaults.java (90%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/entity/UniqueConstraintSourceImpl.java => internal/source/annotations/AbstractConstraintSource.java} (71%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractManyToManyPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAssociationElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeIndexSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractToOneAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationAttributeSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContext.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/AnnotationBindingContextImpl.java (61%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationMetadataSourceProcessorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeIndexSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ColumnSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ComponentAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeIndexSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute => internal/source/annotations}/DerivedValueSourceImpl.java (84%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute => internal/source/annotations}/DiscriminatorSourceImpl.java (68%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/EntityHierarchyImpl.java (74%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FetchProfileSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterDefinitionSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/HibernateTypeSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/PluralAttributeNature.java => internal/source/annotations/IdentifierGeneratorSourceContainer.java} (63%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainerImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/InLineViewSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexConstraintSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexedPluralAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JpaCallbackSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToAnyPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyMappedByPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MapKeyPluralAttributeIndexSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MutliTenancySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyMappedByPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/RootEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SequentialPluralAttributeIndexSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute => internal/source/annotations}/SimpleIdentifierSourceImpl.java (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SingularAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SizeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SourceHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/AnnotationBindingContext.java => internal/source/annotations/SubclassEntitySourceImpl.java} (61%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TableSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneMappedByAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TypeDescriptorSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute/type/AbstractAttributeTypeResolver.java => internal/source/annotations/UniqueConstraintSourceImpl.java} (52%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/UnknownInheritanceTypeException.java (95%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/VersionAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AbstractOverrideDefinition.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute/AttributeNature.java => internal/source/annotations/attribute/AssociationOverride.java} (55%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AttributeOverride.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/attribute/BasicAttribute.java (59%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/attribute/ColumnValues.java => internal/source/annotations/attribute/Column.java} (71%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/FormulaValue.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PrimaryKeyJoinColumn.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SingularAssociationAttribute.java create mode 100755 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/package.html create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AbstractAttributeTypeResolver.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/attribute/type/AttributeTypeResolver.java (70%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/attribute/type/CompositeAttributeTypeResolver.java (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/EnumeratedTypeResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/HibernateTypeResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/LobTypeResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/TemporalTypeResolver.java create mode 100755 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/package.html create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableClass.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/EmbeddableHierarchy.java (61%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/EntityBindingContext.java (67%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclass.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java create mode 100755 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/package.html rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/global/FetchProfileBinder.java => internal/source/annotations/global/FetchProfileProcessor.java} (67%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/IdGeneratorProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/QueryProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/SqlResultSetProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java create mode 100755 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/package.html create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/AnnotationParserHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/ClassmateHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations => internal/source/annotations/util}/EntityHierarchyBuilder.java (66%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations => internal/source/annotations/util}/EnumConversionHelper.java (59%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations => internal/source/annotations/util}/HibernateDotNames.java (87%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations => internal/source/annotations/util}/JPADotNames.java (89%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPAListenerHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations => internal/source/annotations/util}/JandexHelper.java (57%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/MappingAssertion.java create mode 100755 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/package.html rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/PseudoJpaDotNames.java (97%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/filter/AbstractAnnotationFilter.java (94%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/filter/ExclusiveAnnotationFilter.java (91%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/filter/IndexedAnnotationFilter.java (86%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/filter/NameAnnotationFilter.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/filter/NameTargetAnnotationFilter.java (59%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AbstractAttributesBuilder.java (61%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AbstractEntityObjectMocker.java (64%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AbstractMocker.java (58%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AccessHelper.java (85%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AnnotationMocker.java (80%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesContainer.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/BasicMocker.java (72%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/DefaultConfigurationHelper.java (77%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/ElementCollectionMocker.java (56%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EmbeddableMocker.java (61%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EmbeddedIdMocker.java (74%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EmbeddedMocker.java (69%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityElement.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EntityMappingsMocker.java (90%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EntityMocker.java (65%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/GlobalAnnotationMocker.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/GlobalAnnotations.java (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/IdMocker.java (71%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/IndexBuilder.java (83%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Listener.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/ListenerMocker.java (55%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/ManyToManyMocker.java (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/ManyToOneMocker.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/MappedSuperclassMocker.java (70%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/MockHelper.java (88%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/OneToManyMocker.java (63%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/OneToOneMocker.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/PersistenceMetadataMocker.java (89%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyElement.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/PropertyMocker.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/Sortable.java => internal/source/annotations/xml/mocker/SchemaAware.java} (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/TransientMocker.java (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/VersionMocker.java (70%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractComponentAttributeSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/entity/TableSourceImpl.java => internal/source/hbm/AbstractConstraintSource.java} (50%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractHbmSourceNode.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAssociationElementSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/AbstractPluralAttributeSourceImpl.java (58%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractReturnBinder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ArraySourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/hbm/BagAttributeSourceImpl.java => internal/source/hbm/BagSourceImpl.java} (69%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/BasicPluralAttributeElementSourceImpl.java (54%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/ColumnAttributeSourceImpl.java (58%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/ColumnSourceImpl.java (58%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ComponentAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeIndexSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/EntityHierarchyImpl.java (85%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FetchProfileSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterDefinitionSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/FormulaImpl.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/HbmBindingContext.java (80%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmMetadataSourceProcessorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/Helper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HibernateMappingProcessor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HierarchyBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/InLineViewSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IndexConstraintSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ListSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/LoadCollectionBinder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapKeySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/MappingDocument.java (81%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/NamedQueryBindingHelper.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/OneToManyPluralAttributeElementSourceImpl.java (60%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/PluralAttributeKeySourceImpl.java (51%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/PropertyAttributeSourceImpl.java (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ResultSetMappingBinder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnBinder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnJoinBinder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SequentialPluralAttributeIndexSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/hbm/SetAttributeSourceImpl.java => internal/source/hbm/SetSourceImpl.java} (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/SingularIdentifierAttributeSourceImpl.java (66%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SizeSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SubclassEntitySourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TableSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/TimestampAttributeSourceImpl.java (64%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{domain/PluralAttributeNature.java => internal/source/hbm/TypeDescriptorSourceImpl.java} (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UnexpectedAttributeSourceTypeException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UniqueConstraintSourceImpl.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => internal}/source/hbm/VersionAttributeSourceImpl.java (64%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/AbstractQueryElementContentsParser.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/BasicQueryElementContentParser.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/SQLQueryElementContentParser.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source => spi}/MetadataSourceProcessor.java (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/AbstractAttributeBinding.java (73%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/AttributeBinding.java (76%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/AbstractCollectionElement.java => spi/binding/BagBinding.java} (58%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/Caching.java (98%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/CascadeType.java (99%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/RelationalValueSource.java => spi/binding/Cascadeable.java} (72%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/CollectionLaziness.java (96%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/CompositeCollectionElement.java => spi/binding/CompositeAttributeBindingContainer.java} (69%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/CustomSQL.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/EntityDiscriminator.java (78%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/FetchProfile.java (98%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/AssociationAttributeSource.java => spi/binding/Fetchable.java} (68%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{domain/PluralAttribute.java => spi/binding/Filterable.java} (75%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/Helper.java (88%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/HibernateTypeDescriptor.java (75%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/HierarchyDetails.java (80%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/InheritanceType.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/KeyValueBinding.java (96%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToAnyPluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/MetaAttribute.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToManyPluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/PluralAttributeBinding.java (64%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/SetBinding.java (65%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/binding/SingularAssociationAttributeBinding.java (66%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/Orderable.java => spi/binding/SingularNonAssociationAttributeBinding.java} (83%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/AbstractAttributeContainer.java (76%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{domain/Component.java => spi/domain/Aggregate.java} (77%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/Attribute.java (75%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/AttributeContainer.java (83%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/BasicType.java (95%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/Entity.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/Hierarchical.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/IndexedPluralAttribute.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/JavaType.java (98%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/NonEntity.java (96%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/SingularAttribute.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/Superclass.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/Type.java (88%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/TypeNature.java (92%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/domain/package.html (100%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/AbstractAuxiliaryDatabaseObject.java (87%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/AbstractSimpleValue.java => spi/relational/AbstractValue.java} (53%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/BasicAuxiliaryDatabaseObjectImpl.java (94%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/CheckConstraint.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Constraint.java (86%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/DerivedValue.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Exportable.java (70%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/BagBinding.java => spi/relational/ExportableProducer.java} (71%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/ForeignKey.java (71%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Identifier.java (53%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/IllegalIdentifierException.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/InLineView.java (87%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Index.java (51%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/Datatype.java => spi/relational/JdbcDataType.java} (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Loggable.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/ObjectName.java (69%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/PrimaryKey.java (75%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Sequence.java (58%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Size.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/TableSpecification.java (59%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/UniqueKey.java (75%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/Value.java (64%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/ValueContainer.java (87%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/relational/package.html (100%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/ComponentIdentifierSource.java => spi/source/AggregatedCompositeIdentifierSource.java} (72%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/annotations/entity/ConfiguredClassType.java => spi/source/AssociationPluralAttributeElementSource.java} (79%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeRelationalValueSourceContainer.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/AttributeSource.java (87%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/AttributeSourceContainer.java (91%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/CollectionElementNature.java => spi/source/AttributeSourceResolutionContext.java} (69%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/BasicPluralAttributeElementSource.java (83%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/SimpleValueRelationalState.java => spi/source/BasicPluralAttributeIndexSource.java} (83%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/BindingContext.java (92%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CascadeStyleSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnBindingDefaults.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ColumnSource.java (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ComponentAttributeSource.java (96%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositeIdentifierSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/CompositePluralAttributeElementSource.java (86%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeIndexSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ConstraintSource.java (89%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/DerivedValueSource.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/DiscriminatorSource.java (98%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityAttributePluralAttributeIndexSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/EntityHierarchy.java (91%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/EntitySource.java (89%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchProfileSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchableAttributeSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterDefinitionSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterParameterSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/ExplicitHibernateTypeSource.java => spi/source/HibernateTypeSource.java} (83%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierGeneratorSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/IdentifierSource.java (60%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InLineViewSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/TupleRelationalState.java => spi/source/IndexConstraintSource.java} (84%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/PluralAttributeElementNature.java => spi/source/IndexedPluralAttributeSource.java} (77%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/TypeDef.java => spi/source/InvalidMappingException.java} (58%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JoinedSubclassEntitySource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/JpaCallbackClass.java => spi/source/JpaCallbackSource.java} (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/LocalBindingContext.java (83%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ManyToAnyPluralAttributeElementSource.java (87%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ManyToManyPluralAttributeElementSource.java (77%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/ValueRelationalState.java => spi/source/MappedByAssociationSource.java} (83%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/MappingDefaults.java (92%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/MappingException.java (88%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/MappingNotFoundException.java (95%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/MetaAttributeContext.java (94%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/MetaAttributeSource.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MultiTenancySource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/OneToManyPluralAttributeElementSource.java (92%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Orderable.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{binding/BasicCollectionElement.java => spi/source/PluralAttributeElementSource.java} (66%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSourceResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/ManyToOneRelationalState.java => spi/source/PluralAttributeIndexSourceResolver.java} (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/PluralAttributeKeySource.java (78%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/PluralAttributeSource.java (57%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSourceContainer.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/RootEntitySource.java (83%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SecondaryTableSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{relational/state/DerivedValueRelationalState.java => spi/source/SequentialPluralAttributeIndexSource.java} (82%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/SimpleIdentifierSource.java (86%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/SingularAttributeSource.java (74%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SizeSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/RelationalValueSourceContainer.java => spi/source/Sortable.java} (66%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/SubclassEntityContainer.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/SubclassEntitySource.java (82%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/SingularAttributeNature.java => spi/source/TableSource.java} (77%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/TableSource.java => spi/source/TableSpecificationSource.java} (67%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/ToOneAttributeSource.java (62%) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSourceNatureResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TypeDescriptorSource.java rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder => spi/source}/UniqueConstraintSource.java (96%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{source/binder/PluralAttributeElementSource.java => spi/source/VersionAttributeSource.java} (82%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{ => spi}/source/XsdException.java (97%) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java rename hibernate-core/src/main/java/org/hibernate/{metamodel/source/annotations/attribute => tool/schema/extract}/package-info.java (83%) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java rename hibernate-core/src/main/java/org/hibernate/{metamodel/binding/ManyToAnyCollectionElement.java => tool/schema/spi/SchemaManagementException.java} (70%) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java rename hibernate-core/src/main/java/org/hibernate/{metamodel/relational/AuxiliaryDatabaseObject.java => tool/schema/spi/SchemaValidator.java} (60%) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml delete mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{source/internal => internal/source}/Foo.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{source/internal => internal/source}/MetadataImplTest.java (87%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{source/internal => internal/source}/SessionFactoryBuilderImplTest.java (97%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{source/internal => internal/source}/SimpleEntity.java (96%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/AccessBindingTest.java (72%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/BatchSizeBindingTest.java (89%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/CacheBindingTest.java (92%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/CustomSQLBindingTest.java (92%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/EmbeddableBindingTest.java (67%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/EmbeddedIdTest.java (58%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/EnumeratedBindingTest.java (84%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/IdentifierGeneratorTest.java (91%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/InheritanceBindingTest.java (85%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/LobBindingTests.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/MappedSuperclassTest.java (58%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/MapsIdTest.java (83%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/ProxyBindingTest.java (91%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/QuotedIdentifierTest.java (79%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/RowIdBindingTests.java (88%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/SecondaryTableTest.java (54%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/SynchronizeBindingTest.java (75%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/TableNameTest.java (80%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/TemporalBindingTest.java (84%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/entity/WhereClauseTest.java (70%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/global/FetchProfileBinderTest.java (72%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/global/QueryBinderTest.java (82%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/BaseAnnotationIndexTestCase.java (71%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/EmbeddableHierarchyTest.java (84%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/EntityHierarchyTest.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/GenericTypeDiscoveryTest.java (98%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/JandexHelperTest.java (63%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/util/TypeDiscoveryTest.java (97%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/Father.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/OrmXmlParserTests.java (78%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/Star.java (94%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AbstractMockerTest.java (89%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/Author.java (96%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/BasicMockerTest.java (91%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/Book.java (97%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java (96%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/EntityListenerTest.java (91%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/IndexBuilderTest.java (72%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/Item.java (94%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/ItemListener.java (94%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/OverrideTest.java (98%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java (92%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/Topic.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/XmlHelper.java (95%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{source/internal => internal/source}/package-info.java (96%) delete mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/BasicAnnotationBindingTests.java (88%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/BasicHbmBindingTests.java (73%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{binding/ManyToOneEntity.java => spi/binding/EntityWithManyToOnes.java} (70%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{binding/EntityWithBasicCollections.java => spi/binding/EntityWithUnidirectionalManyToMany.java} (61%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/SimpleEntity.java (97%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/SimpleEntitySubClass.java (96%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/SimpleEntityWithSimpleComponent.java (98%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/SimpleValueBindingTests.java (62%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/binding/SimpleVersionedEntity.java (97%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{binding/BasicCollectionBindingTests.java => spi/binding/UnidirectionalManyToManyBindingTests.java} (58%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java rename hibernate-core/src/{main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java => test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java} (70%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java rename hibernate-core/src/{main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java => test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java} (74%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java rename hibernate-core/src/{main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java => test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java} (72%) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/relational/ObjectNameTests.java (74%) rename hibernate-core/src/test/java/org/hibernate/metamodel/{ => spi}/relational/TableManipulationTests.java (52%) create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/AttributeOverride.xml (78%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/default-schema.xml (75%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/default-schema2.xml (50%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/entity-metadata-complete.xml (53%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/listener.xml (79%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/override-to-mappedsuperclass.xml (86%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/mocker/persistence-metadata.xml (93%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/orm-father.xml (84%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/orm-invalid.xml (85%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/orm-quote-identifier.xml (100%) rename hibernate-core/src/test/resources/org/hibernate/metamodel/{ => internal}/source/annotations/xml/orm-star.xml (86%) rename hibernate-core/src/test/{java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml => resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml} (62%) create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml rename hibernate-core/src/test/{java/org/hibernate/metamodel => resources/org/hibernate/metamodel/spi}/binding/SimpleEntity.hbm.xml (50%) rename hibernate-core/src/test/{java/org/hibernate/metamodel => resources/org/hibernate/metamodel/spi}/binding/SimpleEntityWithSimpleComponent.hbm.xml (92%) rename hibernate-core/src/test/{java/org/hibernate/metamodel => resources/org/hibernate/metamodel/spi}/binding/SimpleVersionedEntity.hbm.xml (92%) rename hibernate-core/src/test/{java/org/hibernate/metamodel => resources/org/hibernate/metamodel/spi}/binding/SimpleVersionedEntity.xml (92%) create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml create mode 100644 hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml create mode 100644 hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java rename {hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity => hibernate-testing/src/main/java/org/hibernate/testing/junit4}/BaseAnnotationBindingTestCase.java (70%) rename {hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity => hibernate-testing/src/main/java/org/hibernate/testing/junit4}/Resources.java (96%) diff --git a/build.gradle b/build.gradle index 777f41157f..22f1a1e8b6 100644 --- a/build.gradle +++ b/build.gradle @@ -137,6 +137,7 @@ subprojects { subProject -> dependencies { compile( libraries.logging ) compile( libraries.logging_annotations ) + compile( libraries.logging_processor ) testCompile( libraries.junit ) testCompile( libraries.byteman ) @@ -152,8 +153,11 @@ subprojects { subProject -> jaxb( libraries.jaxb ){ exclude group: "javax.xml.stream" } + jaxb( libraries.jaxb ) jaxb( libraries.jaxb2_basics ) jaxb( libraries.jaxb2_ant ) + jaxb( libraries.jaxb2_jaxb ) + jaxb( libraries.jaxb2_jaxb_xjc ) animalSniffer ( libraries.animal_sniffer ) javaApiSignature ( libraries.java16_signature ) diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle index 767113f03f..275b28bc9f 100644 --- a/hibernate-core/hibernate-core.gradle +++ b/hibernate-core/hibernate-core.gradle @@ -10,6 +10,7 @@ versionInjection { dependencies { compile( libraries.jta ) compile( libraries.dom4j ) + compile( libraries.classmate ) compile( libraries.commons_annotations ) compile( libraries.jpa ) compile( libraries.javassist ) @@ -21,7 +22,6 @@ dependencies { provided( libraries.ant ) provided( libraries.jacc ) provided( libraries.validation ) - provided( libraries.classmate ) testCompile( project(':hibernate-testing') ) testCompile( libraries.validation ) @@ -111,7 +111,7 @@ task jaxb { // input schemas cfgXsd = file( 'src/main/resources/org/hibernate/hibernate-configuration-4.0.xsd') hbmXsd = file( 'src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd' ) - ormXsd = file( 'src/main/resources/org/hibernate/jpa/orm_2_0.xsd' ) + ormXsd = file( 'src/main/resources/org/hibernate/jpa/orm_2_1.xsd' ) // input bindings cfgXjb = file( 'src/main/xjb/hbm-configuration-bindings.xjb' ) @@ -133,7 +133,7 @@ task jaxb { // hibernate-configuration ant.xjc( destdir: '${jaxbTargetDir}', - package: 'org.hibernate.internal.jaxb.cfg', + package: 'org.hibernate.jaxb.spi.cfg', binding: 'src/main/xjb/hbm-configuration-bindings.xjb', schema: cfgXsd.path ) @@ -141,21 +141,25 @@ task jaxb { // hibernate-mapping ant.xjc( destdir: '${jaxbTargetDir}', - package: 'org.hibernate.internal.jaxb.mapping.hbm', + package: 'org.hibernate.jaxb.spi.hbm', binding: hbmXjb.path, schema: hbmXsd.path, extension: 'true' ) { - arg line: '-Xinheritance' + arg line: '-Xinheritance -Xsimplify' } // orm.xml (jpa) ant.xjc( destdir: '${jaxbTargetDir}', - package: 'org.hibernate.internal.jaxb.mapping.orm', + package: 'org.hibernate.jaxb.spi.orm', binding: 'src/main/xjb/orm-bindings.xjb', - schema: ormXsd.path - ) + schema: ormXsd.path, + extension: 'true' + ) { + arg line: '-Xinheritance' + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/InvalidMappingException.java b/hibernate-core/src/main/java/org/hibernate/InvalidMappingException.java index 6a486a4050..096de671ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/InvalidMappingException.java +++ b/hibernate-core/src/main/java/org/hibernate/InvalidMappingException.java @@ -23,7 +23,7 @@ */ package org.hibernate; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.jaxb.spi.Origin; import org.hibernate.internal.util.xml.XmlDocument; /** diff --git a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java index b7ea97b8bd..c05946f6db 100644 --- a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java @@ -30,6 +30,8 @@ import java.util.Set; import javax.naming.Referenceable; import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.cfg.Settings; +import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; @@ -71,6 +73,12 @@ public interface SessionFactory extends Referenceable, Serializable { */ public Interceptor getInterceptor(); + public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy(); + public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver(); + public SessionFactoryObserver[] getSessionFactoryObservers(); + public EntityNameResolver[] getEntityNameResolvers(); + public Settings getSettings(); + /** * Get the delegate for handling entity-not-found exception conditions. * diff --git a/hibernate-core/src/main/java/org/hibernate/TruthValue.java b/hibernate-core/src/main/java/org/hibernate/TruthValue.java new file mode 100644 index 0000000000..cdb8946af7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/TruthValue.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate; + +/** + * An enumeration of truth values. + *

+ * Yes this *could* be handled with Boolean, but then you run into potential problems with premature + * auto-unboxing. + * + * @author Steve Ebersole + */ +public enum TruthValue { + TRUE, + FALSE, + UNKNOWN; + + public static boolean toBoolean(TruthValue value, boolean defaultValue) { + if ( value == TruthValue.TRUE ) { + return true; + } + if ( value == TruthValue.FALSE ) { + return false; + } + return defaultValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java b/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java new file mode 100644 index 0000000000..2e664acb53 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Annotation used to indicate that an entity represents shared (non tenant aware) data in a multi-tenant + * application. + * + * Valid only at the root of an inheritance hierarchy. + * + * @author Steve Ebersole + */ +@java.lang.annotation.Target(TYPE) +@Retention(RUNTIME) +public @interface MultiTenancy { + public boolean shared() default true; + + /** + * The discriminator values can be either be handled as literals or handled through JDBC parameter binding. + * {@code true} here (the default) indicates that the parameter binding approach should be used; {@code false} + * indicates the value should be handled as a literal. + *

+ * Care should be used specifying to use literals here. PreparedStatements will not be able to be reused + * nearly as often by the database/driver which can potentially cause a significant performance impact to your + * application. + */ + public boolean useParameterBinding() default true; +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java b/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java new file mode 100644 index 0000000000..eba993f110 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Describes the column to use as the multi-tenancy discriminator value for the entity. + * + * @author Steve Ebersole + */ +@java.lang.annotation.Target( TYPE ) +@Retention( RUNTIME ) +public @interface TenantColumn { + /** + * Name of the column to use. + */ + public String name(); + + /** + * (Optional) The name of the table that contains the column. If absent the column is assumed to be in the + * primary table. + */ + public String table() default ""; + + /** + * Names the Hibernate mapping type to use for mapping values to/from the specified column. Defaults to + * {@code "string"} which is a {@link String}/{@link java.sql.Types#VARCHAR VARCHAR} mapping. + */ + public String type() default "string"; + + /** + * (Optional) The column length. (Applies only if a string-valued column is used.) + */ + int length() default 255; + + /** + * (Optional) The precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.) + * Value must be set by developer if used when generating the DDL for the column. + */ + int precision() default 0; + + /** + * (Optional) The scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.) + */ + int scale() default 0; +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java b/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java new file mode 100644 index 0000000000..fd1cbd1117 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Describes a formula fragment to use as the multi-tenancy discriminator value for the entity. + * + * @author Steve Ebersole + * @see Formula + */ +@java.lang.annotation.Target(TYPE) +@Retention(RUNTIME) +public @interface TenantFormula { + /** + * The formula fragment. + */ + public String value(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java index 949be8967b..1401aab42b 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java @@ -34,7 +34,7 @@ import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.Environment; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.ConfigLoader; import org.hibernate.service.Service; diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java index d118018d1e..d41157435c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java @@ -140,7 +140,8 @@ public class StrategySelectorBuilder { throw new StrategySelectionException( "Implementation class [" + strategyRegistration.getStrategyImplementation().getName() + "] does not implement strategy interface [" - + strategyRegistration.getStrategyRole().getName() + "]" + + strategyRegistration.getStrategyRole().getName() + "]", + strategyRegistration.getStrategyImplementation().getName() ); } explicitStrategyRegistrations.add( strategyRegistration ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java index fd408184f8..14be66161c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java @@ -126,7 +126,8 @@ public class StrategySelectorImpl implements StrategySelector { } catch (ClassLoadingException e) { throw new StrategySelectionException( - "Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]" + "Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]", + name ); } } @@ -161,7 +162,8 @@ public class StrategySelectorImpl implements StrategySelector { catch (Exception e) { throw new StrategySelectionException( String.format( "Could not instantiate named strategy class [%s]", implementationClass.getName() ), - e + e, + implementationClass.getName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java index 118bda69a0..f5d3be94d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java @@ -31,13 +31,16 @@ import org.hibernate.HibernateException; * @author Steve Ebersole */ public class StrategySelectionException extends HibernateException { + + private final String implementationClassName; /** * Constructs a StrategySelectionException using the specified message. * * @param message A message explaining the exception condition. */ - public StrategySelectionException(String message) { + public StrategySelectionException(String message, String implementationClassName) { super( message ); + this.implementationClassName = implementationClassName; } /** @@ -46,7 +49,17 @@ public class StrategySelectionException extends HibernateException { * @param message A message explaining the exception condition. * @param cause The underlying cause. */ - public StrategySelectionException(String message, Throwable cause) { + public StrategySelectionException(String message, Throwable cause, String implementationClassName) { super( message, cause ); + this.implementationClassName = implementationClassName; + } + + /** + * Gets the selected implementation class involved with the exception. + * + * @return the implementation class name. + */ + public String getImplementationClassName() { + return implementationClassName; } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java new file mode 100644 index 0000000000..4838e12cc7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.boot.spi; + +/** + * Models the definition of caching settings for a particular region. Generally as found in either:

+ * Though certainly other custom sources are acceptable too. + * + * @author Steve Ebersole + */ +public class CacheRegionDefinition { + public static enum CacheRegionType { + ENTITY, + COLLECTION, + QUERY + } + + private final CacheRegionType regionType; + private final String role; + private final String usage; + private final String region; + private final boolean cacheLazy; + + public CacheRegionDefinition( + CacheRegionType cacheType, + String role, + String usage, + String region, + boolean cacheLazy) { + this.regionType = cacheType; + this.role = role; + this.usage = usage; + this.region = region; + this.cacheLazy = cacheLazy; + } + + public CacheRegionType getRegionType() { + return regionType; + } + + public String getRole() { + return role; + } + + public String getUsage() { + return usage; + } + + public String getRegion() { + return region; + } + + public boolean isCacheLazy() { + return cacheLazy; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java index e4917d1200..d29a511a80 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java @@ -28,8 +28,8 @@ import java.util.Comparator; import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.type.VersionType; /** @@ -134,7 +134,7 @@ public class CacheDataDescriptionImpl implements CacheDataDescription { private static Comparator getVersionComparator(EntityBinding model ) { if ( model.isVersioned() ) { final VersionType versionType = (VersionType) model.getHierarchyDetails() - .getVersioningAttributeBinding() + .getEntityVersion().getVersioningAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping(); diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java index 637776f2ef..1a04d36189 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java @@ -39,7 +39,7 @@ import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.spi.SessionFactoryServiceRegistry; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 7aa0874c95..bee2baa4f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -636,7 +636,51 @@ public interface AvailableSettings { */ String IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.ignore_explicit_for_joined"; - String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans"; + /** + * Names a {@link org.hibernate.Interceptor} implementation to be applied to the {@link org.hibernate.SessionFactory} + * Can reference + * + * @since 5.0 + */ + String INTERCEPTOR = "hibernate.sessionFactory.interceptor"; + + /** + * Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts + * 3 values: + */ + public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population"; + + /** + * Used to specify the {@link org.hibernate.tool.schema.spi.SchemaManagementTool} to use for performing + * schema management. The default is to use {@link org.hibernate.tool.schema.internal.HibernateSchemaManagementTool} + * + * @since 5.0 + */ + String SCHEMA_MANAGEMENT_TOOL = "hibernate.schema_management_tool"; + + /** + * A constant naming the setting used to identify the {@link org.hibernate.engine.jdbc.spi.SchemaNameResolver} to use + *

+ * TODO : add to Environment + */ + String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver"; + + String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans"; String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy"; @@ -701,6 +745,15 @@ public interface AvailableSettings { */ String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy"; + /** + * If enabled, an entity's member field types and method return types will automatically be indexed. This allows, + * for example, auto-discovery of @Embeddables without explicitly listing them in the annotated classes. This + * setting will also check classes identified by certain annotations (such as @Target). JPA requires these classes + * to be identified in the annotated classes, however legacy Hibernate behavior was to allow it. Due to the + * performance hit, disabled by default. + */ + String ENABLE_AUTO_INDEX_MEMBER_TYPES = "hibernate.enable_auto_index_member_types"; + /** * A setting to control whether to {@link org.hibernate.engine.internal.StatisticalLoggingSessionEventListener} is * enabled on all Sessions (unless explicitly disabled for a given Session). The default value of this diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java index a3922b0c56..1dd425a3a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * The default NamingStrategy @@ -93,6 +96,22 @@ public class DefaultNamingStrategy implements NamingStrategy, Serializable { if (header == null) throw new AssertionFailure("NammingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java index 25d1c2bce2..31068fb37a 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java @@ -23,9 +23,12 @@ */ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * Naming strategy implementing the EJB3 standards @@ -76,6 +79,22 @@ public class EJB3NamingStrategy implements NamingStrategy, Serializable { if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } public String logicalColumnName(String columnName, String propertyName) { return StringHelper.isNotEmpty( columnName ) ? columnName : StringHelper.unqualify( propertyName ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java index 949459ae03..74c0ba5301 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java @@ -1724,8 +1724,8 @@ public final class HbmBinder { oneToOne.setConstrained( constrained ); oneToOne.setForeignKeyType( constrained ? - ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); + ForeignKeyDirection.FROM_PARENT : + ForeignKeyDirection.TO_PARENT ); initOuterJoinFetchSetting( node, oneToOne ); initLaziness( node, oneToOne, mappings, true ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java index b9be3483c7..f794d64bd9 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * An improved naming strategy that prefers embedded @@ -106,6 +109,22 @@ public class ImprovedNamingStrategy implements NamingStrategy, Serializable { if (header == null) throw new AssertionFailure("NamingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java index c78e0f2f03..e4be023d9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java @@ -23,6 +23,8 @@ */ package org.hibernate.cfg; +import java.util.List; + /** * A set of rules for determining the physical column @@ -37,6 +39,7 @@ package org.hibernate.cfg; * @see ImprovedNamingStrategy * @author Gavin King * @author Emmanuel Bernard + * @author Brett Meyer */ public interface NamingStrategy { /** @@ -93,6 +96,33 @@ public interface NamingStrategy { public String foreignKeyColumnName( String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName ); + /** + * Return a constraint name for foreign keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The foreign key's source table + * @param columnNames The source columns within the foreign key + * @param tableName The foreign key's target table + * @param columnNames The target columns within the foreign key + * @return The generated foreign key constraint name + */ + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames); + /** + * Return a constraint name for unique keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The unique key's table + * @param columnNames The columns within the unique key + * @return The generated unique key constraint name + */ + public String uniqueKeyName(String tableName, List columnNames); + /** + * Return a constraint name for indexes that are not explicitly named in the mappings/annotations. + * + * @param tableName The index's table + * @param columnNames The columns within the index + * @return The generated index constraint name + */ + public String indexName(String tableName, List columnNames); /** * Return the logical column name used to refer to a column in the metadata * (like index, unique constraints etc) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java b/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java index d374505df2..c5f533b250 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java @@ -56,6 +56,10 @@ public abstract class ObjectNameNormalizer { public String handleExplicitName(NamingStrategy strategy, String name); } + public static interface LogicalNamingStrategyHelper extends NamingStrategyHelper{ + public String getLogicalName(NamingStrategy strategy); + } + /** * Performs the actual contract of normalizing a database name. * @@ -78,7 +82,6 @@ public abstract class ObjectNameNormalizer { // handle any quoting for consistent handling in naming strategies objectName = normalizeIdentifierQuoting( explicitName ); objectName = helper.handleExplicitName( getNamingStrategy(), objectName ); - return normalizeIdentifierQuoting( objectName ); } // Conceivable that the naming strategy could return a quoted identifier, or // that user enabled diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java index cf2a410d09..4df180aa33 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java @@ -106,8 +106,8 @@ public class OneToOneSecondPass implements SecondPass { if ( !optional ) value.setConstrained( true ); value.setForeignKeyType( value.isConstrained() ? - ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT + ForeignKeyDirection.FROM_PARENT : + ForeignKeyDirection.TO_PARENT ); PropertyBinder binder = new PropertyBinder(); binder.setName( propertyName ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java index e02a9db459..6312b58da0 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java @@ -42,7 +42,7 @@ import org.hibernate.cache.spi.QueryCacheFactory; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.engine.transaction.spi.TransactionFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java index 5ca1b6b5ca..ef34686ea1 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java @@ -33,7 +33,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 4a1787d150..4b0768b5a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -80,6 +80,11 @@ import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.io.StreamCopier; import org.hibernate.mapping.Column; import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.persister.entity.Lockable; import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; @@ -89,6 +94,13 @@ import org.hibernate.sql.ANSIJoinFragment; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.ForUpdateFragment; import org.hibernate.sql.JoinFragment; +import org.hibernate.tool.schema.internal.StandardAuxiliaryDatabaseObjectExporter; +import org.hibernate.tool.schema.internal.StandardForeignKeyExporter; +import org.hibernate.tool.schema.internal.StandardIndexExporter; +import org.hibernate.tool.schema.internal.StandardSequenceExporter; +import org.hibernate.tool.schema.internal.StandardTableExporter; +import org.hibernate.tool.schema.internal.TemporaryTableExporter; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.ClobTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -1965,6 +1977,37 @@ public abstract class Dialect implements ConversionContext { // DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + private StandardTableExporter tableExporter = new StandardTableExporter( this ); + private StandardSequenceExporter sequenceExporter = new StandardSequenceExporter( this ); + private StandardIndexExporter indexExporter = new StandardIndexExporter( this ); + private StandardForeignKeyExporter foreignKeyExporter = new StandardForeignKeyExporter( this ); + private StandardAuxiliaryDatabaseObjectExporter auxiliaryObjectExporter = new StandardAuxiliaryDatabaseObjectExporter( this ); + private TemporaryTableExporter temporaryTableExporter = new TemporaryTableExporter( this ); + + public Exporter getTableExporter() { + return tableExporter; + } + + public Exporter
getTemporaryTableExporter() { + return temporaryTableExporter; + } + + public Exporter getSequenceExporter() { + return sequenceExporter; + } + + public Exporter getIndexExporter() { + return indexExporter; + } + + public Exporter getForeignKeyExporter() { + return foreignKeyExporter; + } + + public Exporter getAuxiliaryDatabaseObjectExporter() { + return auxiliaryObjectExporter; + } + /** * Get the SQL command used to create the named schema * @@ -1987,6 +2030,15 @@ public abstract class Dialect implements ConversionContext { return "drop schema " + schemaName; } + /** + * Get the SQL command used to retrieve the current schema name + * + * @return The current schema retrieval SQL + */ + public String getCurrentSchemaCommand() { + return null; + } + /** * Does this dialect support the ALTER TABLE syntax? * diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index d5cec3633b..3a3d78142a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -427,4 +427,9 @@ public class H2Dialect extends Dialect { public boolean supportsTuplesInSubqueries() { return false; } + + @Override + public String getCurrentSchemaCommand() { + return "call schema()"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index 9720ce3ab9..fe0e179f40 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -620,4 +620,9 @@ public class Oracle8iDialect extends Dialect { // Oracle supports returning cursors return StandardCallableStatementSupport.REF_CURSOR_INSTANCE; } + + @Override + public String getCurrentSchemaCommand() { + return "select sys_context( 'userenv', 'current_schema' ) from dual"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java index 920e885a5e..ef9adca555 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java @@ -23,9 +23,9 @@ package org.hibernate.dialect.unique; import java.util.Iterator; import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Index; -import org.hibernate.metamodel.relational.UniqueKey; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * DB2 does not allow unique constraints on nullable columns. Rather than @@ -68,13 +68,27 @@ public class DB2UniqueDelegate extends DefaultUniqueDelegate { @Override public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) { if ( hasNullable( uniqueKey ) ) { - return Index.buildSqlCreateIndexString( - dialect, - uniqueKey.getName(), - uniqueKey.getTable(), - uniqueKey.getColumns(), - true - ); + // TODO: This borrows from Index's old way of doing things. This + // should be using StandardIndexExporter. However, not all callers + // have JdbcEnvironment available. We'll need to refactor a bit... + String keyName = dialect.qualifyIndexName() ? uniqueKey.getName() + : StringHelper.unqualify( uniqueKey.getName() ); + StringBuilder buf = new StringBuilder( "create unique index " ) + .append( keyName ).append( " on " ) + .append( uniqueKey.getTable().getQualifiedName( dialect ) ) + .append( " (" ); + boolean first = true; + for ( Column column : uniqueKey.getColumns() ) { + if ( first ) { + first = false; + } + else { + buf.append( ", " ); + } + buf.append( ( column.getColumnName().getText( dialect ) ) ); + } + buf.append( ")" ); + return buf.toString(); } else { return super.getAlterTableToAddUniqueKeyCommand( uniqueKey ); @@ -105,7 +119,12 @@ public class DB2UniqueDelegate extends DefaultUniqueDelegate { @Override public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) { if ( hasNullable( uniqueKey ) ) { - return Index.buildSqlDropIndexString( dialect, uniqueKey.getTable(), uniqueKey.getName() ); + // TODO: This borrows from Index's old way of doing things. This + // should be using StandardIndexExporter. However, not all callers + // have JdbcEnvironment available. We'll need to refactor a bit... + return "drop index " + StringHelper.qualify( + uniqueKey.getTable().getQualifiedName( dialect ), + uniqueKey.getName() ); } else { return super.getAlterTableToDropUniqueKeyCommand( uniqueKey ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java index b65fa4e9bd..97018dbf3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java @@ -23,9 +23,9 @@ package org.hibernate.dialect.unique; import java.util.Iterator; import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.UniqueKey; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * The default UniqueDelegate implementation for most dialects. Uses @@ -135,8 +135,8 @@ public class DefaultUniqueDelegate implements UniqueDelegate { final StringBuilder sb = new StringBuilder( " unique (" ); final Iterator columnIterator = uniqueKey.getColumns().iterator(); while ( columnIterator.hasNext() ) { - final org.hibernate.mapping.Column column = (org.hibernate.mapping.Column) columnIterator.next(); - sb.append( column.getQuotedName( dialect ) ); + Column column = (Column) columnIterator.next(); + sb.append( column.getColumnName().getText( dialect ) ); if ( columnIterator.hasNext() ) { sb.append( ", " ); } @@ -149,10 +149,17 @@ public class DefaultUniqueDelegate implements UniqueDelegate { public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) { // Do this here, rather than allowing UniqueKey/Constraint to do it. // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - - return "alter table " + tableName + " drop constraint " + constraintName; + final StringBuilder buf = new StringBuilder( "alter table " ); + buf.append( uniqueKey.getTable().getQualifiedName( dialect ) ); + buf.append(" drop constraint " ); + if ( dialect.supportsIfExistsBeforeConstraintName() ) { + buf.append( "if exists " ); + } + buf.append( dialect.quote( uniqueKey.getName() ) ); + if ( dialect.supportsIfExistsAfterConstraintName() ) { + buf.append( " if exists" ); + } + return buf.toString(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java index 8a00c411dd..57856c32b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java @@ -21,7 +21,7 @@ package org.hibernate.dialect.unique; import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.UniqueKey; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * Informix requires the constraint name to come last on the alter table. diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java index 156ee17144..8d5315bd66 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java @@ -20,9 +20,9 @@ */ package org.hibernate.dialect.unique; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.UniqueKey; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * Dialect-level delegate in charge of applying "uniqueness" to a column. Uniqueness can be defined diff --git a/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java new file mode 100644 index 0000000000..c7ac6ce850 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.config.spi; + + +import static org.hibernate.engine.config.spi.ConfigurationService.Converter; + +/** + * Standard set of setting converters + * + * @author Steve Ebersole + */ +public class StandardConverters { + public static final Converter BOOLEAN = new Converter() { + @Override + public Boolean convert(Object value) { + if ( value == null ) { + throw new IllegalArgumentException( "Null value passed to convert" ); + } + + return Boolean.class.isInstance( value ) + ? Boolean.class.cast( value ) + : Boolean.parseBoolean( value.toString() ); + } + }; + + public static final Converter STRING = new Converter() { + @Override + public String convert(Object value) { + if ( value == null ) { + throw new IllegalArgumentException( "Null value passed to convert" ); + } + + return value.toString(); + } + }; + + /** + * Disallow direct instantiation + */ + private StandardConverters() { + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java index b208c74692..0b2282d080 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java @@ -222,7 +222,7 @@ public final class Cascade { } if (type.isAssociationType() && ((AssociationType)type).getForeignKeyDirection().equals( - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT )) { + ForeignKeyDirection.TO_PARENT )) { // If FK direction is to-parent, we must remove the orphan *before* the queued update(s) // occur. Otherwise, replacing the association on a managed entity, without manually // nulling and flushing, causes FK constraint violations. diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionException.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionException.java new file mode 100644 index 0000000000..dc4862746d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionException.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.connections.internal; + +import org.hibernate.HibernateException; + +/** + * @author Steve Ebersole + */ +public class UserSuppliedConnectionException extends HibernateException { + public UserSuppliedConnectionException() { + super( "The application must supply JDBC connections" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java index 9987dcdda1..a74481bf84 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java @@ -58,12 +58,12 @@ public class UserSuppliedConnectionProviderImpl implements ConnectionProvider { @Override public Connection getConnection() throws SQLException { - throw new UnsupportedOperationException( "The application must supply JDBC connections" ); + throw new UserSuppliedConnectionException(); } @Override public void closeConnection(Connection conn) throws SQLException { - throw new UnsupportedOperationException( "The application must supply JDBC connections" ); + throw new UserSuppliedConnectionException(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java new file mode 100644 index 0000000000..0b4493c8bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.connections.spi; + +import java.io.Serializable; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Provides centralized access to JDBC connections. Centralized to hide the complexity of accounting for contextual + * (multi-tenant) versus non-contextual access. + * + * @author Steve Ebersole + */ +public interface JdbcConnectionAccess extends Serializable { + /** + * Obtain a JDBC connection + * + * @return The obtained connection + * + * @throws SQLException Indicates a problem getting the connection + */ + public Connection obtainConnection() throws SQLException; + + /** + * Release a previously obtained connection + * + * @param connection The connection to release + * + * @throws SQLException Indicates a problem releasing the connection + */ + public void releaseConnection(Connection connection) throws SQLException; + + /** + * Does the underlying provider of connections support aggressive releasing of connections (and re-acquisition + * of those connections later, if need be) in JTA environments? + * + * @see org.hibernate.engine.jdbc.connections.spi.ConnectionProvider#supportsAggressiveRelease() + * @see org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider#supportsAggressiveRelease() + */ + public boolean supportsAggressiveRelease(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java new file mode 100644 index 0000000000..31af134bbb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; + +/** + * Default implementation + * + * @author Steve Ebersole + */ +public class DefaultSchemaNameResolver implements SchemaNameResolver { + public static final DefaultSchemaNameResolver INSTANCE = new DefaultSchemaNameResolver(); + + @Override + public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException { + Statement statement = connection.createStatement(); + try { + ResultSet resultSet = statement.executeQuery( dialect.getCurrentSchemaCommand() ); + try { + if ( ! resultSet.next() ) { + return null; + } + return resultSet.getString( 1 ); + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java new file mode 100644 index 0000000000..d3041da95f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java @@ -0,0 +1,142 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; + +/** + * Standard implementation of ExtractedDatabaseMetaData + * + * @author Steve Ebersole + */ +public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData { + private final JdbcEnvironment jdbcEnvironment; + + private final boolean supportsRefCursors; + private final boolean supportsNamedParameters; + private final boolean supportsScrollableResults; + private final boolean supportsGetGeneratedKeys; + private final boolean supportsBatchUpdates; + private final boolean supportsDataDefinitionInTransaction; + private final boolean doesDataDefinitionCauseTransactionCommit; + private final SQLStateType sqlStateType; + private final boolean lobLocatorUpdateCopy; + + /** + * Form used when {@link java.sql.DatabaseMetaData} is not available. + * + * @param jdbcEnvironment The JDBC environment containing this metadata. + */ + public ExtractedDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment) { + this.jdbcEnvironment = jdbcEnvironment; + + // if possible, set values that will allow things to still work.... + this.supportsRefCursors = false; // Java 8 feature, safest to say not. + this.supportsNamedParameters = false; + this.supportsScrollableResults = false; + this.supportsGetGeneratedKeys = false; + this.supportsBatchUpdates = false; + this.sqlStateType = SQLStateType.UNKNOWN; + this.lobLocatorUpdateCopy = false; + + // ugh my favorites... + this.supportsDataDefinitionInTransaction = true; + this.doesDataDefinitionCauseTransactionCommit = false; + } + + public ExtractedDatabaseMetaDataImpl( + JdbcEnvironmentImpl jdbcEnvironment, + boolean supportsRefCursors, + boolean supportsNamedParameters, + boolean supportsScrollableResults, + boolean supportsGetGeneratedKeys, + boolean supportsBatchUpdates, + boolean supportsDataDefinitionInTransaction, + boolean doesDataDefinitionCauseTransactionCommit, + SQLStateType sqlStateType, + boolean lobLocatorUpdateCopy) { + this.jdbcEnvironment = jdbcEnvironment; + this.supportsRefCursors = supportsRefCursors; + this.supportsNamedParameters = supportsNamedParameters; + this.supportsScrollableResults = supportsScrollableResults; + this.supportsGetGeneratedKeys = supportsGetGeneratedKeys; + this.supportsBatchUpdates = supportsBatchUpdates; + this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction; + this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; + this.sqlStateType = sqlStateType; + this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; + } + + @Override + public boolean supportsRefCursors() { + return supportsRefCursors; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + @Override + public boolean supportsNamedParameters() { + return supportsNamedParameters; + } + + @Override + public boolean supportsScrollableResults() { + return supportsScrollableResults; + } + + @Override + public boolean supportsGetGeneratedKeys() { + return supportsGetGeneratedKeys; + } + + @Override + public boolean supportsBatchUpdates() { + return supportsBatchUpdates; + } + + @Override + public boolean supportsDataDefinitionInTransaction() { + return supportsDataDefinitionInTransaction; + } + + @Override + public boolean doesDataDefinitionCauseTransactionCommit() { + return doesDataDefinitionCauseTransactionCommit; + } + + @Override + public SQLStateType getSqlStateType() { + return sqlStateType; + } + + @Override + public boolean doesLobLocatorUpdateCopy() { + return lobLocatorUpdateCopy; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java new file mode 100644 index 0000000000..d8b994c6c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java @@ -0,0 +1,339 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.lang.reflect.InvocationTargetException; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.hibernate.boot.registry.selector.spi.StrategySelectionException; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; +import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; +import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl; +import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.engine.jdbc.spi.TypeInfo; +import org.hibernate.exception.internal.SQLExceptionTypeDelegate; +import org.hibernate.exception.internal.SQLStateConversionDelegate; +import org.hibernate.exception.internal.StandardSQLExceptionConverter; +import org.hibernate.exception.spi.SQLExceptionConverter; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +/** + * @author Steve Ebersole + */ +public class JdbcEnvironmentImpl implements JdbcEnvironment { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcEnvironmentImpl.class ); + + private final ServiceRegistryImplementor serviceRegistry; + private final Dialect dialect; + + private final SqlExceptionHelper sqlExceptionHelper; + private final ExtractedDatabaseMetaData extractedMetaDataSupport; + private final Set reservedWords; + private final Identifier currentCatalog; + private final Identifier currentSchema; + private final IdentifierHelper identifierHelper; + private final QualifiedObjectNameSupport qualifiedObjectNameSupport; + private final LobCreatorBuilderImpl lobCreatorBuilder; + private final LinkedHashSet typeInfoSet = new LinkedHashSet(); + + /** + * Constructor form used when the JDBC {@link DatabaseMetaData} is not available. + * + * @param serviceRegistry The service registry + * @param dialect The resolved dialect. + */ + public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) { + this.serviceRegistry = serviceRegistry; + this.dialect = dialect; + + this.sqlExceptionHelper = buildSqlExceptionHelper( dialect ); + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( this ); + + // make sure reserved-words, current-catalog and current-schema happen before the identifier-helper! + this.reservedWords = dialect.getKeywords(); + this.currentCatalog = Identifier.toIdentifier( + serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING ) + ); + this.currentSchema = Identifier.toIdentifier( + serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING ) + ); + + final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false ); + + // a simple temporary impl that works on H2 + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + globallyQuoteIdentifiers, + true, // storesMixedCaseQuotedIdentifiers + false, // storesLowerCaseQuotedIdentifiers + false, // storesUpperCaseQuotedIdentifiers + true, // storesUpperCaseIdentifiers + false // storesLowerCaseIdentifiers + ); + + // again, a simple temporary impl that works on H2 + this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl( + ".", + true, + dialect.openQuote(), + dialect.closeQuote() + ); + + this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(); + + } + + public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect, DatabaseMetaData dbmd) throws SQLException { + this.serviceRegistry = serviceRegistry; + this.dialect = dialect; + + this.sqlExceptionHelper = buildSqlExceptionHelper( dialect ); + + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( + this, + StandardRefCursorSupport.supportsRefCursors( dbmd ), + dbmd.supportsNamedParameters(), + dbmd.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ), + dbmd.supportsGetGeneratedKeys(), + dbmd.supportsBatchUpdates(), + !dbmd.dataDefinitionIgnoredInTransactions(), + dbmd.dataDefinitionCausesTransactionCommit(), + parseSQLStateType( dbmd.getSQLStateType() ), + dbmd.locatorsUpdateCopy() + ); + + // make sure reserved-words happen before the identifier-helper! + this.reservedWords = buildMergedReservedWords( dialect, dbmd ); + + final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false ); + + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + globallyQuoteIdentifiers, + dbmd.storesMixedCaseQuotedIdentifiers(), + dbmd.storesLowerCaseQuotedIdentifiers(), + dbmd.storesUpperCaseQuotedIdentifiers(), + dbmd.storesUpperCaseIdentifiers(), + dbmd.storesLowerCaseIdentifiers() + ); + + // and that current-catalog and current-schema happen after it + this.currentCatalog = determineCurrentCatalog( dbmd ); + this.currentSchema = determineCurrentSchema( dbmd ); + + this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl( + dbmd.getCatalogSeparator(), + dbmd.isCatalogAtStart(), + dialect.openQuote(), + dialect.closeQuote() + ); + + this.typeInfoSet.addAll( TypeInfo.extractTypeInfo( dbmd ) ); + + this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder( + serviceRegistry.getService( ConfigurationService.class ).getSettings(), + dbmd.getConnection() + ); + } + + private SQLStateType parseSQLStateType(int sqlStateType) { + switch ( sqlStateType ) { + case DatabaseMetaData.sqlStateSQL99 : { + return SQLStateType.SQL99; + } + case DatabaseMetaData.sqlStateXOpen : { + return SQLStateType.XOpen; + } + default : { + return SQLStateType.UNKNOWN; + } + } + } + + @SuppressWarnings("deprecation") + private SqlExceptionHelper buildSqlExceptionHelper(Dialect dialect) { + SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter(); + if ( sqlExceptionConverter == null ) { + final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter(); + sqlExceptionConverter = converter; + converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); + converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); + // todo : vary this based on extractedMetaDataSupport.getSqlStateType() + converter.addDelegate( new SQLStateConversionDelegate( dialect ) ); + } + return new SqlExceptionHelper( sqlExceptionConverter ); + } + + private Identifier determineCurrentCatalog(DatabaseMetaData dbmd) throws SQLException { + String currentCatalogName = dbmd.getConnection().getCatalog(); + if ( currentCatalogName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!! + return identifierHelper.fromMetaDataObjectName( currentCatalogName ); + } + else { + currentCatalogName = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING ); + return Identifier.toIdentifier( currentCatalogName ); + } + } + + private Identifier determineCurrentSchema(DatabaseMetaData dbmd) throws SQLException { + String currentSchemaName = locateSchemaNameResolver().resolveSchemaName( dbmd.getConnection(), dialect ); + if ( currentSchemaName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!! + return identifierHelper.fromMetaDataObjectName( currentSchemaName ); + } + else { + currentSchemaName = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING ); + return Identifier.toIdentifier( currentSchemaName ); + } + } + + private SchemaNameResolver locateSchemaNameResolver() { + final Object setting = serviceRegistry.getService( ConfigurationService.class ) + .getSettings() + .get( AvailableSettings.SCHEMA_NAME_RESOLVER ); + try { + return serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy( + SchemaNameResolver.class, + setting, + DefaultSchemaNameResolver.INSTANCE + ); + } + catch ( StrategySelectionException e ) { + final Throwable cause = e.getCause(); + if ( ClassNotFoundException.class.isInstance( cause ) ) { + LOG.unableToLocateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + cause.toString() + ); + } + else if ( InvocationTargetException.class.isInstance( cause ) ) { + LOG.unableToInstantiateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + InvocationTargetException.class.cast( cause ).getTargetException().toString() ); + } + else { + LOG.unableToInstantiateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + cause.toString() ); + } + return null; + } + } + + private Set buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException { + Set reservedWords = new HashSet(); + reservedWords.addAll( dialect.getKeywords() ); + // todo : do we need to explicitly handle SQL:2003 keywords? + reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) ); + return reservedWords; + } + + @Override + public Dialect getDialect() { + return dialect; + } + + @Override + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() { + return extractedMetaDataSupport; + } + + @Override + public Identifier getCurrentCatalog() { + return currentCatalog; + } + + @Override + public Identifier getCurrentSchema() { + return currentSchema; + } + + @Override + public QualifiedObjectNameSupport getQualifiedObjectNameSupport() { + return qualifiedObjectNameSupport; + } + + @Override + public IdentifierHelper getIdentifierHelper() { + return identifierHelper; + } + + @Override + public Set getReservedWords() { + return reservedWords; + } + + @Override + public SqlExceptionHelper getSqlExceptionHelper() { + return sqlExceptionHelper; + } + + @Override + public LobCreatorBuilder getLobCreatorBuilder() { + return lobCreatorBuilder; + } + + @Override + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) { + for ( TypeInfo typeInfo : typeInfoSet ) { + if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) { + return typeInfo; + } + } + return null; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java new file mode 100644 index 0000000000..35239903c7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java @@ -0,0 +1,214 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.HibernateException; +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; +import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; +import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +/** + * @author Steve Ebersole + */ +public class JdbcEnvironmentInitiator implements StandardServiceInitiator { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + JdbcEnvironmentInitiator.class.getName() + ); + + public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator(); + + @Override + public Class getServiceInitiated() { + return JdbcEnvironment.class; + } + + @Override + public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + final DialectFactory dialectFactory = registry.getService( DialectFactory.class ); + + // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. + // The need for it is intended to be alleviated with future development, thus it is + // not defined as an Environment constant... + // + // it is used to control whether we should consult the JDBC metadata to determine + // certain Settings default values; it is useful to *not* do this when the database + // may not be available (mainly in tools usage). + boolean useJdbcMetadata = ConfigurationHelper.getBoolean( + "hibernate.temp.use_jdbc_metadata_defaults", + configurationValues, + true + ); + + if ( useJdbcMetadata ) { + final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry ); + try { + final Connection connection = jdbcConnectionAccess.obtainConnection(); + try { + final DatabaseMetaData dbmd = connection.getMetaData(); + if ( log.isDebugEnabled() ) { + log.debugf( + "Database ->\n" + + " name : %s\n" + + " version : %s\n" + + " major : %s\n" + + " minor : %s", + dbmd.getDatabaseProductName(), + dbmd.getDatabaseProductVersion(), + dbmd.getDatabaseMajorVersion(), + dbmd.getDatabaseMinorVersion() + ); + log.debugf( + "Driver ->\n" + + " name : %s\n" + + " version : %s\n" + + " major : %s\n" + + " minor : %s", + dbmd.getDriverName(), + dbmd.getDriverVersion(), + dbmd.getDriverMajorVersion(), + dbmd.getDriverMinorVersion() + ); + log.debugf( "JDBC version : %s.%s", dbmd.getJDBCMajorVersion(), dbmd.getJDBCMinorVersion() ); + } + + Dialect dialect = dialectFactory.buildDialect( + configurationValues, + new DialectResolutionInfoSource() { + @Override + public DialectResolutionInfo getDialectResolutionInfo() { + try { + return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() ); + } + catch ( SQLException sqlException ) { + throw new HibernateException( + "Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use", + sqlException + ); + } + } + } + ); + return new JdbcEnvironmentImpl( + registry, + dialect, + dbmd + ); + } + catch (SQLException e) { + log.unableToObtainConnectionMetadata( e.getMessage() ); + } + finally { + try { + jdbcConnectionAccess.releaseConnection( connection ); + } + catch (SQLException ignore) { + } + } + } + catch (Exception e) { + log.unableToObtainConnectionToQueryMetadata( e.getMessage() ); + } + } + + // if we get here, either we were asked to not use JDBC metadata or accessing the JDBC metadata failed. + return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect( configurationValues, null ) ); + } + + private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) { + final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); + if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) { + ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class ); + return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); + } + else { + final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class ); + return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); + } + } + + private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final ConnectionProvider connectionProvider; + + public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.closeConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } + + private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final MultiTenantConnectionProvider connectionProvider; + + public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getAnyConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.releaseAnyConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java similarity index 81% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java index 45f335cf11..e8d70d7896 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.engine.jdbc.internal; +package org.hibernate.engine.jdbc.env.internal; import java.lang.reflect.Method; import java.sql.Connection; @@ -34,6 +34,7 @@ import org.hibernate.engine.jdbc.ContextualLobCreator; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.jdbc.NonContextualLobCreator; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; @@ -44,23 +45,40 @@ import org.jboss.logging.Logger; * * @author Steve Ebersole */ -public class LobCreatorBuilder { +public class LobCreatorBuilderImpl implements LobCreatorBuilder { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, - LobCreatorBuilder.class.getName() + LobCreatorBuilderImpl.class.getName() ); - private boolean useContextualLobCreation; + private final boolean useContextualLobCreation; + + private LobCreatorBuilderImpl(boolean useContextualLobCreation) { + this.useContextualLobCreation = useContextualLobCreation; + } + + // factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** - * The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}. + * The public factory method for obtaining the appropriate LOB creator (according to given + * JDBC {@link java.sql.Connection}). * * @param configValues The map of settings * @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support, * specifically for creating LOB references. */ - public LobCreatorBuilder(Map configValues, Connection jdbcConnection) { - this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection ); + public static LobCreatorBuilderImpl makeLobCreatorBuilder(Map configValues, Connection jdbcConnection) { + return new LobCreatorBuilderImpl( useContextualLobCreation( configValues, jdbcConnection ) ); + } + + /** + * For used when JDBC Connection is not available. + * + * @return Appropriate LobCreatorBuilder + */ + public static LobCreatorBuilderImpl makeLobCreatorBuilder() { + LOG.disablingContextualLOBCreationSinceConnectionNull(); + return new LobCreatorBuilderImpl( false ); } private static final Class[] NO_ARG_SIG = new Class[0]; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java new file mode 100644 index 0000000000..7cde165750 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java @@ -0,0 +1,217 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import org.jboss.logging.Logger; + +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** +* @author Steve Ebersole +*/ +public class NormalizingIdentifierHelperImpl implements IdentifierHelper { + private static final Logger log = Logger.getLogger( NormalizingIdentifierHelperImpl.class ); + + private final JdbcEnvironment jdbcEnvironment; + + private final boolean globallyQuoteIdentifiers; + + private final boolean storesMixedCaseQuotedIdentifiers; + private final boolean storesLowerCaseQuotedIdentifiers; + private final boolean storesUpperCaseQuotedIdentifiers; + private final boolean storesUpperCaseIdentifiers; + private final boolean storesLowerCaseIdentifiers; + + public NormalizingIdentifierHelperImpl( + JdbcEnvironment jdbcEnvironment, + boolean globallyQuoteIdentifiers, + boolean storesMixedCaseQuotedIdentifiers, + boolean storesLowerCaseQuotedIdentifiers, + boolean storesUpperCaseQuotedIdentifiers, + boolean storesUpperCaseIdentifiers, + boolean storesLowerCaseIdentifiers) { + this.jdbcEnvironment = jdbcEnvironment; + this.globallyQuoteIdentifiers = globallyQuoteIdentifiers; + this.storesMixedCaseQuotedIdentifiers = storesMixedCaseQuotedIdentifiers; + this.storesLowerCaseQuotedIdentifiers = storesLowerCaseQuotedIdentifiers; + this.storesUpperCaseQuotedIdentifiers = storesUpperCaseQuotedIdentifiers; + this.storesUpperCaseIdentifiers = storesUpperCaseIdentifiers; + this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers; + + if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in mixed, upper and lower case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and upper case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesLowerCaseIdentifiers ) { + log.warn( "JDBC Driver reports it stores non-quoted identifiers in both upper and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in upper case" ); + } + + if ( storesLowerCaseIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in lower case" ); + } + } + + // In the DatabaseMetaData method params for catalog and schema name have the following meaning: + // 1) <""> means to match things "without a catalog/schema" + // 2) means to not limit results based on this field + // + // todo : not sure how "without a catalog/schema" is interpreted. Current? + + @Override + public String toMetaDataCatalogName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentCatalog() == null ? null : jdbcEnvironment.getCurrentCatalog().getText(); + } + + return toText( identifier ); + } + + private String toText(Identifier identifier) { + if ( identifier == null ) { + throw new IllegalArgumentException( "Identifier cannot be null; bad usage" ); + } + + if ( identifier.isQuoted() && storesMixedCaseQuotedIdentifiers ) { + return identifier.getText(); + } + else if ( ( identifier.isQuoted() && storesUpperCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesUpperCaseIdentifiers ) ) { + return StringHelper.toUpperCase( identifier.getText() ); + } + else if ( ( identifier.isQuoted() && storesLowerCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesLowerCaseIdentifiers ) ) { + return StringHelper.toLowerCase( identifier.getText() ); + } + return identifier.getText(); + } + + @Override + public String toMetaDataSchemaName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentSchema() == null ? null : jdbcEnvironment.getCurrentSchema().getText(); + } + + return toText( identifier ); + } + + @Override + public String toMetaDataObjectName(Identifier identifier) { + if ( identifier == null ) { + // if this method was called, the value is needed + throw new IllegalArgumentException( ); + } + return toText( identifier ); + } + + @Override + public Identifier fromMetaDataCatalogName(String catalogName) { + if ( catalogName == null ) { + return null; + } + + if ( jdbcEnvironment.getCurrentCatalog() == null + || catalogName.equals( jdbcEnvironment.getCurrentCatalog().getText() ) ) { + return null; + } + + return toIdentifier( catalogName ); + // note really sure the best way to know (can you?) whether the identifier is quoted + + } + + public Identifier toIdentifier(String text) { + if ( globallyQuoteIdentifiers ) { + return Identifier.toIdentifier( text, true ); + } + + // lovely decipher of whether the incoming value represents a quoted identifier... + final boolean isUpperCase = text.toUpperCase().equals( text ); + final boolean isLowerCase = text.toLowerCase().equals( text ); + final boolean isMixedCase = ! isLowerCase && ! isUpperCase; + + if ( jdbcEnvironment.getReservedWords().contains( text ) ) { + // unequivocally it needs to be quoted... + return Identifier.toIdentifier( text, true ); + } + + if ( storesMixedCaseQuotedIdentifiers && isMixedCase ) { + return Identifier.toIdentifier( text, true ); + } + + if ( storesLowerCaseQuotedIdentifiers && isLowerCase ) { + return Identifier.toIdentifier( text, true ); + } + + if ( storesUpperCaseQuotedIdentifiers && isUpperCase ) { + return Identifier.toIdentifier( text, true ); + } + + return Identifier.toIdentifier( text ); + } + + @Override + public Identifier toIdentifier(String text, boolean quoted) { + return globallyQuoteIdentifiers + ? Identifier.toIdentifier( text, true ) + : Identifier.toIdentifier( text, quoted ); + } + + @Override + public Identifier fromMetaDataSchemaName(String schemaName) { + if ( schemaName == null ) { + return null; + } + + if ( jdbcEnvironment.getCurrentSchema() == null + || schemaName.equals( jdbcEnvironment.getCurrentSchema().getText() ) ) { + return null; + } + + return toIdentifier( schemaName ); + } + + @Override + public Identifier fromMetaDataObjectName(String objectName) { + if ( objectName == null ) { + return null; + } + + return toIdentifier( objectName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java index f33c096e13..ad8af7f389 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java @@ -21,11 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.engine.jdbc.spi; +package org.hibernate.engine.jdbc.env.spi; import java.util.LinkedHashSet; import java.util.Set; +import org.hibernate.engine.jdbc.spi.TypeInfo; + /** * Information extracted from {@link java.sql.DatabaseMetaData} regarding what the JDBC driver reports as * being supported or not. Obviously {@link java.sql.DatabaseMetaData} reports many things, these are a few in @@ -36,22 +38,11 @@ import java.util.Set; @SuppressWarnings( {"UnusedDeclaration"}) public interface ExtractedDatabaseMetaData { /** - * Which specification do the reported SQLState codes follow? + * Obtain the JDBC Environment from which this metadata came. + * + * @return The JDBC environment */ - public enum SQLStateType { - /** - * The reported codes follow the X/Open spec - */ - XOpen, - /** - * The reported codes follow the SQL spec - */ - SQL99, - /** - * It is unknown. Might follow another spec completely, or be a mixture. - */ - UNKOWN - } + public JdbcEnvironment getJdbcEnvironment(); /** * Does the driver report supporting named parameters? @@ -116,15 +107,6 @@ public interface ExtractedDatabaseMetaData { */ public boolean doesDataDefinitionCauseTransactionCommit(); - /** - * Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver. - * - * @return The extra keywords used by this database. - * - * @see java.sql.DatabaseMetaData#getSQLKeywords() - */ - public Set getExtraKeywords(); - /** * Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either * the X/Open standard or the SQL92 standard. @@ -143,27 +125,4 @@ public interface ExtractedDatabaseMetaData { * @see java.sql.DatabaseMetaData#locatorsUpdateCopy() */ public boolean doesLobLocatorUpdateCopy(); - - /** - * Retrieve the name of the schema in effect when we connected to the database. - * - * @return The schema name - */ - public String getConnectionSchemaName(); - - /** - * Retrieve the name of the catalog in effect when we connected to the database. - * - * @return The catalog name - */ - public String getConnectionCatalogName(); - - /** - * Set of type info reported by the driver. - * - * @return The type information obtained from the driver. - * - * @see java.sql.DatabaseMetaData#getTypeInfo() - */ - public LinkedHashSet getTypeInfoSet(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java new file mode 100644 index 0000000000..11a3de36b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Helper for handling {@link Identifier} instances. + * + * @author Steve Ebersole + */ +public interface IdentifierHelper { + /** + * Generate an {@link Identifier} instance from its simple name + * + * @param text The text + * + * @return The identifier form of the name. + */ + public Identifier toIdentifier(String text); + + /** + * Generate an {@link Identifier} instance from its simple name and explicitly whether it is quoted or not + * (although note that 'globally quoted identifiers' setting can still cause returned Identifiers to be quoted + * even if {@code false} is passed in here). + * + * @param text The name + * @param quoted Is the identifier to be quoted explicitly. + * + * @return The identifier form of the name. + */ + public Identifier toIdentifier(String text, boolean quoted); + + public String toMetaDataCatalogName(Identifier identifier); + public String toMetaDataSchemaName(Identifier identifier); + public String toMetaDataObjectName(Identifier identifier); + public Identifier fromMetaDataCatalogName(String catalogName); + public Identifier fromMetaDataSchemaName(String schemaName); + public Identifier fromMetaDataObjectName(String objectName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java new file mode 100644 index 0000000000..5e4e4e9c67 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java @@ -0,0 +1,124 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.engine.jdbc.spi.TypeInfo; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.Service; +import org.hibernate.service.ServiceRegistry; + +/** + * Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData} + * and {@link org.hibernate.dialect.Dialect} + * + * @author Steve Ebersole + */ +public interface JdbcEnvironment extends Service { + /** + * Get the dialect for this environment. + * + * @return The dialect. + */ + public Dialect getDialect(); + + /** + * Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get + * "interpreted" into the helpers/delegates available here). + * + * @return The values extracted from JDBC DatabaseMetaData + */ + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData(); + + /** + * Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()} + * or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}. + * + * @return The current catalog. + */ + public Identifier getCurrentCatalog(); + + /** + * Get the current database catalog. Typically will come from either + * {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection, org.hibernate.dialect.Dialect)} or + * {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}. + * + * @return The current schema + */ + public Identifier getCurrentSchema(); + + /** + * Obtain support for reading and writing qualified object names. + * + * @return Qualified name support. + */ + public QualifiedObjectNameSupport getQualifiedObjectNameSupport(); + + /** + * Obtain the helper for dealing with identifiers in this environment. + * + * @return The identifier helper. + */ + public IdentifierHelper getIdentifierHelper(); + + /** + * Get the complete set of reserved words for this environment. These are significant because they represent + * the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting + * in the metamodel based on these terms. + * + * Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for + * auto-quoting :) yaay! + * + * @return Reserved words + */ + public Set getReservedWords(); + + /** + * Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults. + * + * @return This environment's helper. + */ + public SqlExceptionHelper getSqlExceptionHelper(); + + /** + * Retrieve the delegate for building {@link org.hibernate.engine.jdbc.LobCreator} instances. + * + * @return The LobCreator builder. + */ + public LobCreatorBuilder getLobCreatorBuilder(); + + /** + * Find type information for the type identified by the given "JDBC type code". + * + * @param jdbcTypeCode The JDBC type code. + * + * @return The corresponding type info. + */ + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode); + + public ServiceRegistry getServiceRegistry(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java new file mode 100644 index 0000000000..4f4c9df783 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.engine.jdbc.LobCreationContext; +import org.hibernate.engine.jdbc.LobCreator; + +/** + * @author Steve Ebersole + */ +public interface LobCreatorBuilder { + LobCreator buildLobCreator(LobCreationContext lobCreationContext); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java new file mode 100644 index 0000000000..8bdbb69f90 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Defines support for reading and writing qualified object names to and from the database. Generally speaking + * Hibernate itself only uses {@link #formatName}. Most times when it is "parsing" object names it is coming from + * mappings, in which case we expect simple dot-separated syntax and apply {@link ObjectName#parse} + * + * @author Steve Ebersole + */ +public interface QualifiedObjectNameSupport { + /** + * Performs formatting of an ObjectName to its String representation + * + * @param objectName The object name to be formatted. + * + * @return The dialect specific string form of the name. + */ + public String formatName(ObjectName objectName); + + /** + * Parse a String representation of an Object name to its ObjectName. Note that this specifically + * attempts to parse the text as if coming from the database. Mapping forms always use + * the form {@code ..}, parsing such names should just use {@link ObjectName#parse} + * + * @param text The object name text + * + * @return The parsed ObjectName + */ + public ObjectName parseName(String text); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java new file mode 100644 index 0000000000..7cfcd7517b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +/** + * Enum interpretation of the valid values from {@link java.sql.DatabaseMetaData#getSQLStateType()} + * + * @author Steve Ebersole + */ +public enum SQLStateType { + /** + * The reported codes follow the X/Open spec + */ + XOpen, + /** + * The reported codes follow the SQL spec + */ + SQL99, + /** + * It is unknown. Might follow another spec completely, or be a mixture. + */ + UNKNOWN +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java new file mode 100644 index 0000000000..c9da81ee97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.hibernate.dialect.Dialect; + +/** + * Contract for resolving the schema of a {@link Connection}. + * + * @author Steve Ebersole + */ +public interface SchemaNameResolver { + /** + * Given a JDBC {@link Connection}, resolve the name of the schema (if one) to which it connects. + * + * @param connection The JDBC connection + * @param dialect The Dialect + * + * @return The name of the schema (may be null). + */ + public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java new file mode 100644 index 0000000000..b8953979e2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.util.regex.Pattern; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.IllegalIdentifierException; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * @author Steve Ebersole + */ +public class StandardQualifiedObjectNameSupportImpl implements QualifiedObjectNameSupport { + public static final char DEFAULT_QUOTE_START = '\''; + public static final char DEFAULT_QUOTE_END = '\''; + public static final String DEFAULT_CATALOG_SEPARATOR = "."; + + private final String catalogSeparator; + private final boolean catalogAfterName; + private final char quotedStart; + private final char quotedEnd; + + private final Pattern splitPattern; + + public StandardQualifiedObjectNameSupportImpl( + String catalogSeparator, + boolean catalogAfterName, + char quotedStart, + char quotedEnd) { + this.catalogSeparator = catalogSeparator; + this.catalogAfterName = catalogAfterName; + this.quotedStart = quotedStart; + this.quotedEnd = quotedEnd; + + splitPattern = ".".equals( catalogSeparator ) + ? Pattern.compile( Pattern.quote( "." ) ) + : Pattern.compile( "[\\." + catalogSeparator + "]" ); + } + + public StandardQualifiedObjectNameSupportImpl() { + this( DEFAULT_CATALOG_SEPARATOR, false, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END ); + } + + public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) { + this( catalogSeparator, catalogAfterName, dialect.openQuote(), dialect.closeQuote() ); + } + + public StandardQualifiedObjectNameSupportImpl(Dialect dialect) { + this( DEFAULT_CATALOG_SEPARATOR, false, dialect ); + } + + public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName) { + this( catalogSeparator, catalogAfterName, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END ); + } + + + @Override + public String formatName(ObjectName objectName) { + StringBuilder buffer = new StringBuilder(); + if ( ! catalogAfterName ) { + if ( objectName.getCatalog() != null ) { + buffer.append( objectName.getCatalog().getText( quotedStart, quotedEnd ) ) + .append( catalogSeparator ); + } + } + + if ( objectName.getSchema() != null ) { + buffer.append( objectName.getSchema().getText( quotedStart, quotedEnd ) ).append( '.' ); + } + buffer.append( objectName.getName().getText( quotedStart, quotedEnd ) ); + + if ( catalogAfterName ) { + if ( objectName.getCatalog() != null ) { + buffer.append( catalogSeparator ) + .append( objectName.getCatalog().getText( quotedStart, quotedEnd ) ); + } + } + + return buffer.toString(); + } + + @Override + public ObjectName parseName(String text) { + if ( text == null ) { + throw new IllegalIdentifierException( "Object name must be specified" ); + } + + String catalogName = null; + String schemaName = null; + String localObjectName; + + final String[] tokens = splitPattern.split( text ); + if ( tokens.length == 0 || tokens.length == 1 ) { + // we have just a local name... + localObjectName = text; + } + else if ( tokens.length == 2 ) { + // we have 'something.name', no real way to know if something is a catalog or schema + // but thats ok based on the way we implement Database... so assume schema + schemaName = tokens[0]; + localObjectName = tokens[1]; + } + else if ( tokens.length == 3 ) { + if ( catalogAfterName ) { + schemaName = tokens[0]; + localObjectName = tokens[1]; + catalogName = tokens[2]; + } + else { + catalogName = tokens[0]; + schemaName = tokens[1]; + localObjectName = tokens[2]; + } + } + else { + throw new HibernateException( "Unable to parse object name: " + text ); + } + + return new ObjectName( catalogName, schemaName, localObjectName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java index fc5e45f818..885bc4d454 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java @@ -23,45 +23,22 @@ */ package org.hibernate.engine.jdbc.internal; -import java.lang.reflect.InvocationTargetException; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; -import org.hibernate.HibernateException; import org.hibernate.MultiTenancyStrategy; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; -import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; -import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; -import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; -import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; -import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; -import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.ResultSetWrapper; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; -import org.hibernate.engine.jdbc.spi.TypeInfo; -import org.hibernate.exception.internal.SQLExceptionTypeDelegate; -import org.hibernate.exception.internal.SQLStateConversionDelegate; -import org.hibernate.exception.internal.StandardSQLExceptionConverter; -import org.hibernate.exception.spi.SQLExceptionConverter; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.ServiceRegistryAwareService; @@ -76,13 +53,10 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcServicesImpl.class ); private ServiceRegistryImplementor serviceRegistry; + private JdbcEnvironment jdbcEnvironment; - private Dialect dialect; private ConnectionProvider connectionProvider; private SqlStatementLogger sqlStatementLogger; - private SqlExceptionHelper sqlExceptionHelper; - private ExtractedDatabaseMetaData extractedMetaDataSupport; - private LobCreatorBuilder lobCreatorBuilder; @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { @@ -91,389 +65,17 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi @Override public void configure(Map configValues) { - final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configValues ); - final DialectFactory dialectFactory = serviceRegistry.getService( DialectFactory.class ); + this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); - Dialect dialect = null; - LobCreatorBuilder lobCreatorBuilder = null; - - boolean metaSupportsRefCursors = false; - boolean metaSupportsNamedParams = false; - boolean metaSupportsScrollable = false; - boolean metaSupportsGetGeneratedKeys = false; - boolean metaSupportsBatchUpdates = false; - boolean metaReportsDDLCausesTxnCommit = false; - boolean metaReportsDDLInTxnSupported = true; - String extraKeywordsString = ""; - int sqlStateType = -1; - boolean lobLocatorUpdateCopy = false; - String catalogName = null; - String schemaName = null; - final LinkedHashSet typeInfoSet = new LinkedHashSet(); - - // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. - // The need for it is intended to be alleviated with future development, thus it is - // not defined as an Environment constant... - // - // it is used to control whether we should consult the JDBC metadata to determine - // certain Settings default values; it is useful to *not* do this when the database - // may not be available (mainly in tools usage). - final boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true ); - if ( useJdbcMetadata ) { - try { - final Connection connection = jdbcConnectionAccess.obtainConnection(); - try { - final DatabaseMetaData meta = connection.getMetaData(); - if ( LOG.isDebugEnabled() ) { - LOG.debugf( - "Database ->\n" - + " name : %s\n" - + " version : %s\n" - + " major : %s\n" - + " minor : %s", - meta.getDatabaseProductName(), - meta.getDatabaseProductVersion(), - meta.getDatabaseMajorVersion(), - meta.getDatabaseMinorVersion() - ); - LOG.debugf( - "Driver ->\n" - + " name : %s\n" - + " version : %s\n" - + " major : %s\n" - + " minor : %s", - meta.getDriverName(), - meta.getDriverVersion(), - meta.getDriverMajorVersion(), - meta.getDriverMinorVersion() - ); - LOG.debugf( "JDBC version : %s.%s", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion() ); - } - - metaSupportsRefCursors = StandardRefCursorSupport.supportsRefCursors( meta ); - metaSupportsNamedParams = meta.supportsNamedParameters(); - metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ); - metaSupportsBatchUpdates = meta.supportsBatchUpdates(); - metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit(); - metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions(); - metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys(); - extraKeywordsString = meta.getSQLKeywords(); - sqlStateType = meta.getSQLStateType(); - lobLocatorUpdateCopy = meta.locatorsUpdateCopy(); - typeInfoSet.addAll( TypeInfo.extractTypeInfo( meta ) ); - - dialect = dialectFactory.buildDialect( - configValues, - new DialectResolutionInfoSource() { - @Override - public DialectResolutionInfo getDialectResolutionInfo() { - try { - return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() ); - } - catch ( SQLException sqlException ) { - throw new HibernateException( - "Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use", - sqlException - ); - } - } - } - ); - - catalogName = connection.getCatalog(); - final SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues ); - if ( schemaNameResolver == null ) { -// todo : add dialect method -// schemaNameResolver = dialect.getSchemaNameResolver(); - } - if ( schemaNameResolver != null ) { - schemaName = schemaNameResolver.resolveSchemaName( connection ); - } - lobCreatorBuilder = new LobCreatorBuilder( configValues, connection ); - } - catch ( SQLException sqle ) { - LOG.unableToObtainConnectionMetadata( sqle.getMessage() ); - } - finally { - if ( connection != null ) { - jdbcConnectionAccess.releaseConnection( connection ); - } - } - } - catch ( SQLException sqle ) { - LOG.unableToObtainConnectionToQueryMetadata( sqle.getMessage() ); - dialect = dialectFactory.buildDialect( configValues, null ); - } - catch ( UnsupportedOperationException uoe ) { - // user supplied JDBC connections - dialect = dialectFactory.buildDialect( configValues, null ); - } - } - else { - dialect = dialectFactory.buildDialect( configValues, null ); - } + final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); + this.connectionProvider = MultiTenancyStrategy.NONE == multiTenancyStrategy ? + serviceRegistry.getService( ConnectionProvider.class ) : + null; final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false ); final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false ); - this.dialect = dialect; - this.lobCreatorBuilder = ( - lobCreatorBuilder == null ? - new LobCreatorBuilder( configValues, null ) : - lobCreatorBuilder - ); - this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL ); - - this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( - metaSupportsRefCursors, - metaSupportsNamedParams, - metaSupportsScrollable, - metaSupportsGetGeneratedKeys, - metaSupportsBatchUpdates, - metaReportsDDLInTxnSupported, - metaReportsDDLCausesTxnCommit, - parseKeywords( extraKeywordsString ), - parseSQLStateType( sqlStateType ), - lobLocatorUpdateCopy, - schemaName, - catalogName, - typeInfoSet - ); - - SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter(); - if ( sqlExceptionConverter == null ) { - final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter(); - sqlExceptionConverter = converter; - converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); - converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); - // todo : vary this based on extractedMetaDataSupport.getSqlStateType() - converter.addDelegate( new SQLStateConversionDelegate( dialect ) ); - } - this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter ); - } - - private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues) { - final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); - - if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) { - connectionProvider = serviceRegistry.getService( ConnectionProvider.class ); - return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); - } - else { - connectionProvider = null; - final MultiTenantConnectionProvider multiTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class ); - return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); - } - } - - private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { - private final ConnectionProvider connectionProvider; - - public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { - this.connectionProvider = connectionProvider; - } - - @Override - public Connection obtainConnection() throws SQLException { - return connectionProvider.getConnection(); - } - - @Override - public void releaseConnection(Connection connection) throws SQLException { - connectionProvider.closeConnection( connection ); - } - - @Override - public boolean supportsAggressiveRelease() { - return connectionProvider.supportsAggressiveRelease(); - } - } - - private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { - private final MultiTenantConnectionProvider connectionProvider; - - public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) { - this.connectionProvider = connectionProvider; - } - - @Override - public Connection obtainConnection() throws SQLException { - return connectionProvider.getAnyConnection(); - } - - @Override - public void releaseConnection(Connection connection) throws SQLException { - connectionProvider.releaseAnyConnection( connection ); - } - - @Override - public boolean supportsAggressiveRelease() { - return connectionProvider.supportsAggressiveRelease(); - } - } - - - /** - * A constant naming the setting used to identify the {@link SchemaNameResolver} to use - *

- * TODO : add to Environment - */ - public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver"; - - private SchemaNameResolver determineExplicitSchemaNameResolver(Map configValues) { - final Object setting = configValues.get( SCHEMA_NAME_RESOLVER ); - if ( SchemaNameResolver.class.isInstance( setting ) ) { - return (SchemaNameResolver) setting; - } - - final String resolverClassName = (String) setting; - if ( resolverClassName != null ) { - try { - final Class resolverClass = ReflectHelper.classForName( resolverClassName, getClass() ); - return (SchemaNameResolver) ReflectHelper.getDefaultConstructor( resolverClass ).newInstance(); - } - catch ( ClassNotFoundException e ) { - LOG.unableToLocateConfiguredSchemaNameResolver( resolverClassName, e.toString() ); - } - catch ( InvocationTargetException e ) { - LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.getTargetException().toString() ); - } - catch ( Exception e ) { - LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.toString() ); - } - } - return null; - } - - private Set parseKeywords(String extraKeywordsString) { - final Set keywordSet = new HashSet(); - keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "," ) ) ); - return keywordSet; - } - - private ExtractedDatabaseMetaData.SQLStateType parseSQLStateType(int sqlStateType) { - switch ( sqlStateType ) { - case DatabaseMetaData.sqlStateSQL99 : { - return ExtractedDatabaseMetaData.SQLStateType.SQL99; - } - case DatabaseMetaData.sqlStateXOpen : { - return ExtractedDatabaseMetaData.SQLStateType.XOpen; - } - default : { - return ExtractedDatabaseMetaData.SQLStateType.UNKOWN; - } - } - } - - private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData { - private final boolean supportsRefCursors; - private final boolean supportsNamedParameters; - private final boolean supportsScrollableResults; - private final boolean supportsGetGeneratedKeys; - private final boolean supportsBatchUpdates; - private final boolean supportsDataDefinitionInTransaction; - private final boolean doesDataDefinitionCauseTransactionCommit; - private final Set extraKeywords; - private final SQLStateType sqlStateType; - private final boolean lobLocatorUpdateCopy; - private final String connectionSchemaName; - private final String connectionCatalogName; - private final LinkedHashSet typeInfoSet; - - private ExtractedDatabaseMetaDataImpl( - boolean supportsRefCursors, - boolean supportsNamedParameters, - boolean supportsScrollableResults, - boolean supportsGetGeneratedKeys, - boolean supportsBatchUpdates, - boolean supportsDataDefinitionInTransaction, - boolean doesDataDefinitionCauseTransactionCommit, - Set extraKeywords, - SQLStateType sqlStateType, - boolean lobLocatorUpdateCopy, - String connectionSchemaName, - String connectionCatalogName, - LinkedHashSet typeInfoSet) { - this.supportsRefCursors = supportsRefCursors; - this.supportsNamedParameters = supportsNamedParameters; - this.supportsScrollableResults = supportsScrollableResults; - this.supportsGetGeneratedKeys = supportsGetGeneratedKeys; - this.supportsBatchUpdates = supportsBatchUpdates; - this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction; - this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; - this.extraKeywords = extraKeywords; - this.sqlStateType = sqlStateType; - this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; - this.connectionSchemaName = connectionSchemaName; - this.connectionCatalogName = connectionCatalogName; - this.typeInfoSet = typeInfoSet; - } - - @Override - public boolean supportsRefCursors() { - return supportsRefCursors; - } - - @Override - public boolean supportsNamedParameters() { - return supportsNamedParameters; - } - - @Override - public boolean supportsScrollableResults() { - return supportsScrollableResults; - } - - @Override - public boolean supportsGetGeneratedKeys() { - return supportsGetGeneratedKeys; - } - - @Override - public boolean supportsBatchUpdates() { - return supportsBatchUpdates; - } - - @Override - public boolean supportsDataDefinitionInTransaction() { - return supportsDataDefinitionInTransaction; - } - - @Override - public boolean doesDataDefinitionCauseTransactionCommit() { - return doesDataDefinitionCauseTransactionCommit; - } - - @Override - public Set getExtraKeywords() { - return extraKeywords; - } - - @Override - public SQLStateType getSqlStateType() { - return sqlStateType; - } - - @Override - public boolean doesLobLocatorUpdateCopy() { - return lobLocatorUpdateCopy; - } - - @Override - public String getConnectionSchemaName() { - return connectionSchemaName; - } - - @Override - public String getConnectionCatalogName() { - return connectionCatalogName; - } - - @Override - public LinkedHashSet getTypeInfoSet() { - return typeInfoSet; - } } @Override @@ -488,26 +90,30 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi @Override public SqlExceptionHelper getSqlExceptionHelper() { - return sqlExceptionHelper; + return jdbcEnvironment == null ? null : jdbcEnvironment.getSqlExceptionHelper(); } @Override public Dialect getDialect() { - return dialect; + return jdbcEnvironment == null ? null : jdbcEnvironment.getDialect(); } @Override public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { - return extractedMetaDataSupport; - } + return jdbcEnvironment == null ? null : jdbcEnvironment.getExtractedDatabaseMetaData(); } @Override public LobCreator getLobCreator(LobCreationContext lobCreationContext) { - return lobCreatorBuilder.buildLobCreator( lobCreationContext ); + return jdbcEnvironment == null ? null : jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext ); } @Override public ResultSetWrapper getResultSetWrapper() { return ResultSetWrapperImpl.INSTANCE; } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java index 0e67fdc95c..e4092dcbe5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java @@ -27,6 +27,8 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.service.Service; /** @@ -90,4 +92,6 @@ public interface JdbcServices extends Service { * @return The ResultSet wrapper. */ public ResultSetWrapper getResultSetWrapper(); + + public JdbcEnvironment getJdbcEnvironment(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java index b143a5fdff..d972b652e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java @@ -25,7 +25,7 @@ package org.hibernate.engine.spi; import org.hibernate.cfg.Configuration; import org.hibernate.internal.CacheImpl; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java new file mode 100644 index 0000000000..46fe1f7727 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.spi; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class SyntheticAttributeHelper { + public static final String SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME = "_identifierMapper"; + + private static final String BACKREF_ATTRIBUTE_NAME_PREFIX = "_"; + private static final String BACKREF_ATTRIBUTE_NAME_SUFFIX = "BackRef"; + private static final String INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX = "IndexBackRef"; + + + public static String createBackRefAttributeName(String pluralAttributeRole) { + return createSyntheticAttributeName( + pluralAttributeRole, + BACKREF_ATTRIBUTE_NAME_PREFIX, + BACKREF_ATTRIBUTE_NAME_SUFFIX + ); + } + + public static String createIndexBackRefAttributeName(String pluralAttributeRole) { + return createSyntheticAttributeName( + pluralAttributeRole, + BACKREF_ATTRIBUTE_NAME_PREFIX, + INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX + ); + } + + private static String createSyntheticAttributeName(String attributeRole, String prefix, String suffix) { + return new StringBuilder( + prefix.length() + attributeRole.length() + suffix.length() ) + .append( prefix ) + .append( attributeRole ) + .append( suffix ) + .toString(); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index ae4339585c..de62477316 100755 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -211,14 +211,14 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme // copy created before we actually copy //cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE); super.cascadeBeforeSave( source, persister, entity, copyCache ); - copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ); + copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT ); saveTransientEntity( copy, entityName, event.getRequestedId(), source, copyCache ); // cascade first, so that all unsaved objects get their // copy created before we actually copy super.cascadeAfterSave( source, persister, entity, copyCache ); - copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); + copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT ); event.setResult( copy ); } @@ -391,7 +391,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme final Object[] copiedValues; - if ( foreignKeyDirection == ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ) { + if ( foreignKeyDirection == ForeignKeyDirection.TO_PARENT ) { // this is the second pass through on a merge op, so here we limit the // replacement to associations types (value types were already replaced // during the first pass) diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java index 76493f43d5..60ecbab05b 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java @@ -26,7 +26,7 @@ package org.hibernate.event.service.internal; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/id/Assigned.java b/hibernate-core/src/main/java/org/hibernate/id/Assigned.java index c04ee9835d..a11e404416 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/Assigned.java +++ b/hibernate-core/src/main/java/org/hibernate/id/Assigned.java @@ -28,6 +28,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.Type; @@ -57,7 +58,7 @@ public class Assigned implements IdentifierGenerator, Configurable { return id; } - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { entityName = params.getProperty(ENTITY_NAME); if ( entityName == null ) { throw new MappingException("no entity name"); diff --git a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java index a924daaf91..2c824a95d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java @@ -22,9 +22,9 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.id; + import java.io.Serializable; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -102,7 +102,7 @@ public class CompositeNestedGeneratedValueGenerator implements IdentifierGenerat } private final GenerationContextLocator generationContextLocator; - private List generationPlans = new ArrayList(); + private List generationPlans = new ArrayList(); public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) { this.generationContextLocator = generationContextLocator; @@ -115,19 +115,15 @@ public class CompositeNestedGeneratedValueGenerator implements IdentifierGenerat @Override public Serializable generate(SessionImplementor session, Object object) throws HibernateException { final Serializable context = generationContextLocator.locateGenerationContext( session, object ); - - for ( Object generationPlan : generationPlans ) { - final GenerationPlan plan = (GenerationPlan) generationPlan; + for ( final GenerationPlan plan : generationPlans ) { plan.execute( session, object, context ); } - return context; } @Override public void registerPersistentGenerators(Map generatorMap) { - for ( Object generationPlan : generationPlans ) { - final GenerationPlan plan = (GenerationPlan) generationPlan; + for(final GenerationPlan plan : generationPlans){ plan.registerPersistentGenerators( generatorMap ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/Configurable.java b/hibernate-core/src/main/java/org/hibernate/id/Configurable.java index a65bd7393d..3c67868010 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/Configurable.java +++ b/hibernate-core/src/main/java/org/hibernate/id/Configurable.java @@ -26,6 +26,7 @@ package org.hibernate.id; import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.type.Type; @@ -43,7 +44,8 @@ public interface Configurable { * This method is called just once, following instantiation. * * @param params param values, keyed by parameter name + * @param classLoaderService */ - public void configure(Type type, Properties params, Dialect d) throws MappingException; + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException; } diff --git a/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java new file mode 100644 index 0000000000..d179e4e6fc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.id; + +/** + * Describes the nature of the entity-defined identifier. + * + * @author Steve Ebersole +*/ +public enum EntityIdentifierNature { + /** + * A simple identifier. Resolved as a basic type and mapped to a singular, basic attribute. Equivalent of:

    + *
  • an {@code } mapping
  • + *
  • a single {@code @Id} annotation
  • + *
+ */ + SIMPLE, + + /** + * What Hibernate used to term an "embedded composite identifier", which is not to be confused with the JPA + * term embedded. Resolved as a tuple of basic type values and mapped over multiple singular attributes. + * Specifically a composite identifier where there is no single attribute representing the composite value. + * Equivalent of:
    + *
  • + * a {@code } mapping without a specified {@code name} XML-attribute (which would name + * the single identifier attribute + *
  • + *
  • + * multiple {@code @Id} annotations + *
  • + *
+ * + * NOTE : May or may not have a related "lookup identifier class" as indicated by a {@code @IdClass} annotation. + * + * @see javax.persistence.IdClass + */ + NON_AGGREGATED_COMPOSITE, + + /** + * Composite identifier mapped to a single entity attribute by means of an actual component class used to + * aggregate the tuple values. + * Equivalent of:
    + *
  • + * a {@code } mapping naming a single identifier attribute via the {@code name} XML-attribute + *
  • + *
  • + * an {@code @EmbeddedId} annotation + *
  • + *
+ * + * @see javax.persistence.EmbeddedId + */ + AGGREGATED_COMPOSITE +} diff --git a/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java index 5ce6fd5ca7..b8f14ca311 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java @@ -29,6 +29,7 @@ import java.util.Properties; import org.hibernate.MappingException; import org.hibernate.Session; import org.hibernate.TransientObjectException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.SessionImplementor; @@ -80,7 +81,7 @@ public class ForeignGenerator implements IdentifierGenerator, Configurable { } @Override - public void configure(Type type, Properties params, Dialect d) { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { propertyName = params.getProperty( "property" ); entityName = params.getProperty( ENTITY_NAME ); if ( propertyName==null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java index 1c027464cb..3ce7ef48cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java @@ -31,6 +31,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; @@ -71,7 +72,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable { return previousValueHolder.makeValueThenIncrement(); } - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { returnClass = type.getReturnedClass(); ObjectNameNormalizer normalizer = diff --git a/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java index 175e27207f..fdd2734c39 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java @@ -34,6 +34,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; @@ -47,7 +48,12 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; import org.hibernate.jdbc.WorkExecutorVisitable; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -99,7 +105,12 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera private static final String DEFAULT_PK_COLUMN = "sequence_name"; private static final String DEFAULT_VALUE_COLUMN = "sequence_next_hi_value"; + private ObjectName qualifiedTableName; + private Identifier qualifiedPkColumnName; + private Identifier qualifiedValueColumnName; + private String tableName; + private Table table; private String pkColumnName; private String valueColumnName; private String query; @@ -143,6 +154,15 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera return tableName; } + /** + * The bound Table for this generator. + * + * @return The table. + */ + public final Table getTable() { + return table; + } + public synchronized Serializable generate(final SessionImplementor session, Object obj) { final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry() .getService( JdbcServices.class ) @@ -268,35 +288,35 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera } } - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); tableName = normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( ID_TABLE, params, DEFAULT_TABLE ) ); if ( tableName.indexOf( '.' ) < 0 ) { - tableName = dialect.quote( tableName ); - final String schemaName = dialect.quote( - normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ) - ); - final String catalogName = dialect.quote( - normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ) - ); - tableName = Table.qualify( catalogName, schemaName, tableName ); + final String normalizedTableName = tableName; + final String normalizedSchemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); + final String normalizedCatalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); + qualifiedTableName = new ObjectName( normalizedCatalogName, normalizedSchemaName, normalizedTableName ); + tableName = qualifiedTableName.toText( dialect ); } else { - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + qualifiedTableName = ObjectName.parse( tableName ); } - pkColumnName = dialect.quote( + qualifiedPkColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN ) ) ); - valueColumnName = dialect.quote( + pkColumnName = qualifiedPkColumnName.getText( dialect ); + + qualifiedValueColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN ) ) ); + valueColumnName = qualifiedValueColumnName.getText( dialect ); + keySize = ConfigurationHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH); String keyValue = ConfigurationHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) ); @@ -332,4 +352,20 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera hiloOptimizer = new LegacyHiLoAlgorithmOptimizer( returnClass, maxLo ); } } + + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + + final Schema schema = database.getSchemaFor( qualifiedTableName ); + table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + final Column pkColumn = table.createColumn( qualifiedPkColumnName ); + table.getPrimaryKey().addColumn( pkColumn ); + // todo : leverage TypeInfo-like info from JdbcEnvironment + pkColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) ); + + final Column valueColumn = table.createColumn( qualifiedValueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.INTEGER ) ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java index 2692c67398..a96e8b0fdc 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java @@ -24,6 +24,7 @@ package org.hibernate.id; import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.ExportableProducer; /** * An IdentifierGenerator that requires creation of database objects. @@ -35,7 +36,7 @@ import org.hibernate.dialect.Dialect; * @see Configurable * @author Gavin King */ -public interface PersistentIdentifierGenerator extends IdentifierGenerator { +public interface PersistentIdentifierGenerator extends IdentifierGenerator, ExportableProducer { /** * The configuration parameter holding the schema name diff --git a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java index e0b7d28816..b8f2572058 100755 --- a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java @@ -32,6 +32,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.insert.AbstractSelectingDelegate; @@ -52,7 +53,7 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf private String uniqueKeyPropertyName; - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { uniqueKeyPropertyName = params.getProperty( "key" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java index 6c26f4ed28..5e0c9a7ce4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java @@ -29,17 +29,20 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; +import org.jboss.logging.Logger; + import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - /** * sequence
*
@@ -50,12 +53,19 @@ import org.jboss.logging.Logger; * * @see SequenceHiLoGenerator * @author Gavin King + * + * @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} instead */ +@Deprecated public class SequenceGenerator implements PersistentIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, Configurable { private static final Logger LOG = Logger.getLogger( SequenceGenerator.class.getName() ); + public SequenceGenerator() { + LOG.warn( "Encountered use of deprecated " + getClass().getName() + " class" ); + } + /** * The sequence parameter */ @@ -67,6 +77,8 @@ public class SequenceGenerator */ public static final String PARAMETERS = "parameters"; + private ObjectName qualifiedSequenceName; + private String sequenceName; private String parameters; private Type identifierType; @@ -85,29 +97,24 @@ public class SequenceGenerator } @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); sequenceName = normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( SEQUENCE, params, "hibernate_sequence" ) ); - parameters = params.getProperty( PARAMETERS ); - if ( sequenceName.indexOf( '.' ) < 0 ) { final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - sequenceName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( sequenceName ) - ); + sequenceName = new ObjectName( catalogName, schemaName, sequenceName ).toText( dialect ); + this.qualifiedSequenceName = new ObjectName( catalogName, schemaName, sequenceName ); } else { - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + this.qualifiedSequenceName = ObjectName.parse( sequenceName ); } + this.parameters = params.getProperty( PARAMETERS ); this.identifierType = type; - sql = dialect.getSequenceNextValString( sequenceName ); + this.sql = dialect.getSequenceNextValString( sequenceName ); } @Override @@ -149,6 +156,14 @@ public class SequenceGenerator return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() ); } + @Override + public void registerExportables(Database database) { + final Schema schema = database.getSchemaFor( qualifiedSequenceName ); + if ( schema.locateSequence( qualifiedSequenceName.getName() ) == null ) { + schema.createSequence( qualifiedSequenceName.getName(), 1, 1 ); + } + } + @Override @SuppressWarnings( {"deprecation"}) public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java index e0bfa069af..c9878c58d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java @@ -26,6 +26,7 @@ import java.io.Serializable; import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.enhanced.AccessCallback; @@ -51,8 +52,8 @@ public class SequenceHiLoGenerator extends SequenceGenerator { private LegacyHiLoAlgorithmOptimizer hiloOptimizer; - public void configure(Type type, Properties params, Dialect d) throws MappingException { - super.configure(type, params, d); + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { + super.configure(type, params, d, classLoaderService ); maxLo = ConfigurationHelper.getInt( MAX_LO, params, 9 ); diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java index 1c7490651d..df2c3e99b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java @@ -26,10 +26,10 @@ package org.hibernate.id; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.Properties; + +import org.jboss.logging.Logger; import org.hibernate.HibernateException; -import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.insert.AbstractReturningDelegate; @@ -37,9 +37,6 @@ import org.hibernate.id.insert.IdentifierGeneratingInsert; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.sql.Insert; -import org.hibernate.type.Type; - -import org.jboss.logging.Logger; /** * A generator which combines sequence generation with immediate retrieval @@ -75,11 +72,6 @@ public class SequenceIdentityGenerator return new Delegate( persister, dialect, getSequenceName() ); } - @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { - super.configure( type, params, dialect ); - } - public static class Delegate extends AbstractReturningDelegate { private final Dialect dialect; private final String sequenceNextValFragment; diff --git a/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java index 6c919253e9..9af5ce2f11 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java @@ -33,6 +33,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.LockMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; @@ -44,7 +45,8 @@ import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -73,8 +75,9 @@ import org.jboss.logging.Logger; * * @see TableHiLoGenerator * @author Gavin King - * - * @deprecated use {@link SequenceStyleGenerator} instead. + * + * @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} or + * {@link org.hibernate.id.enhanced.TableGenerator} instead */ @Deprecated public class TableGenerator implements PersistentIdentifierGenerator, Configurable { @@ -99,7 +102,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab private String query; private String update; - public void configure(Type type, Properties params, Dialect dialect) { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) { identifierType = type; ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); @@ -108,11 +111,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab if ( tableName.indexOf( '.' ) < 0 ) { final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - tableName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( tableName ) - ); + tableName = new ObjectName(catalogName, schemaName, tableName).toText( dialect ); } else { // if already qualified there is not much we can do in a portable manner so we pass it @@ -160,40 +159,50 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab // The loop ensures atomicity of the select + update even for no transaction or // read committed isolation level do { - final PreparedStatement qps = prepareStatement( connection, query, statementLogger, listeners ); + final PreparedStatement qps = prepareStatement( + connection, + query, + statementLogger, + listeners + ); try { ResultSet rs = executeQuery( qps, listeners ); if ( !rs.next() ) { String err = "could not read a hi value - you need to populate the table: " + tableName; - LOG.error(err); - throw new IdentifierGenerationException(err); + LOG.error( err ); + throw new IdentifierGenerationException( err ); } value.initialize( rs, 1 ); rs.close(); } - catch (SQLException e) { - LOG.error("Could not read a hi value", e); + catch ( SQLException e ) { + LOG.error( "Could not read a hi value", e ); throw e; } finally { qps.close(); } - final PreparedStatement ups = prepareStatement( connection, update, statementLogger, listeners ); + final PreparedStatement ups = prepareStatement( + connection, + update, + statementLogger, + listeners + ); try { value.copy().increment().bind( ups, 1 ); value.bind( ups, 2 ); rows = executeUpdate( ups, listeners ); } - catch (SQLException sqle) { - LOG.error(LOG.unableToUpdateHiValue(tableName), sqle); + catch ( SQLException sqle ) { + LOG.error( LOG.unableToUpdateHiValue( tableName ), sqle ); throw sqle; } finally { ups.close(); } } - while (rows==0); + while ( rows == 0 ); return value; } }, @@ -237,6 +246,11 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab } } + @Override + public void registerExportables(Database database) { + // not doing anything here as I expect this to go away + } + public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { dialect.getCreateTableString() + " " + tableName + " ( " diff --git a/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java index 60c3395980..df3b75d0ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java @@ -25,6 +25,7 @@ package org.hibernate.id; import java.io.Serializable; import java.util.Properties; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.enhanced.AccessCallback; @@ -63,8 +64,8 @@ public class TableHiLoGenerator extends TableGenerator { private int maxLo; @Override - public void configure(Type type, Properties params, Dialect d) { - super.configure( type, params, d ); + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { + super.configure( type, params, d, classLoaderService ); maxLo = ConfigurationHelper.getInt( MAX_LO, params, Short.MAX_VALUE ); if ( maxLo >= 1 ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java index 74ae7ad2dd..f020a726c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java @@ -29,6 +29,8 @@ import java.util.UUID; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.uuid.StandardRandomStrategy; @@ -36,7 +38,6 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.UUIDTypeDescriptor; - import org.jboss.logging.Logger; /** @@ -72,7 +73,7 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable { return generator; } - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { // check first for the strategy instance strategy = (UUIDGenerationStrategy) params.get( UUID_GEN_STRATEGY ); if ( strategy == null ) { @@ -80,7 +81,14 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable { final String strategyClassName = params.getProperty( UUID_GEN_STRATEGY_CLASS ); if ( strategyClassName != null ) { try { - final Class strategyClass = ReflectHelper.classForName( strategyClassName ); + final Class strategyClass; + // TODO: Exists purely for testing using the old .mappings. Eventually remove. + if (classLoaderService == null) { + strategyClass = ReflectHelper.classForName( strategyClassName ); + } + else { + strategyClass = classLoaderService.classForName( strategyClassName ); + } try { strategy = (UUIDGenerationStrategy) strategyClass.newInstance(); } @@ -88,9 +96,12 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable { LOG.unableToInstantiateUuidGenerationStrategy(ignore); } } - catch ( ClassNotFoundException ignore ) { + catch ( ClassLoadingException ignore ) { LOG.unableToLocateUuidGenerationStrategy(strategyClassName); } + catch ( ClassNotFoundException ignore ) { + LOG.unableToLocateUuidGenerationStrategy(strategyClassName); + } } } if ( strategy == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java index f8d4e42838..b1848111a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java @@ -26,6 +26,7 @@ package org.hibernate.id; import java.io.Serializable; import java.util.Properties; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.CoreMessageLogger; @@ -61,7 +62,7 @@ public class UUIDHexGenerator extends AbstractUUIDGenerator implements Configura } @Override - public void configure(Type type, Properties params, Dialect d) { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { sep = ConfigurationHelper.getString( "separator", params, "" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java index f0080150f9..15aa56651d 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java @@ -25,6 +25,7 @@ package org.hibernate.id.enhanced; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.metamodel.spi.relational.ExportableProducer; /** * Encapsulates definition of the underlying data structure backing a @@ -32,7 +33,7 @@ import org.hibernate.engine.spi.SessionImplementor; * * @author Steve Ebersole */ -public interface DatabaseStructure { +public interface DatabaseStructure extends ExportableProducer { /** * The name of the database structure (table or sequence). * @return The structure name. diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java index 822fd9289d..caf4fe218a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java @@ -25,9 +25,8 @@ package org.hibernate.id.enhanced; import java.lang.reflect.Constructor; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; - import org.jboss.logging.Logger; /** @@ -61,13 +60,15 @@ public class OptimizerFactory { * @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name. * @param returnClass The generated value java type * @param incrementSize The increment size. + * @param classLoaderService ClassLoaderService * * @return The built optimizer * * @deprecated Use {@link #buildOptimizer(String, Class, int, long)} instead */ @Deprecated - public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) { + public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, + ClassLoaderService classLoaderService) { final Class optimizerClass; final StandardOptimizerDescriptor standardDescriptor = StandardOptimizerDescriptor.fromExternalName( type ); @@ -76,7 +77,7 @@ public class OptimizerFactory { } else { try { - optimizerClass = ReflectHelper.classForName( type ); + optimizerClass = classLoaderService.classForName( type ); } catch( Throwable ignore ) { LOG.unableToLocateCustomOptimizerClass( type ); @@ -106,11 +107,12 @@ public class OptimizerFactory { * @param returnClass The generated value java type * @param incrementSize The increment size. * @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify). + * @param classLoaderService ClassLoaderService * * @return The built optimizer */ - public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue) { - final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize ); + public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue, ClassLoaderService classLoaderService) { + final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize, classLoaderService ); if ( InitialValueAwareOptimizer.class.isInstance( optimizer ) ) { ( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java index c1737d18bb..1c27a0dd17 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as + * Copyright (c) 2008, 2012, 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -22,19 +22,22 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.id.enhanced; - import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import org.jboss.logging.Logger; + import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.internal.CoreMessageLogger; - -import org.jboss.logging.Logger; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; /** * Describes a sequence. @@ -47,6 +50,7 @@ public class SequenceStructure implements DatabaseStructure { SequenceStructure.class.getName() ); + private ObjectName qualifiedSequenceName; private final String sequenceName; private final int initialValue; private final int incrementSize; @@ -57,11 +61,12 @@ public class SequenceStructure implements DatabaseStructure { public SequenceStructure( Dialect dialect, - String sequenceName, + ObjectName qualifiedSequenceName, int initialValue, int incrementSize, Class numberType) { - this.sequenceName = sequenceName; + this.qualifiedSequenceName = qualifiedSequenceName; + this.sequenceName = qualifiedSequenceName.toText( dialect ); this.initialValue = initialValue; this.incrementSize = incrementSize; this.numberType = numberType; @@ -142,6 +147,19 @@ public class SequenceStructure implements DatabaseStructure { applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues(); } + @Override + public void registerExportables(Database database) { + final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1; + final Schema schema = database.getSchemaFor( qualifiedSequenceName ); + Sequence sequence = schema.locateSequence( qualifiedSequenceName.getName() ); + if ( sequence != null ) { + sequence.validate( initialValue, sourceIncrementSize ); + } + else { + schema.createSequence( qualifiedSequenceName.getName(), initialValue, sourceIncrementSize ); + } + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1; diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java index bcd321196f..948c9a6bbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java @@ -26,8 +26,11 @@ package org.hibernate.id.enhanced; import java.io.Serializable; import java.util.Properties; +import org.jboss.logging.Logger; + import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; @@ -37,11 +40,11 @@ import org.hibernate.id.Configurable; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - /** * Generates identifier values based on an sequence-style database structure. * Variations range from actually using a sequence to using a table to mimic @@ -227,11 +230,12 @@ public class SequenceStyleGenerator // Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { this.identifierType = type; boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, params, false ); - final String sequenceName = determineSequenceName( params, dialect ); + final ObjectName qualifiedSequenceName = determineSequenceName( params, dialect ); + final String sequenceNameText = qualifiedSequenceName.toText( dialect ); final int initialValue = determineInitialValue( params ); int incrementSize = determineIncrementSize( params ); @@ -251,7 +255,7 @@ public class SequenceStyleGenerator params, dialect, forceTableUse, - sequenceName, + qualifiedSequenceName, initialValue, incrementSize ); @@ -259,7 +263,8 @@ public class SequenceStyleGenerator optimizationStrategy, identifierType.getReturnedClass(), incrementSize, - ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ) + ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ), + classLoaderService ); this.databaseStructure.prepare( optimizer ); } @@ -274,28 +279,25 @@ public class SequenceStyleGenerator * @param dialect The dialect in effect * @return The sequence name */ - protected String determineSequenceName(Properties params, Dialect dialect) { - final String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX ); + protected ObjectName determineSequenceName(Properties params, Dialect dialect) { + String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX ); // JPA_ENTITY_NAME value honors (HBM) and @Entity#name (JPA) overrides. String sequenceName = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEQUENCE_PER_ENTITY, params, false ) ? params.getProperty( JPA_ENTITY_NAME ) + sequencePerEntitySuffix : DEF_SEQUENCE_NAME; - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); - sequenceName = ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName ); + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); + sequenceName = normalizer.normalizeIdentifierQuoting( + ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName ) + ); if ( sequenceName.indexOf( '.' ) < 0 ) { - sequenceName = normalizer.normalizeIdentifierQuoting( sequenceName ); - final String schemaName = params.getProperty( SCHEMA ); - final String catalogName = params.getProperty( CATALOG ); - sequenceName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( sequenceName ) - ); - } - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); + final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - return sequenceName; + return new ObjectName( catalogName, schemaName, sequenceName ); + } + else { + return ObjectName.parse( sequenceName ); + } } /** @@ -309,10 +311,10 @@ public class SequenceStyleGenerator * @param dialect The dialect in effect. * @return The value column name */ - protected String determineValueColumnName(Properties params, Dialect dialect) { - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); + protected Identifier determineValueColumnName(Properties params, Dialect dialect) { + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + return Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); } /** @@ -401,7 +403,7 @@ public class SequenceStyleGenerator Properties params, Dialect dialect, boolean forceTableUse, - String sequenceName, + ObjectName sequenceName, int initialValue, int incrementSize) { final boolean useSequence = dialect.supportsSequences() && !forceTableUse; @@ -409,7 +411,7 @@ public class SequenceStyleGenerator return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize, type.getReturnedClass() ); } else { - final String valueColumnName = determineValueColumnName( params, dialect ); + Identifier valueColumnName = determineValueColumnName( params, dialect ); return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize, type.getReturnedClass() ); } } @@ -430,6 +432,11 @@ public class SequenceStyleGenerator return databaseStructure.getName(); } + @Override + public void registerExportables(Database database) { + databaseStructure.registerExportables( database ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return databaseStructure.sqlCreateStrings( dialect ); diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index 50fe25ac18..773a16f1c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -37,6 +37,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; @@ -53,7 +54,11 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -226,7 +231,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab private Type identifierType; + private ObjectName qualifiedTableName; + private Identifier qualifiedSegmentColumnName; + private Identifier qualifiedValueColumnName; + private String tableName; + private Table table; private String segmentColumnName; private String segmentValue; @@ -266,6 +276,15 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab return tableName; } + /** + * The bound Table for this generator. + * + * @return The table. + */ + public final Table getTable() { + return table; + } + /** * The name of the column in which we store the segment to which each row * belongs. The value here acts as PK. @@ -349,7 +368,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab } @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { identifierType = type; tableName = determineGeneratorTableName( params, dialect ); @@ -379,14 +398,15 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab optimizationStrategy, identifierType.getReturnedClass(), incrementSize, - ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ) + ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ), + classLoaderService ); } /** * Determine the table name to use for the generator values. *

- * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getTableName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -394,22 +414,23 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab * @return The table name to use. */ protected String determineGeneratorTableName(Properties params, Dialect dialect) { - String name = ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE ); + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); + String name = normalizer.normalizeIdentifierQuoting( + ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE ) + ); final boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0; if ( isGivenNameUnqualified ) { - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); - name = normalizer.normalizeIdentifierQuoting( name ); // if the given name is un-qualified we may neen to qualify it final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - name = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( name) - ); + + qualifiedTableName = new ObjectName( catalogName, schemaName, name ); + + name = qualifiedTableName.toText( dialect ); + } + else { + qualifiedTableName = ObjectName.parse( name ); } - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. return name; } @@ -418,7 +439,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab * Determine the name of the column used to indicate the segment for each * row. This column acts as the primary key. *

- * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentColumnName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -428,13 +449,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab protected String determineSegmentColumnName(Properties params, Dialect dialect) { final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + qualifiedSegmentColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); + return qualifiedSegmentColumnName.getText( dialect ); } /** * Determine the name of the column in which we will store the generator persistent value. *

- * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getValueColumnName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -444,13 +466,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab protected String determineValueColumnName(Properties params, Dialect dialect) { final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + qualifiedValueColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); + return qualifiedValueColumnName.getText( dialect ); } /** * Determine the segment value corresponding to this generator instance. *

- * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentValue() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -472,16 +495,20 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab * @return The default segment value to use. */ protected String determineDefaultSegmentValue(Properties params) { - final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false ); + final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( + CONFIG_PREFER_SEGMENT_PER_ENTITY, + params, + false + ); final String defaultToUse = preferSegmentPerEntity ? params.getProperty( TABLE ) : DEF_SEGMENT_VALUE; - LOG.usingDefaultIdGeneratorSegmentValue( tableName, segmentColumnName, defaultToUse ); + LOG.usingDefaultIdGeneratorSegmentValue( qualifiedTableName.toString(), segmentColumnName, defaultToUse ); return defaultToUse; } /** * Determine the size of the {@link #getSegmentColumnName segment column} *

- * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentValueLength() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -502,7 +529,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab protected String buildSelectQuery(Dialect dialect) { final String alias = "tbl"; final String query = "select " + StringHelper.qualify( alias, valueColumnName ) + - " from " + tableName + ' ' + alias + + " from " + qualifiedTableName.toText( dialect ) + ' ' + alias + " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?"; final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE ); lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE ); @@ -511,7 +538,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab } protected String buildUpdateQuery() { - return "update " + tableName + + return "update " + qualifiedTableName.toText( ) + " set " + valueColumnName + "=? " + " where " + valueColumnName + "=? and " + segmentColumnName + "=?"; } @@ -535,76 +562,98 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab new AccessCallback() { @Override public IntegralDataTypeHolder getNextValue() { - return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork( - new AbstractReturningWork() { - @Override - public IntegralDataTypeHolder execute(Connection connection) throws SQLException { - final IntegralDataTypeHolder value = makeValue(); - int rows; - do { - final PreparedStatement selectPS = prepareStatement( connection, selectQuery, statementLogger, statsCollector ); + return session.getTransactionCoordinator() + .getTransaction() + .createIsolationDelegate() + .delegateWork( + new AbstractReturningWork() { + @Override + public IntegralDataTypeHolder execute(Connection connection) + throws SQLException { + final IntegralDataTypeHolder value = makeValue(); + int rows; + do { + final PreparedStatement selectPS = prepareStatement( + connection, + selectQuery, + statementLogger, + statsCollector + ); - try { - selectPS.setString( 1, segmentValue ); - final ResultSet selectRS = executeQuery( selectPS, statsCollector ); - if ( !selectRS.next() ) { - value.initialize( initialValue ); - - final PreparedStatement insertPS = prepareStatement( connection, insertQuery, statementLogger, statsCollector ); try { - insertPS.setString( 1, segmentValue ); - value.bind( insertPS, 2 ); - executeUpdate( insertPS, statsCollector ); + selectPS.setString( 1, segmentValue ); + final ResultSet selectRS = executeQuery( + selectPS, + statsCollector + ); + if ( !selectRS.next() ) { + value.initialize( initialValue ); + + final PreparedStatement insertPS = prepareStatement( + connection, + insertQuery, + statementLogger, + statsCollector + ); + try { + insertPS.setString( 1, segmentValue ); + value.bind( insertPS, 2 ); + executeUpdate( insertPS, statsCollector ); + } + finally { + insertPS.close(); + } + } + else { + value.initialize( selectRS, 1 ); + } + selectRS.close(); + } + catch ( SQLException e ) { + LOG.unableToReadOrInitHiValue( e ); + throw e; } finally { - insertPS.close(); + selectPS.close(); + } + + + final PreparedStatement updatePS = prepareStatement( + connection, + updateQuery, + statementLogger, + statsCollector + ); + try { + final IntegralDataTypeHolder updateValue = value.copy(); + if ( optimizer.applyIncrementSizeToSourceValues() ) { + updateValue.add( incrementSize ); + } + else { + updateValue.increment(); + } + updateValue.bind( updatePS, 1 ); + value.bind( updatePS, 2 ); + updatePS.setString( 3, segmentValue ); + rows = executeUpdate( updatePS, statsCollector ); + } + catch ( SQLException e ) { + LOG.unableToUpdateQueryHiValue( tableName, e ); + throw e; + } + finally { + updatePS.close(); } } - else { - value.initialize( selectRS, 1 ); - } - selectRS.close(); - } - catch (SQLException e) { - LOG.unableToReadOrInitHiValue( e ); - throw e; - } - finally { - selectPS.close(); - } + while ( rows == 0 ); + accessCount++; - final PreparedStatement updatePS = prepareStatement( connection, updateQuery, statementLogger, statsCollector ); - try { - final IntegralDataTypeHolder updateValue = value.copy(); - if ( optimizer.applyIncrementSizeToSourceValues() ) { - updateValue.add( incrementSize ); - } - else { - updateValue.increment(); - } - updateValue.bind( updatePS, 1 ); - value.bind( updatePS, 2 ); - updatePS.setString( 3, segmentValue ); - rows = executeUpdate( updatePS, statsCollector ); + return value; } - catch (SQLException e) { - LOG.unableToUpdateQueryHiValue( tableName, e ); - throw e; - } - finally { - updatePS.close(); - } - } - while ( rows == 0 ); - - accessCount++; - - return value; - } - }, - true - ); + }, + true + ); } @Override @@ -651,6 +700,24 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab } } + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + + table = database.getSchemaFor( qualifiedTableName ) + .createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + Column segmentColumn = table.createColumn( qualifiedSegmentColumnName ); + table.getPrimaryKey().addColumn( segmentColumn ); + // todo : leverage TypeInfo-like info from JdbcEnvironment + segmentColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, segmentValueLength, 0, 0 ) ); + segmentColumn.setNullable( false ); + + Column valueColumn = table.createColumn( qualifiedValueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) ); + valueColumn.setNullable( false ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java index 6f5c8f69cc..06b3617458 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java @@ -42,6 +42,13 @@ import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.jdbc.AbstractReturningWork; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.InitCommand; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; import org.jboss.logging.Logger; @@ -56,8 +63,10 @@ public class TableStructure implements DatabaseStructure { TableStructure.class.getName() ); + private final ObjectName qualifiedTableName; + private final Identifier valueColumnName; + private final String tableName; - private final String valueColumnName; private final int initialValue; private final int incrementSize; private final Class numberType; @@ -69,24 +78,27 @@ public class TableStructure implements DatabaseStructure { public TableStructure( Dialect dialect, - String tableName, - String valueColumnName, + ObjectName qualifiedTableName, + Identifier valueColumnName, int initialValue, int incrementSize, Class numberType) { - this.tableName = tableName; + this.qualifiedTableName = qualifiedTableName; + this.valueColumnName = valueColumnName; + this.tableName = qualifiedTableName.toText( dialect ); this.initialValue = initialValue; this.incrementSize = incrementSize; - this.valueColumnName = valueColumnName; this.numberType = numberType; - selectQuery = "select " + valueColumnName + " as id_val" + + String valueColumnNameText = valueColumnName.getText( dialect ); + + selectQuery = "select " + valueColumnNameText + " as id_val" + " from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) + dialect.getForUpdateString(); updateQuery = "update " + tableName + - " set " + valueColumnName + "= ?" + - " where " + valueColumnName + "=?"; + " set " + valueColumnNameText + "= ?" + + " where " + valueColumnNameText + "=?"; } @Override @@ -224,6 +236,25 @@ public class TableStructure implements DatabaseStructure { } } + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + final Schema schema = database.getSchemaFor( qualifiedTableName ); + Table table = schema.locateTable( qualifiedTableName.getName() ); + if ( table != null ) { + return; + } + + table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + Column valueColumn = table.createColumn( valueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) ); + + database.addInitCommand( + new InitCommand( "insert into " + tableName + " values ( " + initialValue + " )" ) + ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { diff --git a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java index 0f4e4d98ff..7368f24a37 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java @@ -28,6 +28,8 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.id.Assigned; @@ -52,7 +54,6 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -66,6 +67,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener DefaultIdentifierGeneratorFactory.class.getName()); private transient Dialect dialect; + private transient ClassLoaderService classLoaderService; private ConcurrentHashMap generatorStrategyToClassNameMap = new ConcurrentHashMap(); /** @@ -88,7 +90,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener register( "enhanced-sequence", SequenceStyleGenerator.class ); register( "enhanced-table", TableGenerator.class ); } - + @Override public void register(String strategy, Class generatorClass) { LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() ); final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass ); @@ -114,7 +116,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener Class clazz = getIdentifierGeneratorClass( strategy ); IdentifierGenerator identifierGenerator = ( IdentifierGenerator ) clazz.newInstance(); if ( identifierGenerator instanceof Configurable ) { - ( ( Configurable ) identifierGenerator ).configure( type, config, dialect ); + ( ( Configurable ) identifierGenerator ).configure( type, config, dialect, classLoaderService ); } return identifierGenerator; } @@ -133,9 +135,19 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener Class generatorClass = generatorStrategyToClassNameMap.get( strategy ); try { if ( generatorClass == null ) { - generatorClass = ReflectHelper.classForName( strategy ); + // TODO: Exists purely for testing using the old .mappings. Eventually remove. + if (classLoaderService == null) { + generatorClass = ReflectHelper.classForName( strategy ); + } + else { + generatorClass = classLoaderService.classForName( strategy ); + } + register( strategy, generatorClass ); } } + catch ( ClassLoadingException e ) { + throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) ); + } catch ( ClassNotFoundException e ) { throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) ); } @@ -145,5 +157,6 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { this.dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java b/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java index 8b748c78f4..a8fd06e468 100644 --- a/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java +++ b/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java @@ -25,7 +25,7 @@ package org.hibernate.integrator.spi; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index 16c0f54b2f..80cdb924ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -1674,4 +1674,46 @@ public interface CoreMessageLogger extends BasicLogger { "(%2$s=true)" ) void applyingExplicitDiscriminatorColumnForJoined(String className, String overrideSetting); + + @Message(value = "@CollectionTable and @JoinTable specified on the same attribute. Check %s#%s", id = 458) + String collectionTableAndJoinTableUsedTogether(String entityName, String propertyName); + + @Message(value = "@CollectionTable annotation without a @ElementCollection. Check %s#%s", id = 459) + String collectionTableWithoutElementCollection(String entityName, String propertyName); + + @Message(value = "@JoinTable annotation without an association. Check %s#%s", id = 460) + String joinTableForNonAssociationAttribute(String entityName, String propertyName); + + @LogMessage( level = ERROR ) + @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 461 ) + void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName, + String attributeName, + String attributeJavaType, + String metamodelFieldJavaType ); + // moved from EntityManagerMessageLogger w/ id 15007 + + @LogMessage( level = ERROR ) + @Message( value = "Unable to locate static metamodel field : %s#%s", id = 462 ) + void unableToLocateStaticMetamodelField( String metamodelClassName, + String attributeName ); + // moved from EntityManagerMessageLogger w/ id 15011 + + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter)", id = 463) + String accessTypeOverrideShouldBeAnnotatedOnProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + + "Using AccessType.FIELD on the property has no effect", id = 464) + String accessTypeOverrideShouldBeProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field ", id = 465) + String accessTypeOverrideShouldBeAnnotatedOnField( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field with an access type of AccessType.FIELD. " + + "Using AccessType.PROPERTY on the field has no effect", id = 466) + String accessTypeOverrideShouldBeField( String className ); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java b/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java new file mode 100644 index 0000000000..a14fee4c88 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.internal; + +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.Session; +import org.hibernate.persister.entity.EntityPersister; + +/** + * The default implementation of {@link CustomEntityDirtinessStrategy} which does nada. + * + * @author Steve Ebersole + */ +public class DefaultCustomEntityDirtinessStrategy implements CustomEntityDirtinessStrategy { + public static final DefaultCustomEntityDirtinessStrategy INSTANCE = new DefaultCustomEntityDirtinessStrategy(); + + @Override + public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) { + return false; + } + + @Override + public boolean isDirty(Object entity, EntityPersister persister, Session session) { + return false; + } + + @Override + public void resetDirty(Object entity, EntityPersister persister, Session session) { + } + + @Override + public void findDirty( + Object entity, + EntityPersister persister, + Session session, + DirtyCheckContext dirtyCheckContext) { + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java b/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java index 7ae640910f..f5e89b4e39 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java @@ -29,9 +29,11 @@ import java.util.Map; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.persister.entity.Joinable; /** + * Captures all relevant metadata specified as part of defining the filter. * * @author Rob Worsnop */ @@ -42,14 +44,52 @@ public class FilterConfiguration { private final Map aliasTableMap; private final Map aliasEntityMap; private final PersistentClass persistentClass; - - public FilterConfiguration(String name, String condition, boolean autoAliasInjection, Map aliasTableMap, Map aliasEntityMap, PersistentClass persistentClass) { + private final EntityBinding entityBinding; + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap){ + this.name = name; + this.condition = condition; + this.autoAliasInjection = autoAliasInjection; + this.aliasTableMap = aliasTableMap; + this.aliasEntityMap = aliasEntityMap; + this.entityBinding = null; + this.persistentClass = null; + } + + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap, + PersistentClass persistentClass) { this.name = name; this.condition = condition; this.autoAliasInjection = autoAliasInjection; this.aliasTableMap = aliasTableMap; this.aliasEntityMap = aliasEntityMap; this.persistentClass = persistentClass; + this.entityBinding = null; + } + + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap, + EntityBinding entityBinding) { + this.name = name; + this.condition = condition; + this.autoAliasInjection = autoAliasInjection; + this.aliasTableMap = aliasTableMap; + this.aliasEntityMap = aliasEntityMap; + this.persistentClass = null; + this.entityBinding = entityBinding; } public String getName() { @@ -65,28 +105,38 @@ public class FilterConfiguration { } public Map getAliasTableMap(SessionFactoryImplementor factory) { - Map mergedAliasTableMap = mergeAliasMaps(factory); - if (!mergedAliasTableMap.isEmpty()){ + Map mergedAliasTableMap = mergeAliasMaps( factory ); + if ( !mergedAliasTableMap.isEmpty() ) { return mergedAliasTableMap; - } else if (persistentClass != null){ - String table = persistentClass.getTable().getQualifiedName(factory.getDialect(), + } + else if ( persistentClass != null ) { + String table = persistentClass.getTable().getQualifiedName( + factory.getDialect(), factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName()); - return Collections.singletonMap(null, table); - } else{ + factory.getSettings().getDefaultSchemaName() + ); + return Collections.singletonMap( null, table ); + } + else if ( entityBinding != null ) { + String table = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); + return Collections.singletonMap( null, table ); + } + else { return Collections.emptyMap(); } } - - private Map mergeAliasMaps(SessionFactoryImplementor factory){ - Map ret = new HashMap(); - if (aliasTableMap != null){ - ret.putAll(aliasTableMap); + + private Map mergeAliasMaps(SessionFactoryImplementor factory) { + Map ret = new HashMap(); + if ( aliasTableMap != null ) { + ret.putAll( aliasTableMap ); } - if (aliasEntityMap != null){ - for (Map.Entry entry : aliasEntityMap.entrySet()){ - ret.put(entry.getKey(), - Joinable.class.cast(factory.getEntityPersister(entry.getValue())).getTableName()); + if ( aliasEntityMap != null ) { + for ( Map.Entry entry : aliasEntityMap.entrySet() ) { + ret.put( + entry.getKey(), + Joinable.class.cast( factory.getEntityPersister( entry.getValue() ) ).getTableName() + ); } } return ret; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 8e6d28f09b..f70f0803ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -43,6 +43,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.naming.Reference; import javax.naming.StringRefAddr; +import javax.persistence.metamodel.Metamodel; import org.hibernate.AssertionFailure; import org.hibernate.Cache; @@ -66,6 +67,7 @@ import org.hibernate.TypeHelper; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.cache.internal.CacheDataDescriptionImpl; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; @@ -83,7 +85,6 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; -import org.hibernate.cfg.SettingsFactory; import org.hibernate.cfg.annotations.NamedProcedureCallDefinition; import org.hibernate.context.internal.JTASessionContext; import org.hibernate.context.internal.ManagedSessionContext; @@ -125,14 +126,16 @@ import org.hibernate.id.UUIDGenerator; import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; +import org.hibernate.jpa.metamodel.internal.JpaMetaModelPopulationSetting; +import org.hibernate.jpa.metamodel.internal.builder.MetamodelBuilder; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; @@ -216,20 +219,53 @@ public final class SessionFactoryImpl private final transient TypeHelper typeHelper; private final transient TransactionEnvironment transactionEnvironment; private final transient SessionFactoryOptions sessionFactoryOptions; - private final transient CustomEntityDirtinessStrategy customEntityDirtinessStrategy; - private final transient CurrentTenantIdentifierResolver currentTenantIdentifierResolver; + private final transient Metamodel jpaMetamodel; @SuppressWarnings( {"unchecked", "ThrowableResultOfMethodCallIgnored"}) public SessionFactoryImpl( final Configuration cfg, Mapping mapping, final ServiceRegistry serviceRegistry, - Settings settings, - SessionFactoryObserver observer) throws HibernateException { + final Settings settings, + final SessionFactoryObserver userObserver) throws HibernateException { LOG.debug( "Building session factory" ); sessionFactoryOptions = new SessionFactoryOptions() { - private EntityNotFoundDelegate entityNotFoundDelegate; + private final Interceptor interceptor; + private final CustomEntityDirtinessStrategy customEntityDirtinessStrategy; + private final CurrentTenantIdentifierResolver currentTenantIdentifierResolver; + private final EntityNotFoundDelegate entityNotFoundDelegate; + + { + interceptor = cfg.getInterceptor(); + + customEntityDirtinessStrategy = serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy( + CustomEntityDirtinessStrategy.class, + cfg.getProperties().get( AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY ), + DefaultCustomEntityDirtinessStrategy.INSTANCE + ); + + if ( cfg.getCurrentTenantIdentifierResolver() != null ) { + currentTenantIdentifierResolver = cfg.getCurrentTenantIdentifierResolver(); + } + else { + currentTenantIdentifierResolver =serviceRegistry.getService( StrategySelector.class ).resolveStrategy( + CurrentTenantIdentifierResolver.class, + cfg.getProperties().get( AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER ) + ); + } + + if ( cfg.getEntityNotFoundDelegate() != null ) { + entityNotFoundDelegate = cfg.getEntityNotFoundDelegate(); + } + else { + entityNotFoundDelegate = new EntityNotFoundDelegate() { + public void handleEntityNotFound(String entityName, Serializable id) { + throw new ObjectNotFoundException( id, entityName ); + } + }; + } + } @Override public StandardServiceRegistry getServiceRegistry() { @@ -238,22 +274,39 @@ public final class SessionFactoryImpl @Override public Interceptor getInterceptor() { - return cfg.getInterceptor(); + return interceptor; + } + + @Override + public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { + return customEntityDirtinessStrategy; + } + + @Override + public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { + return currentTenantIdentifierResolver; + } + + @Override + public SessionFactoryObserver[] getSessionFactoryObservers() { + return userObserver == null + ? new SessionFactoryObserver[0] + : new SessionFactoryObserver[] { userObserver }; + } + + @Override + public EntityNameResolver[] getEntityNameResolvers() { + return new EntityNameResolver[0]; + } + + @Override + public Settings getSettings() { + return settings; } @Override public EntityNotFoundDelegate getEntityNotFoundDelegate() { if ( entityNotFoundDelegate == null ) { - if ( cfg.getEntityNotFoundDelegate() != null ) { - entityNotFoundDelegate = cfg.getEntityNotFoundDelegate(); - } - else { - entityNotFoundDelegate = new EntityNotFoundDelegate() { - public void handleEntityNotFound(String entityName, Serializable id) { - throw new ObjectNotFoundException( id, entityName ); - } - }; - } } return entityNotFoundDelegate; } @@ -272,7 +325,7 @@ public final class SessionFactoryImpl this.dialect = this.jdbcServices.getDialect(); this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class ); this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() ); - if ( observer != null ) { + for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) { this.observer.addObserver( observer ); } @@ -481,6 +534,12 @@ public final class SessionFactoryImpl persister.postInstantiate(); registerEntityNameResolvers( persister ); } + if ( sessionFactoryOptions.getEntityNameResolvers() != null ) { + for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) { + registerEntityNameResolver( resolver ); + } + } + for ( CollectionPersister persister : collectionPersisters.values() ) { persister.postInstantiate(); } @@ -582,10 +641,20 @@ public final class SessionFactoryImpl fetchProfiles.put( fetchProfile.getName(), fetchProfile ); } - this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy(); - this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( cfg.getCurrentTenantIdentifierResolver() ); this.transactionEnvironment = new TransactionEnvironmentImpl( this ); this.observer.sessionFactoryCreated( this ); + + final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg ); + if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) { + this.jpaMetamodel = org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl.buildMetamodel( + cfg.getClassMappings(), + this, + jpaMetaModelPopulationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED + ); + } + else { + jpaMetamodel = null; + } } private Map toProcedureCallMementos( @@ -626,59 +695,16 @@ public final class SessionFactoryImpl }; } - @SuppressWarnings({ "unchecked" }) - private CustomEntityDirtinessStrategy determineCustomEntityDirtinessStrategy() { - CustomEntityDirtinessStrategy defaultValue = new CustomEntityDirtinessStrategy() { - @Override - public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) { - return false; - } - - @Override - public boolean isDirty(Object entity, EntityPersister persister, Session session) { - return false; - } - - @Override - public void resetDirty(Object entity, EntityPersister persister, Session session) { - } - - @Override - public void findDirty( - Object entity, - EntityPersister persister, - Session session, - DirtyCheckContext dirtyCheckContext) { - // todo : implement proper method body - } - }; - return serviceRegistry.getService( ConfigurationService.class ).getSetting( - AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY, - CustomEntityDirtinessStrategy.class, - defaultValue - ); - } - - @SuppressWarnings({ "unchecked" }) - private CurrentTenantIdentifierResolver determineCurrentTenantIdentifierResolver( - CurrentTenantIdentifierResolver explicitResolver) { - if ( explicitResolver != null ) { - return explicitResolver; - } - return serviceRegistry.getService( ConfigurationService.class ) - .getSetting( - AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, - CurrentTenantIdentifierResolver.class, - null - ); + protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) { + final String setting = cfg.getProperties().getProperty( AvailableSettings.JPA_METAMODEL_POPULATION ); + return JpaMetaModelPopulationSetting.parse( setting ); } @SuppressWarnings( {"ThrowableResultOfMethodCallIgnored"}) public SessionFactoryImpl( MetadataImplementor metadata, - SessionFactoryOptions sessionFactoryOptions, - SessionFactoryObserver observer) throws HibernateException { + SessionFactoryOptions providedSessionFactoryOptions) throws HibernateException { final boolean traceEnabled = LOG.isTraceEnabled(); final boolean debugEnabled = traceEnabled || LOG.isDebugEnabled(); @@ -686,17 +712,13 @@ public final class SessionFactoryImpl LOG.debug( "Building session factory" ); } - this.sessionFactoryOptions = sessionFactoryOptions; + this.sessionFactoryOptions = providedSessionFactoryOptions; this.properties = createPropertiesFromMap( metadata.getServiceRegistry().getService( ConfigurationService.class ).getSettings() ); - // TODO: these should be moved into SessionFactoryOptions - this.settings = new SettingsFactory().buildSettings( - properties, - metadata.getServiceRegistry() - ); + this.settings = sessionFactoryOptions.getSettings(); this.serviceRegistry = sessionFactoryOptions.getServiceRegistry() @@ -714,17 +736,16 @@ public final class SessionFactoryImpl // TODO: get SQL functions from a new service // this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() ); - if ( observer != null ) { - this.observer.addObserver( observer ); + if ( sessionFactoryOptions.getSessionFactoryObservers() != null ) { + for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) { + this.observer.addObserver( observer ); + } } this.typeResolver = metadata.getTypeResolver().scope( this ); this.typeHelper = new TypeLocatorImpl( typeResolver ); - this.filters = new HashMap(); - for ( FilterDefinition filterDefinition : metadata.getFilterDefinitions() ) { - filters.put( filterDefinition.getFilterName(), filterDefinition ); - } + this.filters = Collections.unmodifiableMap( metadata.getFilterDefinitions() ); if ( debugEnabled ) { LOG.debugf( "Session factory constructed with filter configurations : %s", filters ); @@ -772,14 +793,21 @@ public final class SessionFactoryImpl // Prepare persisters and link them up with their cache // region/access-strategy + final MetamodelBuilder jpaMetamodelBuilder = new MetamodelBuilder( + this, + JpaMetaModelPopulationSetting.parse( + properties.getProperty( AvailableSettings.JPA_METAMODEL_POPULATION ) + ) + ); + StringBuilder stringBuilder = new StringBuilder(); if ( settings.getCacheRegionPrefix() != null) { stringBuilder .append( settings.getCacheRegionPrefix() ) .append( '.' ); } + RegionFactory regionFactory = cacheAccess.getRegionFactory(); final String cacheRegionPrefix = stringBuilder.toString(); - entityPersisters = new HashMap(); Map entityAccessStrategies = new HashMap(); Map classMeta = new HashMap(); @@ -791,16 +819,18 @@ public final class SessionFactoryImpl EntityRegionAccessStrategy accessStrategy = null; if ( settings.isSecondLevelCacheEnabled() && rootEntityBinding.getHierarchyDetails().getCaching() != null && - model.getHierarchyDetails().getCaching() != null && - model.getHierarchyDetails().getCaching().getAccessType() != null ) { + model.getHierarchyDetails().getCaching() != null ) { final String cacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails().getCaching().getRegion(); accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) ); if ( accessStrategy == null ) { - final AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType(); + AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType(); + if ( accessType == null ) { + accessType = regionFactory.getDefaultAccessType(); + } if ( traceEnabled ) { LOG.tracev( "Building cache for entity data [{0}]", model.getEntity().getName() ); } - EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( + EntityRegion entityRegion = regionFactory.buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) ); accessStrategy = entityRegion.buildAccessStrategy( accessType ); @@ -808,11 +838,47 @@ public final class SessionFactoryImpl cacheAccess.addCacheRegion( cacheRegionName, entityRegion ); } } + NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null; + if ( settings.isSecondLevelCacheEnabled() && + rootEntityBinding.getHierarchyDetails().getNaturalIdCaching() != null && + model.getHierarchyDetails().getNaturalIdCaching() != null ) { + final String naturalIdCacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails() + .getNaturalIdCaching() + .getRegion(); + naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get( + naturalIdCacheRegionName + ); + if ( naturalIdAccessStrategy == null ) { + final CacheDataDescriptionImpl naturaIdCacheDataDescription = CacheDataDescriptionImpl.decode( model ); + NaturalIdRegion naturalIdRegion = null; + try { + naturalIdRegion = regionFactory.buildNaturalIdRegion( + naturalIdCacheRegionName, + properties, + naturaIdCacheDataDescription + ); + } + catch ( UnsupportedOperationException e ) { + LOG.warnf( + "Shared cache region factory [%s] does not support natural id caching; " + + "shared NaturalId caching will be disabled for not be enabled for %s", + regionFactory.getClass().getName(), + model.getEntity().getName() + ); + } + if ( naturalIdRegion != null ) { + naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() ); + entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); + cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion ); + } + } + } EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister( - model, accessStrategy, this, metadata + model, accessStrategy, naturalIdAccessStrategy, this, metadata ); entityPersisters.put( model.getEntity().getName(), cp ); classMeta.put( model.getEntity().getName(), cp.getClassMetadata() ); + jpaMetamodelBuilder.add( model ); } this.classMetadata = Collections.unmodifiableMap(classMeta); @@ -828,19 +894,32 @@ public final class SessionFactoryImpl "AbstractPluralAttributeBinding has a Singular attribute defined: " + model.getAttribute().getName() ); } - final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion(); - final AccessType accessType = model.getCaching().getAccessType(); CollectionRegionAccessStrategy accessStrategy = null; - if ( accessType != null && settings.isSecondLevelCacheEnabled() ) { - if ( traceEnabled ) { - LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() ); + if ( settings.isSecondLevelCacheEnabled() && + model.getCaching() != null ) { + + final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion(); + AccessType accessType = model.getCaching().getAccessType(); + if( accessType == null ){ + accessType = regionFactory.getDefaultAccessType(); } - CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion( + if ( accessType != null && settings.isSecondLevelCacheEnabled() ) { + if ( traceEnabled ) { + LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() ); + } + CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( + cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) + ); + accessStrategy = collectionRegion.buildAccessStrategy( accessType ); + entityAccessStrategies.put( cacheRegionName, accessStrategy ); + cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); + } + CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) ); accessStrategy = collectionRegion.buildAccessStrategy( accessType ); entityAccessStrategies.put( cacheRegionName, accessStrategy ); - cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); + cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); } CollectionPersister persister = serviceRegistry .getService( PersisterFactory.class ) @@ -879,26 +958,32 @@ public final class SessionFactoryImpl namedQueryRepository = new NamedQueryRepository( metadata.getNamedQueryDefinitions(), metadata.getNamedNativeQueryDefinitions(), - metadata.getResultSetMappingDefinitions(), + metadata.getResultSetMappingDefinitions().values(), new HashMap( ) ); imports = new HashMap(); - for ( Map.Entry importEntry : metadata.getImports() ) { + for ( Map.Entry importEntry : metadata.getImports().entrySet() ) { imports.put( importEntry.getKey(), importEntry.getValue() ); } // after *all* persisters and named queries are registered - Iterator iter = entityPersisters.values().iterator(); - while ( iter.hasNext() ) { - final EntityPersister persister = ( ( EntityPersister ) iter.next() ); + for ( EntityPersister persister : entityPersisters.values() ) { + persister.generateEntityDefinition(); + } + + for ( EntityPersister persister : entityPersisters.values() ) { persister.postInstantiate(); registerEntityNameResolvers( persister ); - } - iter = collectionPersisters.values().iterator(); - while ( iter.hasNext() ) { - final CollectionPersister persister = ( ( CollectionPersister ) iter.next() ); + + if ( sessionFactoryOptions.getEntityNameResolvers() != null ) { + for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) { + registerEntityNameResolver( resolver ); + } + } + + for ( CollectionPersister persister : collectionPersisters.values() ) { persister.postInstantiate(); } @@ -923,12 +1008,29 @@ public final class SessionFactoryImpl LOG.debug("Instantiated session factory"); } + // TODO: FIX this + //settings.getMultiTableBulkIdStrategy().prepare( + // jdbcServices, + // buildLocalConnectionAccess(), + // mapp, + // metadata, + // properties + //); + + if ( settings.isAutoCreateSchema() ) { new SchemaExport( metadata ) .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ) .create( false, true ); } + // TODO: implement these for new metamodel + //if ( settings.isAutoUpdateSchema() ) { + // new SchemaUpdate( metadata ).execute( false, true ); + //} + //if ( settings.isAutoValidateSchema() ) { + // new SchemaValidator( metadata ).validate(); + //} if ( settings.isAutoDropSchema() ) { schemaExport = new SchemaExport( metadata ) .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ); @@ -953,9 +1055,9 @@ public final class SessionFactoryImpl // this needs to happen after persisters are all ready to go... this.fetchProfiles = new HashMap(); - for ( org.hibernate.metamodel.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) { + for ( org.hibernate.metamodel.spi.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) { final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() ); - for ( org.hibernate.metamodel.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { + for ( org.hibernate.metamodel.spi.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { // resolve the persister owning the fetch final String entityName = getImportedClassName( mappingFetch.getEntity() ); final EntityPersister owner = entityName == null ? null : entityPersisters.get( entityName ); @@ -982,10 +1084,10 @@ public final class SessionFactoryImpl fetchProfiles.put( fetchProfile.getName(), fetchProfile ); } - this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy(); - this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( null ); this.transactionEnvironment = new TransactionEnvironmentImpl( this ); this.observer.sessionFactoryCreated( this ); + + this.jpaMetamodel = jpaMetamodelBuilder.buildMetamodel(); } @SuppressWarnings( {"unchecked"} ) @@ -1708,12 +1810,12 @@ public final class SessionFactoryImpl @Override public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { - return customEntityDirtinessStrategy; + return sessionFactoryOptions.getCustomEntityDirtinessStrategy(); } @Override public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { - return currentTenantIdentifierResolver; + return sessionFactoryOptions.getCurrentTenantIdentifierResolver(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java index 58f8b9d3e7..03213de38b 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java @@ -24,10 +24,22 @@ */ package org.hibernate.internal.util; +import java.beans.Introspector; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; + +import com.fasterxml.classmate.MemberResolver; +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.TypeResolver; +import com.fasterxml.classmate.members.ResolvedField; +import com.fasterxml.classmate.members.ResolvedMethod; +import com.fasterxml.classmate.types.ResolvedArrayType; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; @@ -60,6 +72,9 @@ public final class ReflectHelper { private static final Method OBJECT_EQUALS; private static final Method OBJECT_HASHCODE; + private static final TypeResolver TYPE_RESOLVER = new TypeResolver(); + private static final MemberResolver MEMBER_RESOLVER = new MemberResolver( TYPE_RESOLVER ); + static { Method eq; Method hash; @@ -378,4 +393,92 @@ public final class ReflectHelper { } } + /** + * Process bean properties getter by applying the JavaBean naming conventions. + * + * @param member the member for which to get the property name. + * + * @return The bean method name with the "is" or "get" prefix stripped off, {@code null} + * the method name id not according to the JavaBeans standard. + */ + public static String getPropertyName(Member member) { + String name = null; + + if ( member instanceof Field ) { + name = member.getName(); + } + + if ( member instanceof Method ) { + String methodName = member.getName(); + if ( methodName.startsWith( "is" ) ) { + name = Introspector.decapitalize( methodName.substring( 2 ) ); + } + else if ( methodName.startsWith( "has" ) ) { + name = Introspector.decapitalize( methodName.substring( 3 ) ); + } + else if ( methodName.startsWith( "get" ) ) { + name = Introspector.decapitalize( methodName.substring( 3 ) ); + } + } + return name; + } + + public static boolean isProperty(Member m) { + if ( m instanceof Method ) { + Method method = (Method) m; + return !method.isSynthetic() + && !method.isBridge() + && !Modifier.isStatic( method.getModifiers() ) + && method.getParameterTypes().length == 0 + && ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) ); + } + else { + return !Modifier.isTransient( m.getModifiers() ) && !m.isSynthetic(); + } + } + + /** + * Returns a Set of field types in the given class. However, for Collection + * and Map fields, the value and key types are returned instead of the + * Iterable class itself. + * + * @param clazz + * @return Set> + */ + // TODO: This should be moved out of ReflectHelper. Partial duplication with + // AnnotationBindingContextImpl#resolveMemberTypes + public static Set> getMemberTypes( Class clazz ) { + Set> fieldTypes = new HashSet>(); + + ResolvedType resolvedType = TYPE_RESOLVER.resolve( clazz ); + ResolvedTypeWithMembers resolvedTypes = MEMBER_RESOLVER.resolve( resolvedType, null, null ); + ResolvedField[] resolvedFields = resolvedTypes.getMemberFields(); + + for ( ResolvedField resolvedField : resolvedFields ) { + resolveAllTypes( resolvedField.getType(), fieldTypes ); + } + + // TODO: This should really just be checking getters, but for now do everything. + ResolvedMethod[] resolvedMethods = resolvedTypes.getMemberMethods(); + for ( ResolvedMethod resolvedMethod : resolvedMethods ) { + if ( resolvedMethod.getReturnType() != null ) { + resolveAllTypes( resolvedMethod.getReturnType(), fieldTypes ); + } + } + + return fieldTypes; + } + + private static void resolveAllTypes(ResolvedType fieldType, Set> fieldTypes) { + if ( fieldType instanceof ResolvedArrayType ) { + ResolvedArrayType arrayType = (ResolvedArrayType) fieldType; + resolveAllTypes( arrayType.getArrayElementType(), fieldTypes ); + } else { + fieldTypes.add( fieldType.getErasedType() ); + } + + for ( ResolvedType typeParameter : fieldType.getTypeBindings().getTypeParameters() ) { + resolveAllTypes( typeParameter, fieldTypes ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java index f000726034..ecaf31f442 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java @@ -39,6 +39,7 @@ public final class StringHelper { private static final int ALIAS_TRUNCATE_LENGTH = 10; public static final String WHITESPACE = " \n\r\f\t"; + public static final String [] EMPTY_STRINGS = new String[0]; private StringHelper() { /* static methods only - hide constructor */ } @@ -454,6 +455,10 @@ public final class StringHelper { return string == null || string.length() == 0; } + public static boolean isEmptyOrWhiteSpace(String string){ + return isEmpty( string ) || isEmpty( string.trim() ); + } + public static String qualify(String prefix, String name) { if ( name == null || prefix == null ) { throw new NullPointerException( "prefix or name were null attempting to build qualified name" ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java index 8a928d2642..417acdd4f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java @@ -339,6 +339,17 @@ public final class ArrayHelper { return PRIME_NUMER * seed + i; } + /** + * Returns {@code true} if the specified array is {@code null} or empty. + * + * @param array the array to check. + * @return {@code true} if the specified array is {@code null} or empty. + */ + + public static boolean isEmpty(final Object[] array) { + return array == null || array.length == 0; + } + /** * Compare 2 arrays only at the first level */ diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java index d241d768a4..206f75462a 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java @@ -156,7 +156,11 @@ public final class CollectionHelper { return collection == null || collection.isEmpty(); } - public static boolean isEmpty(Map map) { + public static boolean isEmpty(Iterable iterable){ + return iterable == null || !iterable.iterator().hasNext(); + } + + public static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } @@ -172,6 +176,23 @@ public final class CollectionHelper { return objects == null || objects.length==0; } + public static boolean isCollectionOrArray(Class clazz) { + if ( clazz == null ) { + return false; + } + if ( Collection.class.isAssignableFrom( clazz ) ) { + return true; + } + if ( Map.class.isAssignableFrom( clazz ) ) { + return true; + } + // TODO: why is the next block commented out??? +// if ( clazz.isArray() ) { +// return true; +// } + return false; + } + public static Map makeCopy(Map map) { final Map copy = mapOfSize( map.size() + 1 ); copy.putAll( map ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java index f138998e43..e35568588c 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java @@ -224,7 +224,8 @@ public class MappingReader { public static enum SupportedOrmXsdVersion { ORM_1_0( "org/hibernate/jpa/orm_1_0.xsd" ), ORM_2_0( "org/hibernate/jpa/orm_2_0.xsd" ), - ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ); + ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ), + HBM_4_0( "org/hibernate/hibernate-mapping-4.0.xsd"); private final String schemaResourceName; @@ -242,6 +243,9 @@ public class MappingReader { else if ( "2.1".equals( name ) ) { return ORM_2_1; } + else if ( "4.0".equals( name ) ) { + return HBM_4_0; + } throw new UnsupportedOrmXsdVersionException( name, origin ); } @@ -264,7 +268,7 @@ public class MappingReader { } } - private static URL resolveLocalSchemaUrl(String schemaName) { + public static URL resolveLocalSchemaUrl(String schemaName) { URL url = MappingReader.class.getClassLoader().getResource( schemaName ); if ( url == null ) { throw new XmlInfrastructureException( "Unable to locate schema [" + schemaName + "] via classpath" ); @@ -272,7 +276,11 @@ public class MappingReader { return url; } - private static Schema resolveLocalSchema(URL schemaUrl) { + public static Schema resolveLocalSchema(String schemaName){ + return resolveLocalSchema( resolveLocalSchemaUrl( schemaName ) ); + } + + public static Schema resolveLocalSchema(URL schemaUrl) { try { InputStream schemaStream = schemaUrl.openStream(); @@ -326,7 +334,7 @@ public class MappingReader { if ( errorHandler.hasErrors() ) { throw errorHandler.getErrors().get( 0 ); } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); + return new XmlDocumentImpl( document, origin ); } catch ( Exception e ) { if ( LOG.isDebugEnabled() ) { @@ -344,7 +352,7 @@ public class MappingReader { errorHandler.logErrors(); throw errorHandler.getErrors().get( 0 ); } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); + return new XmlDocumentImpl( document, origin ); } catch ( Exception e2 ) { if ( LOG.isDebugEnabled() ) { @@ -361,7 +369,7 @@ public class MappingReader { errorHandler.logErrors(); throw errorHandler.getErrors().get( 0 ); } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); + return new XmlDocumentImpl( document, origin ); } catch ( Exception e3 ) { if ( LOG.isDebugEnabled() ) { @@ -382,13 +390,13 @@ public class MappingReader { if ( "orm_2_1.xsd".equals( xsd ) ) { saxReader.setProperty( "http://apache.org/xml/properties/schema/external-schemaLocation", - "http://xmlns.jcp.org/xml/ns/persistence/orm " + xsd + LocalXmlResourceResolver.SECOND_JPA_ORM_NS + " " + xsd ); } else { saxReader.setProperty( "http://apache.org/xml/properties/schema/external-schemaLocation", - "http://java.sun.com/xml/ns/persistence/orm " + xsd + LocalXmlResourceResolver.INITIAL_JPA_ORM_NS + " " + xsd ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/internal/AbstractJaxbProcessor.java b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/AbstractJaxbProcessor.java new file mode 100644 index 0000000000..958da56e8f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/AbstractJaxbProcessor.java @@ -0,0 +1,190 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.internal; + +import java.io.InputStream; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventHandler; +import javax.xml.bind.ValidationEventLocator; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.validation.Schema; + +import org.jboss.logging.Logger; + +import org.hibernate.internal.util.xml.BufferedXMLEventReader; +import org.hibernate.internal.util.xml.LocalXmlResourceResolver; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.service.ServiceRegistry; + +/** + * @author Strong Liu + */ +abstract class AbstractJaxbProcessor { + protected static final Logger log = Logger.getLogger( AbstractJaxbProcessor.class ); + +// public static final String VALIDATE_XML_SETTING = "hibernate.xml.validate"; + + protected final ServiceRegistry serviceRegistry; + protected final boolean validateXml; + + public AbstractJaxbProcessor(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); +// this( +// serviceRegistry, +// serviceRegistry.getService( ConfigurationService.class ).getSetting( +// VALIDATE_XML_SETTING, +// StandardConverters.BOOLEAN, +// true +// ) +// ); + } + + public AbstractJaxbProcessor(ServiceRegistry serviceRegistry, boolean validateXml) { + this.serviceRegistry = serviceRegistry; + this.validateXml = validateXml; + } + + public JaxbRoot unmarshal(InputStream stream, Origin origin) { + try { + BufferedXMLEventReader staxReader = new BufferedXMLEventReader(staxFactory().createXMLEventReader( stream ), 100); + try { + return unmarshal( staxReader, origin ); + } + finally { + try { + staxReader.close(); + } + catch ( Exception ignore ) { + } + } + } + catch ( XMLStreamException e ) { + throw new MappingException( "Unable to create stax reader", e, origin ); + } + } + + private XMLInputFactory staxFactory; + + private XMLInputFactory staxFactory() { + if ( staxFactory == null ) { + staxFactory = buildStaxFactory(); + } + return staxFactory; + } + + @SuppressWarnings( { "UnnecessaryLocalVariable" }) + private XMLInputFactory buildStaxFactory() { + XMLInputFactory staxFactory = XMLInputFactory.newInstance(); + staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE ); + return staxFactory; + } + + @SuppressWarnings( { "unchecked" }) + private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) { + XMLEvent event; + try { + event = staxEventReader.peek(); + while ( event != null && !event.isStartElement() ) { + staxEventReader.nextEvent(); + event = staxEventReader.peek(); + } + } + catch ( Exception e ) { + throw new MappingException( "Error accessing stax stream", e, origin ); + } + + if ( event == null ) { + throw new MappingException( "Could not locate root element", origin ); + } + + + + final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); + try { + Schema schema = getSchema(event, origin); + staxEventReader = wrapReader( staxEventReader, event ); + JAXBContext jaxbContext =getJaxbContext(event); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setSchema( schema ); + unmarshaller.setEventHandler( handler ); + final Object target = unmarshaller.unmarshal( staxEventReader ); + return new JaxbRoot( target, origin ); + } + catch ( JAXBException e ) { + StringBuilder builder = new StringBuilder(); + builder.append( "Unable to perform unmarshalling at line number " ); + builder.append( handler.getLineNumber() ); + builder.append( " and column " ); + builder.append( handler.getColumnNumber() ); + builder.append( ". Message: " ); + builder.append( handler.getMessage() ); + throw new MappingException( builder.toString(), e, origin ); + } + } + protected abstract JAXBContext getJaxbContext(XMLEvent event) throws JAXBException; + protected abstract Schema getSchema(XMLEvent event, Origin origin) throws JAXBException; + protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event){ + return xmlEventReader; + } + protected static boolean isNamespaced(StartElement startElement) { + return ! "".equals( startElement.getName().getNamespaceURI() ); + } + + + static class ContextProvidingValidationEventHandler implements ValidationEventHandler { + private int lineNumber; + private int columnNumber; + private String message; + + @Override + public boolean handleEvent(ValidationEvent validationEvent) { + ValidationEventLocator locator = validationEvent.getLocator(); + lineNumber = locator.getLineNumber(); + columnNumber = locator.getColumnNumber(); + message = validationEvent.getMessage(); + return false; + } + + public int getLineNumber() { + return lineNumber; + } + + public int getColumnNumber() { + return columnNumber; + } + + public String getMessage() { + return message; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbConfigurationProcessor.java b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbConfigurationProcessor.java new file mode 100644 index 0000000000..5991ebe5d9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbConfigurationProcessor.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.internal; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.XMLEvent; +import javax.xml.validation.Schema; + +import org.jboss.logging.Logger; + +import org.hibernate.internal.util.xml.MappingReader; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; +import org.hibernate.service.ServiceRegistry; + +/** + * @author Steve Ebersole + */ +public class JaxbConfigurationProcessor extends AbstractJaxbProcessor { + private static final Logger log = Logger.getLogger( JaxbConfigurationProcessor.class ); + + public static final String HIBERNATE_CONFIGURATION_URI = "http://www.hibernate.org/xsd/hibernate-configuration"; + + + public JaxbConfigurationProcessor(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); + } + + public JaxbConfigurationProcessor(ServiceRegistry serviceRegistry, boolean validateXml) { + super(serviceRegistry, validateXml); + } + + @Override + protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event) { + if ( !isNamespaced( event.asStartElement() ) ) { + // if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled. + log.debug( "cfg.xml document did not define namespaces; wrapping in custom event reader to introduce namespace information" ); + return new NamespaceAddingEventReader( xmlEventReader, HIBERNATE_CONFIGURATION_URI ); + } + return super.wrapReader( xmlEventReader, event ); + } + + @Override + protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException{ + return JAXBContext.newInstance( JaxbHibernateConfiguration.class ); + } + + @Override + protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { + if ( schema == null ) { + schema = MappingReader.resolveLocalSchema( "org/hibernate/hibernate-configuration-4.0.xsd" ); + } + return schema; + } + + private Schema schema; + + + + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbMappingProcessor.java new file mode 100644 index 0000000000..6fc2ffa850 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/JaxbMappingProcessor.java @@ -0,0 +1,184 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.internal; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; + +import org.jboss.logging.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.xml.LocalXmlResourceResolver; +import org.hibernate.internal.util.xml.MappingReader; +import org.hibernate.internal.util.xml.OriginImpl; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.jaxb.spi.orm.JaxbEntityMappings; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.service.ServiceRegistry; + +/** + * Loads {@code hbm.xml} and {@code orm.xml} files and processes them using StAX and JAXB. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class JaxbMappingProcessor extends AbstractJaxbProcessor{ + private static final Logger log = Logger.getLogger( JaxbMappingProcessor.class ); + public static final String HIBERNATE_MAPPING_URI = "http://www.hibernate.org/xsd/hibernate-mapping"; + + public JaxbMappingProcessor(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); + } + + public JaxbMappingProcessor(ServiceRegistry serviceRegistry, boolean validateXml) { + super(serviceRegistry, validateXml); + } + + @Override + protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException { + final String elementName = event.asStartElement().getName().getLocalPart(); + final Class jaxbTarget; + if ( "entity-mappings".equals( elementName ) ) { + jaxbTarget = JaxbEntityMappings.class; + } + else { + jaxbTarget = JaxbHibernateMapping.class; + } + return JAXBContext.newInstance( jaxbTarget ); + } + + @Override + protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { + final String elementName = event.asStartElement().getName().getLocalPart(); + final Schema validationSchema; + if ( "entity-mappings".equals( elementName ) ) { + final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME ); + final String explicitVersion = attribute == null ? null : attribute.getValue(); + validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null; + } + else { + validationSchema = validateXml ? MappingReader.SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; + } + return validationSchema; + } + + @Override + protected XMLEventReader wrapReader(XMLEventReader staxEventReader, XMLEvent event) { + final String elementName = event.asStartElement().getName().getLocalPart(); + if ( "entity-mappings".equals( elementName ) ) { + final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME ); + final String explicitVersion = attribute == null ? null : attribute.getValue(); + if ( !"2.1".equals( explicitVersion ) ) { + return new LegacyJPAEventReader( + staxEventReader, + LocalXmlResourceResolver.SECOND_JPA_ORM_NS + ); + } + } + else { + if ( !isNamespaced( event.asStartElement() ) ) { + // if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled. + log.debug( "HBM mapping document did not define namespaces; wrapping in custom event reader to introduce namespace information" ); + return new NamespaceAddingEventReader( staxEventReader, HIBERNATE_MAPPING_URI ); + } + } + return super.wrapReader( staxEventReader, event ); + } + + private static final QName ORM_VERSION_ATTRIBUTE_QNAME = new QName( "version" ); + + + + + + @SuppressWarnings( { "unchecked" }) + public JaxbRoot unmarshal(Document document, Origin origin) { + Element rootElement = document.getDocumentElement(); + if ( rootElement == null ) { + throw new MappingException( "No root element found", origin ); + } + + final Schema validationSchema; + final Class jaxbTarget; + + if ( "entity-mappings".equals( rootElement.getNodeName() ) ) { + final String explicitVersion = rootElement.getAttribute( "version" ); + validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null; + jaxbTarget = JaxbEntityMappings.class; + } + else { + validationSchema = validateXml ? MappingReader.SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; + jaxbTarget = JaxbHibernateMapping.class; + } + + final Object target; + try { + JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setSchema( validationSchema ); + target = unmarshaller.unmarshal( new DOMSource( document ) ); + } + catch ( JAXBException e ) { + throw new MappingException( "Unable to perform unmarshalling", e, origin ); + } + + return new JaxbRoot( target, origin ); + } + + private Schema resolveSupportedOrmXsd(String explicitVersion, Origin origin) { + + if ( StringHelper.isEmpty( explicitVersion ) ) { + return MappingReader.SupportedOrmXsdVersion.ORM_2_1.getSchema(); + } + + // Here we always use JPA 2.1 schema to do the validation, since the {@link LegacyJPAEventReader} already + // transforms the legacy orm.xml to JPA 2.1 namespace and version. + // + // This may cause some problems, like a jpa 1.0 orm.xml having some element which is only available in the later + // version. It is "invalid" but due to the fact we're using the latest schema to do the validation, then + // it is "valid". Don't know if this will cause any problems, but let's do it for now. + // + // However, still check for the validity of the version by calling #parse. If someone explicitly uses a value + // that doesn't exist, we still need to throw the exception. + @SuppressWarnings("unused") + MappingReader.SupportedOrmXsdVersion version = + MappingReader.SupportedOrmXsdVersion.parse( + explicitVersion, + new OriginImpl( origin.getType().name(), origin.getName() ) + ); + // return version.getSchema(); + return MappingReader.SupportedOrmXsdVersion.ORM_2_1.getSchema(); + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/internal/LegacyJPAEventReader.java b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/LegacyJPAEventReader.java new file mode 100644 index 0000000000..04a0e11b7d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/LegacyJPAEventReader.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.internal; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +import org.hibernate.internal.util.xml.LocalXmlResourceResolver; + +/** + * + * We're lying to the xml validator here :D + *

+ * + * Since JPA 2.1 changed its orm.xml namespace, so to support all versions + *

    + *
  • 1.0
  • + *
  • 2.0
  • + *
  • 2.1
  • + *
+ * + * the validator must recognize all of these two namespaces. + * + * but it is very hard to do that, so we're making an assumption (because I really don't konw if this is true or not) + * here that JPA 2.1 is backward compatible w/ the old releases. + * + * So, there it comes, we just simply remove all legacy namespaces if it is an orm.xml and add the expected namespace + * , here is it JPA 2.1, to every elements in the xml. + * + * Finally, for the xml validator, it always see the JPA 2.1 namespace only, and it would be happy to do the validation. + * + *

+ * {@see HHH-8108} for more discussion. + * + * @author Strong Liu + */ +public class LegacyJPAEventReader extends EventReaderDelegate { + private final XMLEventFactory xmlEventFactory; + private final String namespaceUri; + + public LegacyJPAEventReader(XMLEventReader reader, String namespaceUri) { + this( reader, XMLEventFactory.newInstance(), namespaceUri ); + } + + public LegacyJPAEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + this.namespaceUri = namespaceUri; + } + + private StartElement withNamespace(StartElement startElement) { + + Iterator attributes; + Iterator namespacesItr; + if ( "entity-mappings".equals( startElement.getName().getLocalPart() ) ) { + List st = new ArrayList(); + Iterator itr = startElement.getAttributes(); + while ( itr.hasNext() ) { + Attribute obj = (Attribute) itr.next(); + if ( "version".equals( obj.getName().getLocalPart() ) ) { + if ( "".equals( obj.getName().getPrefix() ) ) { + st.add( xmlEventFactory.createAttribute( obj.getName(), "2.1" ) ); + } + } + else { + st.add( obj ); + } + } + attributes = st.iterator(); + // otherwise, wrap the start element event to provide a default namespace mapping + final List namespaces = new ArrayList(); + namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) ); + Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace ns = (Namespace) originalNamespaces.next(); + if ( !LocalXmlResourceResolver.INITIAL_JPA_ORM_NS.equals( ns.getNamespaceURI() ) ) { + namespaces.add( ns ); + } + } + namespacesItr = namespaces.iterator(); + } else { + attributes = startElement.getAttributes(); + namespacesItr = startElement.getNamespaces(); + } + + return xmlEventFactory.createStartElement( + new QName( namespaceUri, startElement.getName().getLocalPart() ), + attributes, + namespacesItr + ); + } + + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + private XMLEvent wrap(XMLEvent event) { + if ( event!=null && event.isStartElement() ) { + return withNamespace( event.asStartElement() ); + } + return event; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/internal/NamespaceAddingEventReader.java b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/NamespaceAddingEventReader.java new file mode 100644 index 0000000000..148e9ea4db --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/internal/NamespaceAddingEventReader.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.internal; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +import org.hibernate.internal.util.xml.LocalXmlResourceResolver; + +/** + * Used to wrap a StAX {@link XMLEventReader} in order to introduce namespaces into the underlying document. This + * is intended for temporary migration feature to allow legacy HBM mapping documents (DTD-based) to continue to + * parse correctly. This feature will go away eventually. + * + * @author Steve Ebersole + */ +public class NamespaceAddingEventReader extends EventReaderDelegate { + private final XMLEventFactory xmlEventFactory; + private final String namespaceUri; + + public NamespaceAddingEventReader(XMLEventReader reader, String namespaceUri) { + this( reader, XMLEventFactory.newInstance(), namespaceUri ); + } + + public NamespaceAddingEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + this.namespaceUri = namespaceUri; + } + + private StartElement withNamespace(StartElement startElement) { + // otherwise, wrap the start element event to provide a default namespace mapping + final List namespaces = new ArrayList(); + namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) ); + Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace ns = (Namespace) originalNamespaces.next(); + namespaces.add( ns ); + } + return xmlEventFactory.createStartElement( + new QName( namespaceUri, startElement.getName().getLocalPart() ), + startElement.getAttributes(), + namespaces.iterator() + ); + } + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + + private XMLEvent wrap(XMLEvent event) { + if ( event.isStartElement() ) { + return withNamespace( event.asStartElement() ); + } + return event; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/package-info.java b/hibernate-core/src/main/java/org/hibernate/jaxb/package-info.java new file mode 100644 index 0000000000..763951f03e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/package-info.java @@ -0,0 +1,5 @@ +package org.hibernate.jaxb; + +/** + * Defines Hibernate's JAXB usage. + */ \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/JaxbRoot.java similarity index 93% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/JaxbRoot.java index 57bbb80461..99ac5dd496 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/JaxbRoot.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb; +package org.hibernate.jaxb.spi; + +import java.io.Serializable; /** * Holds information about a JAXB-unmarshalled XML document. @@ -29,7 +31,7 @@ package org.hibernate.internal.jaxb; * @author Hardy Ferentschik * @author Steve Ebersole */ -public class JaxbRoot { +public class JaxbRoot implements Serializable { private final T root; private final Origin origin; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/Origin.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/Origin.java index c596537f8b..7e6d21f72f 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/Origin.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb; +package org.hibernate.jaxb.spi; import java.io.Serializable; @@ -57,4 +57,40 @@ public class Origin implements Serializable { public String getName() { return name; } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof Origin ) ) { + return false; + } + + Origin origin = (Origin) o; + + if ( name != null ? !name.equals( origin.name ) : origin.name != null ) { + return false; + } + if ( type != origin.type ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + ( name != null ? name.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "Origin{" + + "name='" + name + '\'' + + ", type=" + type + + '}'; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/SourceType.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/SourceType.java index 32245a3eaa..3a27ab91e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/SourceType.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb; +package org.hibernate.jaxb.spi; /** * From what type of source did we obtain the data diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ComponentSourceElement.java similarity index 79% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ComponentSourceElement.java index 5213c84d36..d5d533c1fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ComponentSourceElement.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; /** * @author Steve Ebersole */ -public interface CustomSqlElement { - public String getValue(); - public boolean isCallable(); - public JaxbCheckAttribute getCheck(); +public interface ComponentSourceElement extends MetaAttributeContainer { + public String getAccess(); + public String getClazz(); + public String getName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/EntityElement.java similarity index 63% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/EntityElement.java index a0280bc69c..be50f4f817 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/EntityElement.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; import java.util.List; @@ -32,10 +32,10 @@ public interface EntityElement extends MetaAttributeContainer { public String getName(); public String getEntityName(); - public Boolean isAbstract(); + public boolean isAbstract(); public Boolean isLazy(); public String getProxy(); - public String getBatchSize(); + public int getBatchSize(); public boolean isDynamicInsert(); public boolean isDynamicUpdate(); public boolean isSelectBeforeUpdate(); @@ -44,9 +44,9 @@ public interface EntityElement extends MetaAttributeContainer { public String getPersister(); public JaxbLoaderElement getLoader(); - public JaxbSqlInsertElement getSqlInsert(); - public JaxbSqlUpdateElement getSqlUpdate(); - public JaxbSqlDeleteElement getSqlDelete(); + public JaxbSqlDmlElement getSqlInsert(); + public JaxbSqlDmlElement getSqlUpdate(); + public JaxbSqlDmlElement getSqlDelete(); public List getSynchronize(); @@ -54,7 +54,21 @@ public interface EntityElement extends MetaAttributeContainer { public List getResultset(); - public List getQueryOrSqlQuery(); + public List getSqlQuery(); + public List getQuery(); - public List getPropertyOrManyToOneOrOneToOne(); + public List getProperty(); + public List getProperties(); + public List getManyToOne(); + public List getOneToOne(); + public List getComponent(); + public List getDynamicComponent(); + public List getAny(); + public List getMap(); + public List getSet(); + public List getList(); + public List getBag(); + public List getIdbag(); + public List getArray(); + public List getPrimitiveArray(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/IdBagPluralAttributeElementAdapter.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/IdBagPluralAttributeElementAdapter.java index fad92698bb..611ab953dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/IdBagPluralAttributeElementAdapter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; /** * Adaptive implementation of the {@link PluralAttributeElement} for {@code } mappings which diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/JoinElementSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/JoinElementSource.java index 4ff687415d..8f7106fb75 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/JoinElementSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; import java.util.List; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/MetaAttributeContainer.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/MetaAttributeContainer.java index 6a178cb8f0..ffa695f345 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/MetaAttributeContainer.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; import java.util.List; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/PluralAttributeElement.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/PluralAttributeElement.java index adf766fbe0..6e3cc5692c 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/PluralAttributeElement.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; import java.util.List; @@ -30,7 +30,7 @@ import java.util.List; * * @author Steve Ebersole */ -public interface PluralAttributeElement extends MetaAttributeContainer { +public interface PluralAttributeElement extends TableInformationSource, MetaAttributeContainer { public String getName(); public String getAccess(); @@ -42,20 +42,15 @@ public interface PluralAttributeElement extends MetaAttributeContainer { public JaxbManyToManyElement getManyToMany(); public JaxbManyToAnyElement getManyToAny(); - public String getSchema(); - public String getCatalog(); - public String getTable(); public String getComment(); public String getCheck(); - public String getSubselect(); - public String getSubselectAttribute(); public String getWhere(); public JaxbLoaderElement getLoader(); - public JaxbSqlInsertElement getSqlInsert(); - public JaxbSqlUpdateElement getSqlUpdate(); - public JaxbSqlDeleteElement getSqlDelete(); - public JaxbSqlDeleteAllElement getSqlDeleteAll(); + public JaxbSqlDmlElement getSqlInsert(); + public JaxbSqlDmlElement getSqlUpdate(); + public JaxbSqlDmlElement getSqlDelete(); + public JaxbSqlDmlElement getSqlDeleteAll(); public List getSynchronize(); @@ -67,7 +62,7 @@ public interface PluralAttributeElement extends MetaAttributeContainer { public JaxbLazyAttributeWithExtra getLazy(); public JaxbOuterJoinAttribute getOuterJoin(); - public String getBatchSize(); + public int getBatchSize(); public boolean isInverse(); public boolean isMutable(); public boolean isOptimisticLock(); diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/QuerySourceElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/QuerySourceElement.java new file mode 100644 index 0000000000..36d2b3534e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/QuerySourceElement.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.spi.hbm; + +import java.io.Serializable; +import java.util.List; + +/** + * TODO javadoc + * + * @author Strong Liu + */ +public interface QuerySourceElement { + List getContent(); + JaxbCacheModeAttribute getCacheMode(); + String getCacheRegion(); + boolean isCacheable(); + String getComment(); + Integer getFetchSize(); + JaxbFlushModeAttribute getFlushMode(); + String getName(); + boolean isReadOnly(); + Integer getTimeout(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ReturnElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ReturnElement.java new file mode 100644 index 0000000000..004a8fdbdf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/ReturnElement.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.spi.hbm; + +import java.util.List; + +/** + * @author Strong Liu + */ +public interface ReturnElement { + public String getAlias(); + public JaxbLockModeAttribute getLockMode(); + public List getReturnProperty(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SingularAttributeSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SingularAttributeSource.java index 0030cbe725..90cbe98b0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SingularAttributeSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SubEntityElement.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java rename to hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SubEntityElement.java index 3d0dfd8284..c52e6cc15e 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/SubEntityElement.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.jaxb.spi.hbm; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/TableInformationSource.java b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/TableInformationSource.java new file mode 100644 index 0000000000..5fa8d06683 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jaxb/spi/hbm/TableInformationSource.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jaxb.spi.hbm; + +/** + * @author Steve Ebersole + */ +public interface TableInformationSource { + public String getSchema(); + + public String getCatalog(); + + public String getTable(); + + public String getSubselect(); + + public String getSubselectAttribute(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractAttribute.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractAttribute.java new file mode 100644 index 0000000000..6f962fce0d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractAttribute.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.ManagedType; + +import org.hibernate.internal.util.ReflectHelper; + +/** + * Models the commonality of the JPA {@link Attribute} hierarchy. + * + * @author Steve Ebersole + */ +public abstract class AbstractAttribute implements Attribute, Serializable { + private final String name; + private final Class javaType; + private final AbstractManagedType declaringType; + private transient Member member; + private final PersistentAttributeType persistentAttributeType; + + public AbstractAttribute( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + PersistentAttributeType persistentAttributeType) { + this.name = name; + this.javaType = javaType; + this.declaringType = declaringType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + } + + @Override + public String getName() { + return name; + } + + @Override + public ManagedType getDeclaringType() { + return declaringType; + } + + @Override + public Class getJavaType() { + return javaType; + } + + @Override + public Member getJavaMember() { + return member; + } + + @Override + public PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + /** + * Used by JDK serialization... + * + * @param oos The output stream to which we are being written... + * @throws IOException Indicates a general IO stream exception + */ + protected void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject( getJavaMember().getDeclaringClass().getName() ); + oos.writeObject( getJavaMember().getName() ); + // should only ever be a field or the getter-method... + oos.writeObject( Method.class.isInstance( getJavaMember() ) ? "method" : "field" ); + } + + /** + * Used by JDK serialization... + * + * @param ois The input stream from which we are being read... + * @throws java.io.IOException Indicates a general IO stream exception + * @throws ClassNotFoundException Indicates a class resolution issue + */ + protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + final String memberDeclaringClassName = ( String ) ois.readObject(); + final String memberName = ( String ) ois.readObject(); + final String memberType = ( String ) ois.readObject(); + + final Class memberDeclaringClass = Class.forName( + memberDeclaringClassName, + false, + declaringType.getJavaType().getClassLoader() + ); + try { + this.member = "method".equals( memberType ) + ? memberDeclaringClass.getMethod( memberName, ReflectHelper.NO_PARAM_SIGNATURE ) + : memberDeclaringClass.getField( memberName ); + } + catch ( Exception e ) { + throw new IllegalStateException( + "Unable to locate member [" + memberDeclaringClassName + "#" + + memberName + "]" + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractIdentifiableType.java new file mode 100644 index 0000000000..9a556857cb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractIdentifiableType.java @@ -0,0 +1,302 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +/** + * Defines commonality for the JPA {@link IdentifiableType} types. JPA defines + * identifiable types as entities or mapped-superclasses. Basically things to which an + * identifier can be attached. + *

+ * NOTE : Currently we only really have support for direct entities in the Hibernate metamodel + * as the information for them is consumed into the closest actual entity subclass(es) in the + * internal Hibernate mapping-metamodel. + * + * @author Steve Ebersole + */ +public abstract class AbstractIdentifiableType + extends AbstractManagedType + implements IdentifiableType, Serializable { + + private final boolean hasIdentifierProperty; + private final boolean isVersioned; + + private SingularAttributeImpl id; + private SingularAttributeImpl version; + private Set> idClassAttributes; + + public AbstractIdentifiableType( + Class javaType, + AbstractIdentifiableType superType, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, superType ); + this.hasIdentifierProperty = hasIdentifierProperty; + isVersioned = versioned; + } + + @Override + public AbstractIdentifiableType getSupertype() { + return ( AbstractIdentifiableType ) super.getSupertype(); + } + + /** + * Indicates if a non-null super type is required to provide the + * identifier attribute(s) if this object does not have a declared + * identifier. + * . + * @return true, if a non-null super type is required to provide + * the identifier attribute(s) if this object does not have a + * declared identifier; false, otherwise. + */ + protected abstract boolean requiresSupertypeForNonDeclaredIdentifier(); + + protected AbstractIdentifiableType requireSupertype() { + if ( getSupertype() == null ) { + throw new IllegalStateException( "No supertype found" ); + } + return getSupertype(); + } + + @Override + public boolean hasSingleIdAttribute() { + return hasIdentifierProperty; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getId(Class javaType) { + final SingularAttribute id_; + if ( id != null ) { + checkSimpleId(); + id_ = ( SingularAttribute ) id; + if ( javaType != id.getJavaType() ) { + throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() ); + } + } + else { + //yuk yuk bad me + if ( ! requiresSupertypeForNonDeclaredIdentifier()) { + final AbstractIdentifiableType supertype = getSupertype(); + if (supertype != null) { + id_ = supertype.getId( javaType ); + } + else { + id_ = null; + } + } + else { + id_ = requireSupertype().getId( javaType ); + } + } + return id_; + } + + /** + * Centralized check to ensure the id for this hierarchy is a simple one (i.e., does not use + * an id-class). + * + * @see #checkIdClass() + */ + protected void checkSimpleId() { + if ( ! hasIdentifierProperty ) { + throw new IllegalStateException( "This class uses an @IdClass" ); + } + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredId(Class javaType) { + checkDeclaredId(); + checkSimpleId(); + if ( javaType != id.getJavaType() ) { + throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() ); + } + return (SingularAttribute) id; + } + + /** + * Centralized check to ensure the id is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredId() { + if ( id == null ) { + throw new IllegalArgumentException( "The id attribute is not declared on this type" ); + } + } + + @Override + public Type getIdType() { + if ( id != null ) { + checkSimpleId(); + return id.getType(); + } + else { + return requireSupertype().getIdType(); + } + } + + private boolean hasIdClassAttributesDefined() { + return idClassAttributes != null || + ( getSupertype() != null && getSupertype().hasIdClassAttributesDefined() ); + } + + @Override + public Set> getIdClassAttributes() { + if ( idClassAttributes != null ) { + checkIdClass(); + } + else { + // Java does not allow casting requireSupertype().getIdClassAttributes() + // to Set> because the + // superclass X is a different Java type from this X + // (i.e, getSupertype().getJavaType() != getJavaType()). + // It will, however, allow a Set> + // to be initialized with requireSupertype().getIdClassAttributes(), + // since getSupertype().getJavaType() is a superclass of getJavaType() + if ( requiresSupertypeForNonDeclaredIdentifier() ) { + idClassAttributes = new HashSet>( requireSupertype().getIdClassAttributes() ); + } + else if ( getSupertype() != null && hasIdClassAttributesDefined() ) { + idClassAttributes = new HashSet>( getSupertype().getIdClassAttributes() ); + } + } + return idClassAttributes; + } + + /** + * Centralized check to ensure the id for this hierarchy uses an id-class. + * + * @see #checkSimpleId() + */ + private void checkIdClass() { + if ( hasIdentifierProperty ) { + throw new IllegalArgumentException( "This class does not use @IdClass" ); + } + } + + @Override + public boolean hasVersionAttribute() { + return isVersioned; + } + + public boolean hasDeclaredVersionAttribute() { + return isVersioned && version != null; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getVersion(Class javaType) { + if ( ! hasVersionAttribute() ) { + return null; + } + final SingularAttribute version_; + if ( version != null ) { + version_ = ( SingularAttribute ) version; + if ( javaType != version.getJavaType() ) { + throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() ); + } + } + else { + version_ = requireSupertype().getVersion( javaType ); + } + return version_; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredVersion(Class javaType) { + checkDeclaredVersion(); + if ( javaType != version.getJavaType() ) { + throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() ); + } + return ( SingularAttribute ) version; + } + + /** + * For used to retrieve the declared version when populating the static metamodel. + * + * @return The declared + */ + public SingularAttribute getDeclaredVersion() { + checkDeclaredVersion(); + return version; + } + + /** + * Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredVersion() { + if ( version == null || ( getSupertype() != null && getSupertype().hasVersionAttribute() )) { + throw new IllegalArgumentException( "The version attribute is not declared on this type" ); + } + } + + @Override + public Builder getBuilder() { + final AbstractManagedType.Builder managedBuilder = super.getBuilder(); + return new Builder() { + @Override + public void applyIdAttribute(SingularAttributeImpl idAttribute) { + AbstractIdentifiableType.this.id = idAttribute; + managedBuilder.addAttribute( idAttribute ); + } + + @Override + public void applyIdClassAttributes(Set> idClassAttributes) { + for ( SingularAttribute idClassAttribute : idClassAttributes ) { + if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) { + @SuppressWarnings({ "unchecked" }) + SingularAttribute declaredAttribute = ( SingularAttribute ) idClassAttribute; + addAttribute( declaredAttribute ); + } + } + AbstractIdentifiableType.this.idClassAttributes = idClassAttributes; + } + @Override + public void applyVersionAttribute(SingularAttributeImpl versionAttribute) { + AbstractIdentifiableType.this.version = versionAttribute; + managedBuilder.addAttribute( versionAttribute ); + } + + @Override + public void addAttribute(Attribute attribute) { + managedBuilder.addAttribute( attribute ); + } + }; + } + + public static interface Builder extends AbstractManagedType.Builder { + public void applyIdAttribute(SingularAttributeImpl idAttribute); + public void applyIdClassAttributes(Set> idClassAttributes); + public void applyVersionAttribute(SingularAttributeImpl versionAttribute); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractManagedType.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractManagedType.java new file mode 100644 index 0000000000..19f0996fe4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractManagedType.java @@ -0,0 +1,480 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.annotations.common.AssertionFailure; + +/** + * Defines commonality for the JPA {@link ManagedType} hierarchy of interfaces. + * + * @author Steve Ebersole + */ +public abstract class AbstractManagedType + extends AbstractType + implements ManagedType, Serializable { + + private final AbstractManagedType superType; + + private final Map> declaredAttributes + = new HashMap>(); + private final Map> declaredSingularAttributes + = new HashMap>(); + private final Map> declaredPluralAttributes + = new HashMap>(); + + protected AbstractManagedType(Class javaType, AbstractManagedType superType) { + super( javaType ); + this.superType = superType; + } + + public AbstractManagedType getSupertype() { + return superType; + } + + private boolean locked = false; + + public Builder getBuilder() { + if ( locked ) { + throw new IllegalStateException( "Type has been locked" ); + } + return new Builder() { + @Override + public void addAttribute(Attribute attribute) { + declaredAttributes.put( attribute.getName(), attribute ); + final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType(); + switch ( bindableType ) { + case SINGULAR_ATTRIBUTE : { + declaredSingularAttributes.put( attribute.getName(), (SingularAttribute) attribute ); + break; + } + case PLURAL_ATTRIBUTE : { + declaredPluralAttributes.put(attribute.getName(), (PluralAttribute) attribute ); + break; + } + default : { + throw new AssertionFailure( "unknown bindable type: " + bindableType ); + } + } + } + }; + } + + public void lock() { + locked = true; + } + + public static interface Builder { + public void addAttribute(Attribute attribute); + } + + + @Override + @SuppressWarnings({ "unchecked" }) + public Set> getAttributes() { + HashSet attributes = new HashSet>( declaredAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getAttributes() ); + } + return attributes; + } + + @Override + public Set> getDeclaredAttributes() { + return new HashSet>( declaredAttributes.values() ); + } + + @Override + @SuppressWarnings({ "unchecked" }) + public Attribute getAttribute(String name) { + Attribute attribute = declaredAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getAttribute( name ); + } + return attribute; + } + + @Override + public Attribute getDeclaredAttribute(String name) { + final Attribute attr = declaredSingularAttributes.get( name ); + checkNotNull( "Attribute ", attr, name ); + return attr; + } + + private void checkNotNull(String attributeType, Attribute attribute, String name) { + if ( attribute == null ) { + throw new IllegalArgumentException( attributeType + " named " + name + " is not present" ); + } + } + + @Override + @SuppressWarnings({ "unchecked" }) + public Set> getSingularAttributes() { + HashSet attributes = new HashSet>( declaredSingularAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getSingularAttributes() ); + } + return attributes; + } + + @Override + public Set> getDeclaredSingularAttributes() { + return new HashSet>( declaredSingularAttributes.values() ); + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + return attribute; + } + + @Override + public SingularAttribute getDeclaredSingularAttribute(String name) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkNotNull( "SingularAttribute ", attr, name ); + return attr; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name, Class type) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + checkTypeForSingleAttribute( "SingularAttribute ", attribute, name, type ); + return ( SingularAttribute ) attribute; + } + + @Override + @SuppressWarnings( "unchecked") + public SingularAttribute getDeclaredSingularAttribute(String name, Class javaType) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkTypeForSingleAttribute( "SingularAttribute ", attr, name, javaType ); + return ( SingularAttribute ) attr; + } + + private void checkTypeForSingleAttribute( + String attributeType, + SingularAttribute attribute, + String name, + Class javaType) { + if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) { + if ( isPrimitiveVariant( attribute, javaType ) ) { + return; + } + throw new IllegalArgumentException( + attributeType + " named " + name + + ( javaType != null ? " and of type " + javaType.getName() : "" ) + + " is not present" + ); + } + } + + @SuppressWarnings({ "SimplifiableIfStatement" }) + protected boolean isPrimitiveVariant(SingularAttribute attribute, Class javaType) { + if ( attribute == null ) { + return false; + } + Class declaredType = attribute.getBindableJavaType(); + + if ( declaredType.isPrimitive() ) { + return ( Boolean.class.equals( javaType ) && Boolean.TYPE.equals( declaredType ) ) + || ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) ) + || ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) ) + || ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) ) + || ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) ) + || ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) ) + || ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) ) + || ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) ); + } + + if ( javaType.isPrimitive() ) { + return ( Boolean.class.equals( declaredType ) && Boolean.TYPE.equals( javaType ) ) + || ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) ) + || ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) ) + || ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) ) + || ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) ) + || ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) ) + || ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) ) + || ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) ); + } + + return false; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public Set> getPluralAttributes() { + HashSet attributes = new HashSet>( declaredPluralAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getPluralAttributes() ); + } + return attributes; + } + + @Override + public Set> getDeclaredPluralAttributes() { + return new HashSet>( declaredPluralAttributes.values() ); + } + + @Override + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + private PluralAttribute getPluralAttribute(String name) { + return declaredPluralAttributes.get( name ); + } + + private void basicCollectionCheck(PluralAttribute attribute, String name) { + checkNotNull( "CollectionAttribute", attribute, name ); + if ( ! CollectionAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() ); + } + } + + @Override + @SuppressWarnings( "unchecked") + public CollectionAttribute getDeclaredCollection(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicSetCheck( attribute, name ); + return (SetAttribute) attribute; + } + + private void basicSetCheck(PluralAttribute attribute, String name) { + checkNotNull( "SetAttribute", attribute, name ); + if ( ! SetAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a SetAttribute: " + attribute.getClass() ); + } + } + + @Override + @SuppressWarnings( "unchecked") + public SetAttribute getDeclaredSet(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicSetCheck( attribute, name ); + return ( SetAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicListCheck( attribute, name ); + return (ListAttribute) attribute; + } + + private void basicListCheck(PluralAttribute attribute, String name) { + checkNotNull( "ListAttribute", attribute, name ); + if ( ! ListAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a ListAttribute: " + attribute.getClass() ); + } + } + + @Override + public ListAttribute getDeclaredList(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicListCheck( attribute, name ); + return ( ListAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicMapCheck( attribute, name ); + return (MapAttribute) attribute; + } + + private void basicMapCheck(PluralAttribute attribute, String name) { + checkNotNull( "MapAttribute", attribute, name ); + if ( ! MapAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a MapAttribute: " + attribute.getClass() ); + } + } + + @Override + public MapAttribute getDeclaredMap(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicMapCheck( attribute, name ); + return ( MapAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + @Override + public CollectionAttribute getDeclaredCollection(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + private void checkCollectionElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "CollectionAttribute", attribute, name, elementType, PluralAttribute.CollectionType.COLLECTION ); + } + + private void checkTypeForPluralAttributes( + String attributeType, + PluralAttribute attribute, + String name, + Class elementType, + PluralAttribute.CollectionType collectionType) { + if ( attribute == null + || ( elementType != null && !attribute.getBindableJavaType().equals( elementType ) ) + || attribute.getCollectionType() != collectionType ) { + throw new IllegalArgumentException( + attributeType + " named " + name + + ( elementType != null ? " and of element type " + elementType : "" ) + + " is not present" + ); + } + } + + @Override + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + private void checkSetElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "SetAttribute", attribute, name, elementType, PluralAttribute.CollectionType.SET ); + } + + @Override + public SetAttribute getDeclaredSet(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + private void checkListElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "ListAttribute", attribute, name, elementType, PluralAttribute.CollectionType.LIST ); + } + + @Override + public ListAttribute getDeclaredList(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name, Class keyType, Class valueType) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } + + private void checkMapValueType(PluralAttribute attribute, String name, Class valueType) { + checkTypeForPluralAttributes( "MapAttribute", attribute, name, valueType, PluralAttribute.CollectionType.MAP); + } + + private void checkMapKeyType(MapAttribute mapAttribute, String name, Class keyType) { + if ( mapAttribute.getKeyJavaType() != keyType ) { + throw new IllegalArgumentException( "MapAttribute named " + name + " does not support a key of type " + keyType ); + } + } + + @Override + public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractType.java similarity index 56% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java rename to hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractType.java index 8cc4854bc9..f8069c91f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/AbstractType.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by * third-party contributors as indicated by either @author tags or express * copyright attribution statements applied by the authors. All * third-party contributions are distributed under license by Red Hat Inc. @@ -21,38 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; +package org.hibernate.jpa.metamodel.internal; +import java.io.Serializable; +import javax.persistence.metamodel.Type; /** - * Models a simple, non-compound value. + * Defines commonality for the JPA {@link Type} hierarchy of interfaces. * * @author Steve Ebersole */ -public interface SimpleValue extends Value { - /** - * Retrieve the datatype of this value. - * - * @return The value's datatype - */ - public Datatype getDatatype(); +public abstract class AbstractType implements Type, Serializable { + private final Class javaType; - /** - * Set the datatype of this value. - * - * @param datatype The value's datatype - */ - public void setDatatype(Datatype datatype); + public AbstractType(Class javaType) { + this.javaType = javaType; + } - /** - * For any column name, generate an alias that is unique - * to that column name, unique across tables, and within - * alias size constraints determined by - * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. - * - * @param dialect the dialect. - * @return the alias. - */ - public String getAlias(Dialect dialect); + public Class getJavaType() { + return javaType; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/BasicTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/BasicTypeImpl.java new file mode 100644 index 0000000000..c7e9cc4f3f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/BasicTypeImpl.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; +import java.io.Serializable; +import javax.persistence.metamodel.BasicType; + +/** + * @author Emmanuel Bernard + */ +public class BasicTypeImpl implements BasicType, Serializable { + private final Class clazz; + private PersistenceType persistenceType; + + @Override + public PersistenceType getPersistenceType() { + return persistenceType; + } + + @Override + public Class getJavaType() { + return clazz; + } + + public BasicTypeImpl(Class clazz, PersistenceType persistenceType) { + this.clazz = clazz; + this.persistenceType = persistenceType; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EmbeddableTypeImpl.java new file mode 100644 index 0000000000..e12e492104 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EmbeddableTypeImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import java.io.Serializable; +import javax.persistence.metamodel.EmbeddableType; + +import org.hibernate.type.ComponentType; + +/** + * @author Emmanuel Bernard + */ +public class EmbeddableTypeImpl + extends AbstractManagedType + implements EmbeddableType, Serializable { + + private final AbstractManagedType parent; + private final ComponentType hibernateType; + + public EmbeddableTypeImpl(Class javaType, AbstractManagedType parent, ComponentType hibernateType) { + super( javaType, null ); + this.parent = parent; + this.hibernateType = hibernateType; + } + + @Override + public PersistenceType getPersistenceType() { + return PersistenceType.EMBEDDABLE; + } + + public AbstractManagedType getParent() { + return parent; + } + + public ComponentType getHibernateType() { + return hibernateType; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EntityTypeImpl.java new file mode 100644 index 0000000000..eed0bafb78 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/EntityTypeImpl.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; +import java.io.Serializable; +import javax.persistence.metamodel.EntityType; + +/** + * Defines the Hibernate implementation of the JPA {@link EntityType} contract. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class EntityTypeImpl + extends AbstractIdentifiableType + implements EntityType, Serializable { + private final String entityName; + + public EntityTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + String entityName, + boolean hasIdentifierProperty, + boolean isVersioned) { + super( javaType, superType, hasIdentifierProperty, isVersioned ); + this.entityName = entityName; + } + + @Override + public String getName() { + return entityName; + } + + @Override + public BindableType getBindableType() { + return BindableType.ENTITY_TYPE; + } + + @Override + public Class getBindableJavaType() { + return getJavaType(); + } + + @Override + public PersistenceType getPersistenceType() { + return PersistenceType.ENTITY; + } + + @Override + protected boolean requiresSupertypeForNonDeclaredIdentifier() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/JpaMetaModelPopulationSetting.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/JpaMetaModelPopulationSetting.java new file mode 100644 index 0000000000..1b5836555c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/JpaMetaModelPopulationSetting.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +/** +* @author Steve Ebersole +*/ +public enum JpaMetaModelPopulationSetting { + ENABLED, + DISABLED, + IGNORE_UNSUPPORTED; + + public static JpaMetaModelPopulationSetting parse(String setting) { + if ( "enabled".equalsIgnoreCase( setting ) ) { + return ENABLED; + } + else if ( "disabled".equalsIgnoreCase( setting ) ) { + return DISABLED; + } + else { + return IGNORE_UNSUPPORTED; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MappedSuperclassTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MappedSuperclassTypeImpl.java new file mode 100644 index 0000000000..ccd6706f89 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MappedSuperclassTypeImpl.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import javax.persistence.metamodel.MappedSuperclassType; + +/** + * @author Emmanuel Bernard + */ +public class MappedSuperclassTypeImpl extends AbstractIdentifiableType implements MappedSuperclassType { + public MappedSuperclassTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, superType, hasIdentifierProperty, versioned ); + } + + public PersistenceType getPersistenceType() { + return PersistenceType.MAPPED_SUPERCLASS; + } + + @Override + protected boolean requiresSupertypeForNonDeclaredIdentifier() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MetamodelImpl.java new file mode 100644 index 0000000000..63ea6a65f8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/MetamodelImpl.java @@ -0,0 +1,128 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.EmbeddableType; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.Metamodel; + +import org.hibernate.internal.util.collections.CollectionHelper; + +/** + * Hibernate implementation of the JPA {@link javax.persistence.metamodel.Metamodel} contract. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class MetamodelImpl implements Metamodel, Serializable { + private final Map, EntityTypeImpl> entityTypeMap; + private final Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap; + private final Map, EmbeddableTypeImpl> embeddableTypeMap; + private final Map> entityTypesByEntityName; + + /** + * Instantiate the metamodel. + * + * @param entityTypeMap The entity mappings. + * @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings + * @param embeddableTypeMap The embeddable (component) mappings. + */ + public MetamodelImpl( + Map, EntityTypeImpl> entityTypeMap, + Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap, + Map, EmbeddableTypeImpl> embeddableTypeMap, + Map> entityTypesByEntityName) { + this.entityTypeMap = entityTypeMap; + this.mappedSuperclassTypeMap = mappedSuperclassTypeMap; + this.embeddableTypeMap = embeddableTypeMap; + this.entityTypesByEntityName = entityTypesByEntityName; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public EntityType entity(Class cls) { + final EntityType entityType = entityTypeMap.get( cls ); + if ( entityType == null ) { + throw new IllegalArgumentException( "Not an entity: " + cls ); + } + return (EntityType) entityType; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public ManagedType managedType(Class cls) { + ManagedType type = entityTypeMap.get( cls ); + if ( type == null ) { + type = mappedSuperclassTypeMap.get( cls ); + } + if ( type == null ) { + type = embeddableTypeMap.get( cls ); + } + if ( type == null ) { + throw new IllegalArgumentException( "Not an managed type: " + cls ); + } + return (ManagedType) type; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public EmbeddableType embeddable(Class cls) { + final EmbeddableType embeddableType = embeddableTypeMap.get( cls ); + if ( embeddableType == null ) { + throw new IllegalArgumentException( "Not an embeddable: " + cls ); + } + return (EmbeddableType) embeddableType; + } + + @Override + public Set> getManagedTypes() { + final int setSize = CollectionHelper.determineProperSizing( + entityTypeMap.size() + mappedSuperclassTypeMap.size() + embeddableTypeMap.size() + ); + final Set> managedTypes = new HashSet>( setSize ); + managedTypes.addAll( entityTypeMap.values() ); + managedTypes.addAll( mappedSuperclassTypeMap.values() ); + managedTypes.addAll( embeddableTypeMap.values() ); + return managedTypes; + } + + @Override + public Set> getEntities() { + return new HashSet>( entityTypesByEntityName.values() ); + } + + @Override + public Set> getEmbeddables() { + return new HashSet>( embeddableTypeMap.values() ); + } + + public EntityTypeImpl getEntityTypeByName(String entityName) { + return entityTypesByEntityName.get( entityName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/PluralAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/PluralAttributeImpl.java new file mode 100644 index 0000000000..466e91234d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/PluralAttributeImpl.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +import java.io.Serializable; +import java.lang.reflect.Member; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.Type; + +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; + +/** + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public abstract class PluralAttributeImpl + extends AbstractAttribute + implements PluralAttribute, Serializable { + + private final Type elementType; + + @SuppressWarnings("unchecked") + private PluralAttributeImpl(Builder builder) { + super( + builder.attributeBinding.getAttribute().getName(), + builder.collectionClass, + builder.owner, + builder.member, + builder.persistentAttributeType + ); + this.elementType = builder.elementType; + } + + public static class Builder { + private final Class collectionClass; + private AbstractManagedType owner; + private PluralAttributeBinding attributeBinding; + private Member member; + private Type keyType; + private Type elementType; + private PersistentAttributeType persistentAttributeType; + + public Builder(Class collectionClass) { + this.collectionClass = collectionClass; + } + + public Builder owner(AbstractManagedType owner) { + this.owner = owner; + return this; + } + + public Builder member(Member member) { + this.member = member; + return this; + } + + public Builder binding(PluralAttributeBinding attributeBinding) { + this.attributeBinding = attributeBinding; + return this; + } + + public Builder elementType(Type elementType) { + this.elementType = elementType; + return this; + } + + public Builder keyType(Type keyType) { + this.keyType = keyType; + return this; + } + + public Builder persistentAttributeType(PersistentAttributeType attrType) { + this.persistentAttributeType = attrType; + return this; + } + + @SuppressWarnings( "unchecked" ) + public PluralAttributeImpl build() { + //apply strict spec rules first + if ( Map.class.equals( collectionClass ) ) { + return ( PluralAttributeImpl ) new MapAttributeImpl( this ); + } + else if ( Set.class.equals( collectionClass ) ) { + return ( PluralAttributeImpl ) new SetAttributeImpl( this ); + } + else if ( List.class.equals( collectionClass ) ) { + return ( PluralAttributeImpl ) new ListAttributeImpl( this ); + } + else if ( Collection.class.equals( collectionClass ) ) { + return ( PluralAttributeImpl ) new CollectionAttributeImpl( this ); + } + + //apply loose rules + if ( Map.class.isAssignableFrom( collectionClass ) ) { + return ( PluralAttributeImpl ) new MapAttributeImpl( this ); + } + else if ( Set.class.isAssignableFrom( collectionClass ) ) { + return ( PluralAttributeImpl ) new SetAttributeImpl( this ); + } + else if ( List.class.isAssignableFrom( collectionClass ) ) { + return ( PluralAttributeImpl ) new ListAttributeImpl( this ); + } + else if ( Collection.class.isAssignableFrom( collectionClass ) ) { + return ( PluralAttributeImpl ) new CollectionAttributeImpl( this ); + } + throw new UnsupportedOperationException( "Unknown collection: " + collectionClass ); + } + } + + public static Builder builder(Class collectionClass) { + return new Builder( collectionClass ); + } + + @Override + public Type getElementType() { + return elementType; + } + + @Override + public boolean isAssociation() { + return true; + } + + @Override + public boolean isCollection() { + return true; + } + + @Override + public BindableType getBindableType() { + return BindableType.PLURAL_ATTRIBUTE; + } + + @Override + public Class getBindableJavaType() { + return elementType.getJavaType(); + } + + static class SetAttributeImpl extends PluralAttributeImpl,E> implements SetAttribute { + SetAttributeImpl(Builder xceBuilder) { + super( xceBuilder ); + } + + @Override + public CollectionType getCollectionType() { + return CollectionType.SET; + } + } + + static class CollectionAttributeImpl extends PluralAttributeImpl,E> implements CollectionAttribute { + CollectionAttributeImpl(Builder xceBuilder) { + super( xceBuilder ); + } + + @Override + public CollectionType getCollectionType() { + return CollectionType.COLLECTION; + } + } + + static class ListAttributeImpl extends PluralAttributeImpl,E> implements ListAttribute { + ListAttributeImpl(Builder xceBuilder) { + super( xceBuilder ); + } + + @Override + public CollectionType getCollectionType() { + return CollectionType.LIST; + } + } + + static class MapAttributeImpl extends PluralAttributeImpl,V> implements MapAttribute { + private final Type keyType; + + @SuppressWarnings("unchecked") + MapAttributeImpl(Builder xceBuilder) { + super( xceBuilder ); + this.keyType = xceBuilder.keyType; + } + + @Override + public CollectionType getCollectionType() { + return CollectionType.MAP; + } + + @Override + public Class getKeyJavaType() { + return keyType.getJavaType(); + } + + @Override + public Type getKeyType() { + return keyType; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/SingularAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/SingularAttributeImpl.java new file mode 100644 index 0000000000..ec478c3a21 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/SingularAttributeImpl.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; +import java.io.Serializable; +import java.lang.reflect.Member; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +/** + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public class SingularAttributeImpl + extends AbstractAttribute + implements SingularAttribute, Serializable { + private final boolean isIdentifier; + private final boolean isVersion; + private final boolean isOptional; + private final Type attributeType; + + public SingularAttributeImpl( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + boolean isIdentifier, + boolean isVersion, + boolean isOptional, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, persistentAttributeType ); + this.isIdentifier = isIdentifier; + this.isVersion = isVersion; + this.isOptional = isOptional; + this.attributeType = attributeType; + } + + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * identifier. + */ + public static class Identifier extends SingularAttributeImpl { + public Identifier( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, true, false, false, attributeType, persistentAttributeType ); + } + } + + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * version. + */ + public static class Version extends SingularAttributeImpl { + public Version( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, false, true, false, attributeType, persistentAttributeType ); + } + } + + @Override + public boolean isId() { + return isIdentifier; + } + + @Override + public boolean isVersion() { + return isVersion; + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public Type getType() { + return attributeType; + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean isCollection() { + return false; + } + + @Override + public BindableType getBindableType() { + return BindableType.SINGULAR_ATTRIBUTE; + } + + @Override + public Class getBindableJavaType() { + return attributeType.getJavaType(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/UnsupportedFeature.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/UnsupportedFeature.java new file mode 100644 index 0000000000..65ce3dec77 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/UnsupportedFeature.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal; + +/** + * Represents Hibernate mapping features that are not supported in JPA metamodel. Used to allow control over how + * such features are handled in regards to building the JPA {@link javax.persistence.metamodel.Metamodel} instance. + * + * @author Steve Ebersole +*/ +public enum UnsupportedFeature { + ANY( "ANY mappings not supported in JPA metamodel" ), + ARRAY( "Arrays (HBM mappings) are not supported in JPA metamodel" ); + + private final String message; + + UnsupportedFeature(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeBuilder.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeBuilder.java new file mode 100644 index 0000000000..cf7c211040 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeBuilder.java @@ -0,0 +1,704 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import javax.persistence.OneToOne; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Attribute.PersistentAttributeType; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; + +import org.jboss.logging.Logger; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.metamodel.internal.AbstractIdentifiableType; +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.jpa.metamodel.internal.BasicTypeImpl; +import org.hibernate.jpa.metamodel.internal.EmbeddableTypeImpl; +import org.hibernate.jpa.metamodel.internal.MappedSuperclassTypeImpl; +import org.hibernate.jpa.metamodel.internal.PluralAttributeImpl; +import org.hibernate.jpa.metamodel.internal.SingularAttributeImpl; +import org.hibernate.jpa.metamodel.internal.UnsupportedFeature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.MapBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.type.ComponentType; +import org.hibernate.type.EmbeddedComponentType; + +/** + * A factory for building {@link Attribute} instances. Exposes 3 main services:

    + *
  1. {@link #buildAttribute} for building normal attributes
  2. + *
  3. {@link #buildIdAttribute} for building identifier attributes
  4. + *
  5. {@link #buildVersionAttribute} for building version attributes}
  6. + *
      + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class AttributeBuilder { + private static final Logger LOG = Logger.getLogger( AttributeBuilder.class.getName() ); + + /** + * The context for attribute building + */ + public static interface Context { + public Type locateEntityTypeByName(String entityName); + + public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType); + + public SessionFactoryImplementor getSessionFactory(); + + public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass); + + public void handleUnsupportedFeature(UnsupportedFeature feature); + } + + private final Context context; + + public AttributeBuilder(Context context) { + this.context = context; + } + + /** + * Build a normal attribute. + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs) + */ + public Attribute buildAttribute(AbstractManagedType ownerType, AttributeBinding attributeBinding) { + if ( attributeBinding.getAttribute().isSynthetic() ) { + // hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel. + LOG.tracef( + "Skipping synthetic property %s(%s)", + ownerType.getJavaType().getName(), + attributeBinding.getAttribute().getName() + ); + return null; + } + LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + attributeBinding.getAttribute().getName() + "]"); + final AttributeMetadata attributeMetadata = determineAttributeMetadata( + ownerType, + attributeBinding, + NORMAL_MEMBER_RESOLVER + ); + if ( attributeMetadata == null ) { + return null; + } + if ( attributeMetadata.isPlural() ) { + return buildPluralAttribute( (PluralAttributeMetadata) attributeMetadata ); + } + final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata)attributeMetadata; + final Type metaModelType = getSingularAttributeMetaModelType( singularAttributeMetadata.getAttributeTypeDescriptor() ); + //noinspection unchecked + return new SingularAttributeImpl( + attributeMetadata.getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + false, + false, + true, // todo : need to handle this somehow : property.isOptional(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + /** + * Build the identifier attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildIdAttribute(AbstractIdentifiableType ownerType, AttributeBinding attributeBinding) { + LOG.trace( + "Building identifier attribute [" + ownerType.getJavaType().getName() + "#" + + attributeBinding.getAttribute().getName() + "]" + ); + final SingularAttributeMetadata attributeMetadata = (SingularAttributeMetadata) determineAttributeMetadata( + ownerType, + attributeBinding, + IDENTIFIER_MEMBER_RESOLVER + ); + final Type metaModelType = getSingularAttributeMetaModelType( attributeMetadata.getAttributeTypeDescriptor() ); + return new SingularAttributeImpl.Identifier( + attributeBinding.getAttribute().getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + /** + * Build the version attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildVersionAttribute(AbstractIdentifiableType ownerType, AttributeBinding attributeBinding) { + LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]"); + final SingularAttributeMetadata attributeMetadata = (SingularAttributeMetadata) determineAttributeMetadata( + ownerType, + attributeBinding, + VERSION_MEMBER_RESOLVER + ); + final Type metaModelType = getSingularAttributeMetaModelType( attributeMetadata.getAttributeTypeDescriptor() ); + return new SingularAttributeImpl.Version( + attributeBinding.getAttribute().getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + @SuppressWarnings( "unchecked" ) + private PluralAttribute buildPluralAttribute(PluralAttributeMetadata attributeMetadata) { + final PluralAttributeBinding pluralAttributeBinding = + (PluralAttributeBinding) attributeMetadata.getAttributeBinding(); + + final Type elementType = getPluralAttributeElementMetaModelType( + attributeMetadata.getElementAttributeTypeDescriptor() + ); + if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { + final Type keyType = getPluralAttributeMapKeyMetaModelType( + attributeMetadata.getMapKeyAttributeTypeDescriptor() + ); + return PluralAttributeImpl.builder( attributeMetadata.getJavaType() ) + .owner( attributeMetadata.getOwnerType() ) + .elementType( elementType ) + .keyType( keyType ) + .member( attributeMetadata.getMember() ) + .binding( pluralAttributeBinding ) + .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) + .build(); + } + return PluralAttributeImpl.builder( attributeMetadata.getJavaType() ) + .owner( attributeMetadata.getOwnerType() ) + .elementType( elementType ) + .member( attributeMetadata.getMember() ) + .binding( pluralAttributeBinding ) + .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) + .build(); + } + + @SuppressWarnings( "unchecked" ) + private Type getSingularAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( !attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected singular attribute binding, but it was plural: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + if ( ! ( attributeBinding instanceof CompositeAttributeBinding ) ) { + throw new IllegalArgumentException( + String.format( + "Unexpected type of attribute binding. Expected: %s; Actual: %s", + CompositeAttributeBinding.class.getName(), + attributeBinding.getClass().getName() + ) + ); + } + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + (CompositeAttributeBinding) attributeBinding + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getPluralAttributeElementMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + final AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected plural attribute binding, but it was singular: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + final CompositePluralAttributeElementBinding compositePluralAttributeElementBinding = + (CompositePluralAttributeElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding(); + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + compositePluralAttributeElementBinding.getCompositeAttributeBindingContainer() + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getPluralAttributeMapKeyMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + final AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected plural attribute binding, but it was singular: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + if ( ! ( attributeBinding instanceof MapBinding ) ) { + throw new IllegalArgumentException( + String.format( + "Expected a map binding: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + final MapBinding mapBinding = (MapBinding) attributeBinding; + final CompositePluralAttributeIndexBinding pluralAttributeIndexBinding = + (CompositePluralAttributeIndexBinding) mapBinding.getPluralAttributeIndexBinding(); + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + pluralAttributeIndexBinding.getCompositeAttributeBindingContainer() + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getBasicAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.BASIC ); + return new BasicTypeImpl( + attributeTypeDescriptor.getBindableType(), + Type.PersistenceType.BASIC + ); + } + + @SuppressWarnings( "unchecked" ) + private Type getEntityAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.ENTITY ); + final org.hibernate.type.EntityType type = (org.hibernate.type.EntityType) attributeTypeDescriptor.getHibernateType(); + return (Type) context.locateEntityTypeByName( type.getAssociatedEntityName() ); + } + + @SuppressWarnings( "unchecked" ) + private Type getEmbeddableAttributeMetaModelType( + AttributeTypeDescriptor attributeTypeDescriptor, + CompositeAttributeBindingContainer compositeAttributeBindingContainer) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.EMBEDDABLE ); + if ( ! compositeAttributeBindingContainer.isAggregated() ) { + throw new IllegalArgumentException( + "Composite attribute binding is not aggregated." + ); + } + final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl( + attributeTypeDescriptor.getBindableType(), + attributeTypeDescriptor.getAttributeMetadata().getOwnerType(), + (ComponentType) attributeTypeDescriptor.getHibernateType() + ); + context.registerEmbeddedableType( embeddableType ); + for ( AttributeBinding subAttributeBinding : compositeAttributeBindingContainer.attributeBindings() ) { + final Attribute attribute = buildAttribute( embeddableType, subAttributeBinding ); + if ( attribute != null ) { + embeddableType.getBuilder().addAttribute( attribute ); + } + } + embeddableType.lock(); + return embeddableType; + } + + private void checkCorrectValueClassification( + AttributeTypeDescriptor attributeTypeDescriptor, + AttributeTypeDescriptor.ValueClassification expectedValueClassification) { + if ( attributeTypeDescriptor.getValueClassification() != expectedValueClassification ) { + throw new IllegalArgumentException( + String.format( + "Unexpected value classification for [%s]; expected:[%s] actual:[%s]", + attributeTypeDescriptor, + expectedValueClassification, + attributeTypeDescriptor.getValueClassification() + ) + ); + } + } + + private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType ownerType) { + final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); + if ( persistenceType == Type.PersistenceType.ENTITY) { + String entityName; + if ( ownerType instanceof EntityType ) { + entityName = ( ( EntityType ) ownerType ).getName(); + } else { + entityName = ownerType.getJavaType().getName(); + } + return context.getSessionFactory() + .getEntityPersister( entityName ).getEntityMetamodel(); + } + else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) { + return context.getSubClassEntityPersister( (MappedSuperclassTypeImpl) ownerType ).getEntityMetamodel(); + } + else { + throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType ); + } + } + + /** + * Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata + * against the known Hibernate metadata and build a descriptor for the attribute. + * + * @param jpaOwner The JPA representation of the attribute owner + * @param attributeBinding Hibernate metamodel representation of the attribute binding + * @param memberResolver Strategy for how to resolve the member defining the attribute. + * + * @return The attribute description + */ + @SuppressWarnings({ "unchecked" }) + private AttributeMetadata determineAttributeMetadata( + AbstractManagedType jpaOwner, + AttributeBinding attributeBinding, + MemberResolver memberResolver) { + LOG.trace("Starting attribute metadata determination [" + attributeBinding.getAttribute().getName() + "]"); + final Member member = memberResolver.resolveMember( jpaOwner, attributeBinding ); + LOG.trace(" Determined member [" + member + "]"); + + final org.hibernate.type.Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]"); + + if ( type.isAnyType() ) { + // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + + final PersistentAttributeType jpaAttributeType; + if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isAggregate() ) { + jpaAttributeType = PersistentAttributeType.EMBEDDED; + } + else if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isAssociation() ) { + jpaAttributeType = determineSingularAssociationAttributeType( member ); + } + else { + jpaAttributeType = PersistentAttributeType.BASIC; + } + return new SingularAttributeMetadataImpl( attributeBinding, jpaOwner, member, jpaAttributeType ); + } + else { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + + if ( pluralAttributeBinding.getAttribute().getNature() == org.hibernate.metamodel.spi.domain.PluralAttribute.Nature.ARRAY ) { + context.handleUnsupportedFeature( UnsupportedFeature.ARRAY ); + return null; + } + + // First, determine the type of the elements and use that to help determine the + // collection type) + final PluralAttributeElementBinding elementBinding = pluralAttributeBinding.getPluralAttributeElementBinding(); + final PluralAttributeElementBinding.Nature elementNature = elementBinding.getNature(); + final PersistentAttributeType persistentAttributeType; + final PersistentAttributeType elementPersistentAttributeType; + PersistentAttributeType keyPersistentAttributeType = null; + + if ( elementNature == PluralAttributeElementBinding.Nature.MANY_TO_ANY ) { + // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + else if ( elementNature == PluralAttributeElementBinding.Nature.BASIC ) { + elementPersistentAttributeType = PersistentAttributeType.BASIC; + persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION; + } + else if ( elementNature == PluralAttributeElementBinding.Nature.AGGREGATE ) { + elementPersistentAttributeType = PersistentAttributeType.EMBEDDED; + persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION; + } + else { + elementPersistentAttributeType = elementNature == PluralAttributeElementBinding.Nature.MANY_TO_MANY + ? PersistentAttributeType.MANY_TO_MANY + : PersistentAttributeType.ONE_TO_MANY; + persistentAttributeType = elementPersistentAttributeType; + } + + // For maps, also check the key binding + if ( pluralAttributeBinding.getAttribute().getNature() == org.hibernate.metamodel.spi.domain.PluralAttribute.Nature.MAP ) { + final IndexedPluralAttributeBinding indexedPluralAttributeBinding + = (IndexedPluralAttributeBinding) pluralAttributeBinding; + final PluralAttributeIndexBinding.Nature indexNature + = indexedPluralAttributeBinding.getPluralAttributeIndexBinding().getNature(); + + if ( indexNature == PluralAttributeIndexBinding.Nature.MANY_TO_ANY ) { + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + else if ( indexNature == PluralAttributeIndexBinding.Nature.MANY_TO_MANY ) { + keyPersistentAttributeType = Attribute.PersistentAttributeType.MANY_TO_ONE; + } + else if ( indexNature == PluralAttributeIndexBinding.Nature.AGGREGATE ) { + keyPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED; + } + else { + keyPersistentAttributeType = Attribute.PersistentAttributeType.BASIC; + } + } + + return new PluralAttributeMetadataImpl( + pluralAttributeBinding, + jpaOwner, + member, + persistentAttributeType, + elementPersistentAttributeType, + keyPersistentAttributeType + ); + } + } + + public static PersistentAttributeType determineSingularAssociationAttributeType(Member member) { + if ( Field.class.isInstance( member ) ) { + return ( (Field) member ).getAnnotation( OneToOne.class ) != null + ? PersistentAttributeType.ONE_TO_ONE + : PersistentAttributeType.MANY_TO_ONE; + } + else { + return ( (Method) member ).getAnnotation( OneToOne.class ) != null + ? PersistentAttributeType.ONE_TO_ONE + : PersistentAttributeType.MANY_TO_ONE; + } + } + + public static ParameterizedType getSignatureType(Member member) { + final java.lang.reflect.Type type = Field.class.isInstance( member ) + ? ( ( Field ) member ).getGenericType() + : ( ( Method ) member ).getGenericReturnType(); + //this is a raw type + if ( type instanceof Class ) return null; + return (ParameterizedType) type; + } + + public static Class determineDeclaredType( Member member ) { + final Class declaredType; + // we can support method or field members here. Is there really any other valid type? + if ( Field.class.isInstance( member ) ) { + declaredType = ( (Field) member ).getType(); + } + else if ( Method.class.isInstance( member ) ) { + declaredType = ( (Method) member ).getReturnType(); + } + else { + throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" ); + } + return declaredType; + } + + public static PluralAttribute.CollectionType determineCollectionType(Class javaType) { + if ( java.util.List.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.LIST; + } + else if ( java.util.Set.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.SET; + } + else if ( java.util.Map.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.MAP; + } + else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.COLLECTION; + } + else { + throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" ); + } + } + +// public static boolean isManyToMany(Member member) { +// return Field.class.isInstance( member ) +// ? ( (Field) member ).getAnnotation( ManyToMany.class ) != null +// : ( (Method) member ).getAnnotation( ManyToMany.class ) != null; +// } + + private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl ) owner; + final String attributeName = attributeBinding.getAttribute().getName(); + return embeddableType.getHibernateType() + .getComponentTuplizer() + .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + + private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final IdentifiableType identifiableType = (IdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) { + throw new IllegalArgumentException( "expecting a virtual (non-aggregated composite) identifier mapping" ); + } + org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType(); + if ( entityMetamodel.getIdentifierProperty().hasIdentifierMapper() ) { + if ( ! ComponentType.class.isInstance( type ) ) { + throw new IllegalArgumentException( "expecting an idclass identifier mapping" ); + } + } + else { + if ( ! EmbeddedComponentType.class.isInstance( type ) ) { + throw new IllegalArgumentException( "expecting a non-aggregated composite identifier mapping" ); + } + } + + final ComponentType componentType = (ComponentType) type; + final String attributeName = attributeBinding.getAttribute().getName(); + return componentType.getComponentTuplizer() + .getGetter( componentType.getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + /** + * A {@link Member} resolver for normal attributes. + */ + private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final Type.PersistenceType persistenceType = owner.getPersistenceType(); + if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) { + return EMBEDDED_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + else if ( Type.PersistenceType.ENTITY == persistenceType + || Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) { + final IdentifiableType identifiableType = (IdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String propertyName = attributeBinding.getAttribute().getName(); + final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName ); + if ( index == null ) { + // just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + else { + return entityMetamodel.getTuplizer() + .getGetter( index ) + .getMember(); + } + } + else { + throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType ); + } + } + }; + + private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final IdentifiableType identifiableType = (IdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String attributeName = attributeBinding.getAttribute().getName(); + if ( ! attributeName.equals( entityMetamodel.getIdentifierProperty().getName() ) ) { + // this *should* indicate processing part of an IdClass... + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + return entityMetamodel.getTuplizer().getIdentifierGetter().getMember(); + } + }; + + private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final IdentifiableType identifiableType = (IdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String versionPropertyName = attributeBinding.getAttribute().getName(); + if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) { + // this should never happen, but to be safe... + throw new IllegalArgumentException( "Given property did not match declared version property" ); + } + return entityMetamodel.getTuplizer().getVersionGetter().getMember(); + } + }; +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeMetadata.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeMetadata.java new file mode 100644 index 0000000000..5731149729 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeMetadata.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Basic contract for describing an attribute in a format needed while building the JPA metamodel. + * + * The "description" is described:
        + *
      1. partially in terms of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType})
      2. + *
      3. partially in terms of Hibernate metamodel ({@link #getAttributeBinding})
      4. + *
      5. and partially just in terms of the java model itself ({@link #getMember} and {@link #getJavaType})
      6. + *
      + * + * @param The attribute owner type + * @param The attribute type. + */ +public interface AttributeMetadata { + /** + * Retrieve the name of the attribute + * + * @return The attribute name + */ + public String getName(); + + /** + * Retrieve the member defining the attribute + * + * @return The attribute member + */ + public Member getMember(); + + /** + * Retrieve the attribute java type. + * + * @return The java type of the attribute. + */ + public Class getJavaType(); + + /** + * Get the JPA attribute type classification for this attribute. + * + * @return The JPA attribute type classification + */ + public Attribute.PersistentAttributeType getPersistentAttributeType(); + + /** + * Retrieve the attribute owner's metamodel information + * + * @return The metamodel information for the attribute owner + */ + public AbstractManagedType getOwnerType(); + + /** + * Retrieve the Hibernate property mapping related to this attribute. + * + * @return The Hibernate property mapping + */ + public AttributeBinding getAttributeBinding(); + + /** + * Is the attribute plural (a collection)? + * + * @return True if it is plural, false otherwise. + */ + public boolean isPlural(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeTypeDescriptor.java new file mode 100644 index 0000000000..e283bf9776 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/AttributeTypeDescriptor.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +/** + * Centralized access to a variety of information about a the type of an attribute being built for the JPA metamodel. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface AttributeTypeDescriptor { + /** + * Enum of the simplified types a value might be. These relate more to the Hibernate classification + * then the JPA classification + */ + enum ValueClassification { + EMBEDDABLE, + ENTITY, + BASIC + } + + public org.hibernate.type.Type getHibernateType(); + + public Class getBindableType(); + + /** + * Retrieve the simplified value classification + * + * @return The value type + */ + public ValueClassification getValueClassification(); + + /** + * Retrieve the metadata about the attribute from which this value comes + * + * @return The "containing" attribute metadata. + */ + public AttributeMetadata getAttributeMetadata(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/BaseAttributeMetadata.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/BaseAttributeMetadata.java new file mode 100644 index 0000000000..4d9cf2ec02 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/BaseAttributeMetadata.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Base implementation of AttributeMetadata + * + * @author Steve Ebersole + */ +public abstract class BaseAttributeMetadata implements AttributeMetadata { + private final AttributeBinding attributeBinding; + private final AbstractManagedType ownerType; + private final Member member; + private final Class javaType; + private final Attribute.PersistentAttributeType persistentAttributeType; + + @SuppressWarnings({ "unchecked" }) + public BaseAttributeMetadata( + AttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + this.attributeBinding = attributeBinding; + this.ownerType = ownerType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + + this.javaType = (Class) AttributeBuilder.determineDeclaredType( member ); + } + + @Override + public String getName() { + return attributeBinding.getAttribute().getName(); + } + + @Override + public Member getMember() { + return member; + } + + public String getMemberDescription() { + return determineMemberDescription( getMember() ); + } + + public String determineMemberDescription(Member member) { + return member.getDeclaringClass().getName() + '#' + member.getName(); + } + + @Override + public Class getJavaType() { + return javaType; + } + + @Override + public Attribute.PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + @Override + public AbstractManagedType getOwnerType() { + return ownerType; + } + + @Override + public boolean isPlural() { + return ! attributeBinding.getAttribute().isSingular(); + } + + @Override + public AttributeBinding getAttributeBinding() { + return attributeBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MemberResolver.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MemberResolver.java new file mode 100644 index 0000000000..8581f00d43 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MemberResolver.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Member; + +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Contract for how we resolve the {@link java.lang.reflect.Member} for a given attribute context. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface MemberResolver { + /** + * Resolve the member. + * + * @param owner The JPA Metamodel representation of the class tha owns the member to be resolved + * @param attributeBinding Hibernate metamodel representation of the attribute for which to resolve the member. + * + * @return The resolved member. + */ + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MetamodelBuilder.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MetamodelBuilder.java new file mode 100644 index 0000000000..e346014116 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/MetamodelBuilder.java @@ -0,0 +1,532 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +import org.jboss.logging.Logger; + +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.metamodel.internal.AbstractIdentifiableType; +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.jpa.metamodel.internal.EmbeddableTypeImpl; +import org.hibernate.jpa.metamodel.internal.EntityTypeImpl; +import org.hibernate.jpa.metamodel.internal.JpaMetaModelPopulationSetting; +import org.hibernate.jpa.metamodel.internal.MappedSuperclassTypeImpl; +import org.hibernate.jpa.metamodel.internal.MetamodelImpl; +import org.hibernate.jpa.metamodel.internal.UnsupportedFeature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; +import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.Hierarchical; +import org.hibernate.metamodel.spi.domain.Superclass; +import org.hibernate.persister.entity.EntityPersister; + +/** + * Defines the contract for building JPA Metamodel ({@link org.hibernate.jpa.metamodel.internal.MetamodelImpl}). + *

      + * Contract is made up of:

        + *
      1. Instantiating this builder
      2. + *
      3. adding all managed mapping classes to it ({@link #add})
      4. + *
      5. calling {@link #buildMetamodel}
      6. + *
      + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class MetamodelBuilder { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + MetamodelBuilder.class.getName() + ); + private final SessionFactoryImplementor sessionFactory; + + // these maps eventually make up the JPA Metamodel + private final Map,EntityTypeImpl> entityTypeMap = new HashMap, EntityTypeImpl>(); + private final Map, EmbeddableTypeImpl> embeddableTypeMap = new HashMap, EmbeddableTypeImpl>(); + private final Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap = new HashMap, MappedSuperclassTypeImpl>(); + + // these fields are needed just for the duration of building the metamodel + private final JpaMetaModelPopulationSetting populationSetting; + private final AttributeBuilder attributeBuilder; + private final Map> entityTypeByNameMap = new HashMap>(); + private final Map mappedSuperclassEntityNameMap = new HashMap(); + private List entityBindingList = new ArrayList(); + private Set alreadyProcessed = new HashSet(); + + + public MetamodelBuilder(SessionFactoryImplementor sessionFactory, JpaMetaModelPopulationSetting populationSetting) { + this.sessionFactory = sessionFactory; + this.populationSetting = populationSetting; + this.attributeBuilder = new AttributeBuilder( new AttributeBuilderContext() ); + } + + public void add(EntityBinding entityBinding) { + if ( entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO ) { + locateOrBuildEntityType( entityBinding ); + } + entityBindingList.add( entityBinding ); + } + + private EntityTypeImpl locateOrBuildEntityType(EntityBinding binding) { + EntityTypeImpl entityType = entityTypeByNameMap.get( binding.getEntityName() ); + if ( entityType == null ) { + entityType = buildEntityType( binding ); + } + return entityType; + } + + @SuppressWarnings("unchecked") + private EntityTypeImpl buildEntityType(EntityBinding entityBinding) { + final Class javaType = entityBinding.getClassReference(); + final AbstractIdentifiableType superType = locateOrBuildSuperType( entityBinding.getEntity().getSuperType(), entityBinding ); + + EntityTypeImpl entityType = new EntityTypeImpl( + javaType, + superType, + entityBinding.getEntityName(), + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null, + entityBinding.isVersioned() + ); + + entityTypeMap.put( javaType, entityType ); + entityTypeByNameMap.put( entityBinding.getEntityName(), entityType ); + return entityType; + } + + /** + * IMPORTANT!!! This method is called in 2 somewhat different cases:
        + *
      1. resolving super class for @Entity
      2. + *
      3. resolving super class for @MappedSuperclass
      4. + *
      + * Make sure changes fit both uses + * + * @param superDescriptor Hibernate metamodel descriptor of the super class + * @param entityBinding The Hibernate metamodel entity binding; could be describing different class between the + * 2 use cases described above. + * + * @return The super type. + */ + private AbstractIdentifiableType locateOrBuildSuperType(Hierarchical superDescriptor, EntityBinding entityBinding) { + if ( superDescriptor == null ) { + return null; + } + + // the super type here could be either a "mapped superclass" or an entity + if ( Entity.class.isInstance( superDescriptor ) ) { + // make sure super entity binding points to same... + final EntityBinding superBinding = entityBinding.getSuperEntityBinding(); + if ( superBinding == null ) { + throw new IllegalStateException( "EntityBinding with super class of Entity type did not specify super entity binding" ); + } + if ( superBinding.getEntity() != superDescriptor ) { + throw new IllegalStateException( "Super entity binding and descriptor referenced different descriptors" ); + } + return locateOrBuildEntityType( superBinding ); + } + else if ( Superclass.class.isInstance( superDescriptor ) ) { + return locateOrBuildMappedSuperclassType( (Superclass) superDescriptor, entityBinding ); + } + else { + throw new IllegalStateException( + "Unexpected type for entity super descriptor; expecting Entity or Superclass, found [" + + superDescriptor.getClassName() + "]" + ); + } + } + + private MappedSuperclassTypeImpl locateOrBuildMappedSuperclassType(Superclass superDescriptor, EntityBinding entityBinding) { + MappedSuperclassTypeImpl mappedSuperclassType = mappedSuperclassTypeMap.get( superDescriptor.getClassReference() ); + if ( mappedSuperclassType == null ) { + mappedSuperclassType = buildMappedSuperclassType( superDescriptor, entityBinding ); + } + return mappedSuperclassType; + } + + @SuppressWarnings("unchecked") + private MappedSuperclassTypeImpl buildMappedSuperclassType(Superclass superDescriptor, EntityBinding entityBinding) { + final Class javaType = superDescriptor.getClassReference(); + final AbstractIdentifiableType superSuperType = locateOrBuildSuperType( superDescriptor, entityBinding ); + + MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( + javaType, + superSuperType, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null, + entityBinding.isVersioned() + ); + + mappedSuperclassTypeMap.put( javaType, mappedSuperclassType ); + mappedSuperclassEntityNameMap.put( mappedSuperclassType, entityBinding.getEntity().getName() ); + return mappedSuperclassType; + } + + public MetamodelImpl buildMetamodel() { + LOG.trace( "Building JPA Metamodel instance..." ); + // we need to process types from superclasses to subclasses + for ( EntityBinding entityBinding : entityBindingList ) { + processHierarchy( entityBinding ); + } + + for ( EmbeddableTypeImpl embeddable : embeddableTypeMap.values() ) { + populateStaticMetamodel( embeddable ); + } + + + return new MetamodelImpl( + entityTypeMap, + mappedSuperclassTypeMap, + embeddableTypeMap, + entityTypeByNameMap + ); + } + + private void processHierarchy(EntityBinding entityBinding) { + LOG.trace( " Starting binding [" + entityBinding.getEntity().getName() + "]" ); + processType( entityBinding.getEntity(), entityBinding ); + } + + /** + * Performs a depth-first traversal of the super types... + * + * @param descriptor The type descriptor to process + * @param entityBinding + */ + private void processType(Hierarchical descriptor, EntityBinding entityBinding) { + if ( descriptor == null ) { + return; + } + + if ( alreadyProcessed.contains( descriptor ) ) { + return; + } + alreadyProcessed.add( descriptor ); + + // perform a depth-first traversal of the super types... + processSuperType( descriptor, entityBinding ); + + final AbstractIdentifiableType jpaDescriptor = Entity.class.isInstance( descriptor ) + ? entityTypeByNameMap.get( descriptor.getName() ) + : mappedSuperclassTypeMap.get( descriptor.getClassReference() ); + if ( jpaDescriptor == null && entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) { + return; + } + applyIdMetadata( descriptor, entityBinding.getHierarchyDetails(), jpaDescriptor ); + applyVersionAttribute( descriptor, entityBinding.getHierarchyDetails(), jpaDescriptor ); + + for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { + continue; + } + if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ) { + // skip the version property, it was already handled previously. + continue; + } + final Attribute attribute = attributeBuilder.buildAttribute( jpaDescriptor, attributeBinding ); + if ( attribute != null ) { + //noinspection unchecked + jpaDescriptor.getBuilder().addAttribute( attribute ); + } + } + jpaDescriptor.lock(); + populateStaticMetamodel( jpaDescriptor ); + } + + private void processSuperType(Hierarchical descriptor, EntityBinding entityBinding) { + final Hierarchical superDescriptor = descriptor.getSuperType(); + final EntityBinding superEntityBinding = Entity.class.isInstance( superDescriptor ) + ? entityBinding.getSuperEntityBinding() + : entityBinding; + processType( superDescriptor, superEntityBinding ); + } + + private void applyIdMetadata( + Hierarchical descriptor, + HierarchyDetails hierarchyDetails, + AbstractIdentifiableType jpaDescriptor) { + switch ( hierarchyDetails.getEntityIdentifier().getNature() ) { + case SIMPLE: { + SingularNonAssociationAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdAttribute( + attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding ) + ); + } + } + break; + } + case AGGREGATED_COMPOSITE: { + CompositeAttributeBinding idAttributeBinding = + (CompositeAttributeBinding) hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdAttribute( + attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding ) + ); + } + } + break; + } + default: { + // nature == (non-aggregated) COMPOSITE + CompositeAttributeBinding idAttributeBinding = + (CompositeAttributeBinding) hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + Set idClassAttributes = new HashSet(); + for ( AttributeBinding idClassAttributeBinding : idAttributeBinding.attributeBindings() ) { + idClassAttributes.add( attributeBuilder.buildIdAttribute( jpaDescriptor, idClassAttributeBinding ) ); + } + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdClassAttributes( idClassAttributes ); + } + } + } + } + } + + private void applyVersionAttribute( + Hierarchical descriptor, + HierarchyDetails hierarchyDetails, + AbstractIdentifiableType jpaDescriptor) { + final BasicAttributeBinding versionBinding = hierarchyDetails.getEntityVersion().getVersioningAttributeBinding(); + if ( versionBinding != null ) { + if ( versionBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyVersionAttribute( + attributeBuilder.buildVersionAttribute( jpaDescriptor, versionBinding ) + ); + } + } + } + + private void populateStaticMetamodel(AbstractManagedType jpaDescriptor) { + if ( populationSetting == JpaMetaModelPopulationSetting.DISABLED ) { + return; + } + final Class managedTypeClass = jpaDescriptor.getJavaType(); + final String metamodelClassName = managedTypeClass.getName() + "_"; + try { + final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); + // we found the class; so populate it... + registerAttributes( metamodelClass, jpaDescriptor ); + } + catch ( ClassNotFoundException ignore ) { + // nothing to do... + } + + AbstractManagedType superType = jpaDescriptor.getSupertype(); + if ( superType != null ) { + populateStaticMetamodel( superType ); + } + + } + + + private final Set processedMetamodelClasses = new HashSet(); + + private void registerAttributes(Class metamodelClass, AbstractManagedType managedType) { + if ( !processedMetamodelClasses.add( metamodelClass ) ) { + return; + } + + // push the attributes on to the metamodel class... + for ( Object attribute : managedType.getDeclaredAttributes() ) { + + registerAttribute( metamodelClass, (Attribute) attribute ); + } + if ( IdentifiableType.class.isInstance( managedType ) ) { + final AbstractIdentifiableType entityType = (AbstractIdentifiableType) managedType; + // handle version + if ( entityType.hasDeclaredVersionAttribute() ) { + registerAttribute( metamodelClass, entityType.getDeclaredVersion() ); + } + + // handle id-class mappings specially + if ( !entityType.hasSingleIdAttribute() ) { + final Set> attributes = entityType.getIdClassAttributes(); + if ( attributes != null ) { + for ( SingularAttribute attribute : attributes ) { + registerAttribute( metamodelClass, attribute ); + } + } + } + } + + + } + + private void registerAttribute(Class metamodelClass, Attribute attribute) { + final String name = attribute.getName(); + try { + // there is a shortcoming in the existing Hibernate code in terms of the way MappedSuperclass + // support was bolted on which comes to bear right here when the attribute is an embeddable type + // defined on a MappedSuperclass. We do not have the correct information to determine the + // appropriate attribute declarer in such cases and so the incoming metamodelClass most likely + // does not represent the declarer in such cases. + // + // As a result, in the case of embeddable classes we simply use getField rather than get + // getDeclaredField + final Field field = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED + ? metamodelClass.getField( name ) + : metamodelClass.getDeclaredField( name ); + try { + if ( ! field.isAccessible() ) { + // should be public anyway, but to be sure... + field.setAccessible( true ); + } + field.set( null, attribute ); + } + catch ( IllegalAccessException e ) { + // todo : exception type? + throw new AssertionFailure( + "Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name, + e + ); + } + catch ( IllegalArgumentException e ) { + // most likely a mismatch in the type we are injecting and the defined field; this represents a + // mismatch in how the annotation processor interpretted the attribute and how our metamodel + // and/or annotation binder did. + +// This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator + +// throw new AssertionFailure( +// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name +// + "; expected type : " + attribute.getClass().getName() +// + "; encountered type : " + field.getType().getName() +// ); + LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(), + name, + attribute.getClass().getName(), + field.getType().getName()); + } + } + catch ( NoSuchFieldException e ) { + LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name); +// throw new AssertionFailure( +// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name +// ); + } + } + + +// private void populateStaticMetamodel(EmbeddableTypeImpl embeddable) { +// if ( populationSetting == JpaMetaModelPopulationSetting.DISABLED ) { +// return; +// } +// final Class managedTypeClass = embeddable.getJavaType(); +// final String metamodelClassName = managedTypeClass.getName() + "_"; +// try { +// final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); +// // we found the class; so populate it... +// registerAttributes( metamodelClass, embeddable ); +// } +// catch ( ClassNotFoundException ignore ) { +// // nothing to do... +// } +// +// AbstractManagedType superType = embeddable.getSupertype(); +// if ( superType != null ) { +// populateStaticMetamodel( superType ); +// } +// } + + + /** + * Implementation of AttributeBuilder.Context + */ + class AttributeBuilderContext implements AttributeBuilder.Context { + public AttributeBuilderContext() { + } + + public Type locateEntityTypeByName(String entityName) { + return entityTypeByNameMap.get( entityName ); + } + + @Override + public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) { + embeddableTypeMap.put( embeddableType.getJavaType(), embeddableType ); + } + + public SessionFactoryImplementor getSessionFactory() { + return sessionFactory; + } + + @Override + public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass) { + final String entityName = mappedSuperclassEntityNameMap.get( mappedSuperclass ); + if ( entityName == null ) { + throw new HibernateException( + String.format( + "Could not resolve @MappedSuperclass [%s] to entity name", + mappedSuperclass.getJavaType().getName() + ) + ); + } + final EntityPersister entityPersister = sessionFactory.getEntityPersister( entityName ); + if ( entityPersister == null ) { + throw new HibernateException( + String.format( + "Unable to resolve entity name [%s] to EntityPersister for @MappedSuperclass [%s]", + entityName, + mappedSuperclass.getJavaType().getName() + ) + ); + } + return entityPersister; + } + + @Override + public void handleUnsupportedFeature(UnsupportedFeature feature) { + if ( populationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED ) { + LOG.debug( "Ignoring mapping construct not supported as part of JPA metamodel [" + feature.getMessage() + "]" ); + } + else { + throw new UnsupportedOperationException( feature.getMessage() ); + } + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadata.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadata.java new file mode 100644 index 0000000000..c6e54d6167 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadata.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import javax.persistence.metamodel.PluralAttribute; + +/** + * Attribute metadata contract for a plural attribute. + * @param The owner type + * @param The attribute type (the collection type) + * @param The collection element type + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +interface PluralAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the JPA collection type classification for this attribute + * + * @return The JPA collection type classification + */ + public PluralAttribute.CollectionType getAttributeCollectionType(); + + /** + * Retrieve the value context for the collection's elements. + * + * @return The value context for the collection's elements. + */ + public AttributeTypeDescriptor getElementAttributeTypeDescriptor(); + + /** + * Retrieve the value context for the collection's keys (if a map, null otherwise). + * + * @return The value context for the collection's keys (if a map, null otherwise). + */ + public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadataImpl.java new file mode 100644 index 0000000000..d026e5b691 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/PluralAttributeMetadataImpl.java @@ -0,0 +1,184 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Member; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.TypeVariable; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.PluralAttribute; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; + +/** +* @author Steve Ebersole +*/ +public class PluralAttributeMetadataImpl + extends BaseAttributeMetadata + implements PluralAttributeMetadata { + private final PluralAttribute.CollectionType attributeCollectionType; + private final Attribute.PersistentAttributeType elementPersistentAttributeType; + private final Attribute.PersistentAttributeType keyPersistentAttributeType; + private final Class elementJavaType; + private final Class keyJavaType; + private final AttributeTypeDescriptor elementAttributeTypeDescriptor; + private final AttributeTypeDescriptor keyAttributeTypeDescriptor; + + PluralAttributeMetadataImpl( + PluralAttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType, + Attribute.PersistentAttributeType elementPersistentAttributeType, + Attribute.PersistentAttributeType keyPersistentAttributeType) { + super( attributeBinding, ownerType, member, persistentAttributeType ); + this.attributeCollectionType = AttributeBuilder.determineCollectionType( getJavaType() ); + this.elementPersistentAttributeType = elementPersistentAttributeType; + this.keyPersistentAttributeType = keyPersistentAttributeType; + + ParameterizedType signatureType = AttributeBuilder.getSignatureType( member ); + if ( keyPersistentAttributeType == null ) { + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + keyJavaType = null; + } + else { + keyJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) : + Object.class; //FIXME and honor targetEntity? + } + + this.elementAttributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return getAttributeBinding().getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + public Class getBindableType() { + return elementJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + + // interpret the key, if one + if ( keyPersistentAttributeType != null ) { + this.keyAttributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return ( (IndexedPluralAttributeBinding) getAttributeBinding() ).getPluralAttributeIndexBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + public Class getBindableType() { + return keyJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + } + else { + keyAttributeTypeDescriptor = null; + } + } + + private Class getClassFromGenericArgument(java.lang.reflect.Type type) { + if ( type instanceof Class ) { + return (Class) type; + } + else if ( type instanceof TypeVariable ) { + final java.lang.reflect.Type upperBound = ( ( TypeVariable ) type ).getBounds()[0]; + return getClassFromGenericArgument( upperBound ); + } + else if ( type instanceof ParameterizedType ) { + final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType(); + return getClassFromGenericArgument( rawType ); + } + else { + throw new AssertionFailure( + "Fail to process type argument in a generic declaration. Member : " + getMemberDescription() + + " Type: " + type.getClass() + ); + } + } + + @Override + public PluralAttributeBinding getAttributeBinding() { + return (PluralAttributeBinding) super.getAttributeBinding(); + } + + public AttributeTypeDescriptor getElementAttributeTypeDescriptor() { + return elementAttributeTypeDescriptor; + } + + public PluralAttribute.CollectionType getAttributeCollectionType() { + return attributeCollectionType; + } + + public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor() { + return keyAttributeTypeDescriptor; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadata.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadata.java new file mode 100644 index 0000000000..1fab29eadc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadata.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +/** + * Attribute metadata contract for a non-plural attribute. + * @param The owner type + * @param The attribute type + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface SingularAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the value context for this attribute + * + * @return The attributes value context + */ + public AttributeTypeDescriptor getAttributeTypeDescriptor(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadataImpl.java new file mode 100644 index 0000000000..177d3ce588 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/builder/SingularAttributeMetadataImpl.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.metamodel.internal.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** +* @author Steve Ebersole +*/ +public class SingularAttributeMetadataImpl + extends BaseAttributeMetadata + implements SingularAttributeMetadata { + private final AttributeTypeDescriptor attributeTypeDescriptor; + + public SingularAttributeMetadataImpl( + AttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + super( attributeBinding, ownerType, member, persistentAttributeType ); + attributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return getAttributeMetadata().getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(); + } + + @Override + public Class getBindableType() { + return getAttributeMetadata().getJavaType(); + } + + @Override + public ValueClassification getValueClassification() { + switch ( getPersistentAttributeType() ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + @Override + public AttributeMetadata getAttributeMetadata() { + return SingularAttributeMetadataImpl.this; + } + }; + } + + public AttributeTypeDescriptor getAttributeTypeDescriptor() { + return attributeTypeDescriptor; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractAttribute.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractAttribute.java new file mode 100644 index 0000000000..26212edb0e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractAttribute.java @@ -0,0 +1,142 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.ManagedType; + +import org.hibernate.internal.util.ReflectHelper; + +/** + * Models the commonality of the JPA {@link javax.persistence.metamodel.Attribute} hierarchy. + * + * @author Steve Ebersole + */ +public abstract class AbstractAttribute + implements Attribute, AttributeImplementor, Serializable { + private final String name; + private final Class javaType; + private final AbstractManagedType declaringType; + private transient Member member; + private final PersistentAttributeType persistentAttributeType; + + public AbstractAttribute( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + PersistentAttributeType persistentAttributeType) { + this.name = name; + this.javaType = javaType; + this.declaringType = declaringType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + public ManagedType getDeclaringType() { + return declaringType; + } + + /** + * {@inheritDoc} + */ + public Class getJavaType() { + return javaType; + } + + /** + * {@inheritDoc} + */ + public Member getJavaMember() { + return member; + } + + /** + * {@inheritDoc} + */ + public PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + /** + * Used by JDK serialization... + * + * @param ois The input stream from which we are being read... + * @throws java.io.IOException Indicates a general IO stream exception + * @throws ClassNotFoundException Indicates a class resolution issue + */ + protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + final String memberDeclaringClassName = ( String ) ois.readObject(); + final String memberName = ( String ) ois.readObject(); + final String memberType = ( String ) ois.readObject(); + + final Class memberDeclaringClass = Class.forName( + memberDeclaringClassName, + false, + declaringType.getJavaType().getClassLoader() + ); + try { + this.member = "method".equals( memberType ) + ? memberDeclaringClass.getMethod( memberName, ReflectHelper.NO_PARAM_SIGNATURE ) + : memberDeclaringClass.getField( memberName ); + } + catch ( Exception e ) { + throw new IllegalStateException( + "Unable to locate member [" + memberDeclaringClassName + "#" + + memberName + "]" + ); + } + } + + /** + * Used by JDK serialization... + * + * @param oos The output stream to which we are being written... + * @throws java.io.IOException Indicates a general IO stream exception + */ + protected void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject( getJavaMember().getDeclaringClass().getName() ); + oos.writeObject( getJavaMember().getName() ); + // should only ever be a field or the getter-method... + oos.writeObject( Method.class.isInstance( getJavaMember() ) ? "method" : "field" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractIdentifiableType.java new file mode 100644 index 0000000000..a654b1df17 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractIdentifiableType.java @@ -0,0 +1,318 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +/** + * Defines commonality for the JPA {@link javax.persistence.metamodel.IdentifiableType} types. JPA defines + * identifiable types as entities or mapped-superclasses. Basically things to which an + * identifier can be attached. + *

      + * NOTE : Currently we only really have support for direct entities in the Hibernate metamodel + * as the information for them is consumed into the closest actual entity subclass(es) in the + * internal Hibernate mapping-metamodel. + * + * @author Steve Ebersole + */ +public abstract class AbstractIdentifiableType + extends AbstractManagedType + implements IdentifiableType, Serializable { + + private final boolean hasIdentifierProperty; + private final boolean isVersioned; + + private SingularAttributeImpl id; + private SingularAttributeImpl version; + private Set> idClassAttributes; + + public AbstractIdentifiableType( + Class javaType, + AbstractIdentifiableType superType, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, superType ); + this.hasIdentifierProperty = hasIdentifierProperty; + isVersioned = versioned; + } + + /** + * {@inheritDoc} + */ + public AbstractIdentifiableType getSupertype() { + return ( AbstractIdentifiableType ) super.getSupertype(); + } + + /** + * Indicates if a non-null super type is required to provide the + * identifier attribute(s) if this object does not have a declared + * identifier. + * . + * @return true, if a non-null super type is required to provide + * the identifier attribute(s) if this object does not have a + * declared identifier; false, otherwise. + */ + protected abstract boolean requiresSupertypeForNonDeclaredIdentifier(); + + protected AbstractIdentifiableType requireSupertype() { + if ( getSupertype() == null ) { + throw new IllegalStateException( "No supertype found" ); + } + return getSupertype(); + } + + /** + * {@inheritDoc} + */ + public boolean hasSingleIdAttribute() { + return hasIdentifierProperty; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getId(Class javaType) { + final SingularAttribute id_; + if ( id != null ) { + checkSimpleId(); + id_ = ( SingularAttribute ) id; + if ( javaType != id.getJavaType() ) { + throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() ); + } + } + else { + //yuk yuk bad me + if ( ! requiresSupertypeForNonDeclaredIdentifier()) { + final AbstractIdentifiableType supertype = getSupertype(); + if (supertype != null) { + id_ = supertype.getId( javaType ); + } + else { + id_ = null; + } + } + else { + id_ = requireSupertype().getId( javaType ); + } + } + return id_; + } + + /** + * Centralized check to ensure the id for this hierarchy is a simple one (i.e., does not use + * an id-class). + * + * @see #checkIdClass() + */ + protected void checkSimpleId() { + if ( ! hasIdentifierProperty ) { + throw new IllegalStateException( "This class uses an @IdClass" ); + } + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredId(Class javaType) { + checkDeclaredId(); + checkSimpleId(); + if ( javaType != id.getJavaType() ) { + throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() ); + } + return (SingularAttribute) id; + } + + /** + * Centralized check to ensure the id is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredId() { + if ( id == null ) { + throw new IllegalArgumentException( "The id attribute is not declared on this type" ); + } + } + + /** + * {@inheritDoc} + */ + public Type getIdType() { + if ( id != null ) { + checkSimpleId(); + return id.getType(); + } + else { + return requireSupertype().getIdType(); + } + } + + private boolean hasIdClassAttributesDefined() { + return idClassAttributes != null || + ( getSupertype() != null && getSupertype().hasIdClassAttributesDefined() ); + } + + /** + * {@inheritDoc} + */ + public Set> getIdClassAttributes() { + if ( idClassAttributes != null ) { + checkIdClass(); + } + else { + // Java does not allow casting requireSupertype().getIdClassAttributes() + // to Set> because the + // superclass X is a different Java type from this X + // (i.e, getSupertype().getJavaType() != getJavaType()). + // It will, however, allow a Set> + // to be initialized with requireSupertype().getIdClassAttributes(), + // since getSupertype().getJavaType() is a superclass of getJavaType() + if ( requiresSupertypeForNonDeclaredIdentifier() ) { + idClassAttributes = new HashSet>( requireSupertype().getIdClassAttributes() ); + } + else if ( getSupertype() != null && hasIdClassAttributesDefined() ) { + idClassAttributes = new HashSet>( getSupertype().getIdClassAttributes() ); + } + } + return idClassAttributes; + } + + /** + * Centralized check to ensure the id for this hierarchy uses an id-class. + * + * @see #checkSimpleId() + */ + private void checkIdClass() { + if ( hasIdentifierProperty ) { + throw new IllegalArgumentException( "This class does not use @IdClass" ); + } + } + + /** + * {@inheritDoc} + */ + public boolean hasVersionAttribute() { + return isVersioned; + } + + public boolean hasDeclaredVersionAttribute() { + return isVersioned && version != null; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getVersion(Class javaType) { + if ( ! hasVersionAttribute() ) { + return null; + } + final SingularAttribute version_; + if ( version != null ) { + version_ = ( SingularAttribute ) version; + if ( javaType != version.getJavaType() ) { + throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() ); + } + } + else { + version_ = requireSupertype().getVersion( javaType ); + } + return version_; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredVersion(Class javaType) { + checkDeclaredVersion(); + if ( javaType != version.getJavaType() ) { + throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() ); + } + return ( SingularAttribute ) version; + } + + /** + * For used to retrieve the declared version when populating the static metamodel. + * + * @return The declared + */ + public SingularAttribute getDeclaredVersion() { + checkDeclaredVersion(); + return version; + } + + /** + * Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredVersion() { + if ( version == null || ( getSupertype() != null && getSupertype().hasVersionAttribute() )) { + throw new IllegalArgumentException( "The version attribute is not declared on this type" ); + } + } + + public Builder getBuilder() { + final AbstractManagedType.Builder managedBuilder = super.getBuilder(); + return new Builder() { + public void applyIdAttribute(SingularAttributeImpl idAttribute) { + AbstractIdentifiableType.this.id = idAttribute; + managedBuilder.addAttribute( idAttribute ); + } + + public void applyIdClassAttributes(Set> idClassAttributes) { + for ( SingularAttribute idClassAttribute : idClassAttributes ) { + if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) { + @SuppressWarnings({ "unchecked" }) + SingularAttribute declaredAttribute = ( SingularAttribute ) idClassAttribute; + addAttribute( declaredAttribute ); + } + } + AbstractIdentifiableType.this.idClassAttributes = idClassAttributes; + } + + public void applyVersionAttribute(SingularAttributeImpl versionAttribute) { + AbstractIdentifiableType.this.version = versionAttribute; + managedBuilder.addAttribute( versionAttribute ); + } + + public void addAttribute(Attribute attribute) { + managedBuilder.addAttribute( attribute ); + } + }; + } + + public static interface Builder extends AbstractManagedType.Builder { + public void applyIdAttribute(SingularAttributeImpl idAttribute); + public void applyIdClassAttributes(Set> idClassAttributes); + public void applyVersionAttribute(SingularAttributeImpl versionAttribute); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractManagedType.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractManagedType.java new file mode 100644 index 0000000000..9bad9a1ce5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractManagedType.java @@ -0,0 +1,529 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.annotations.common.AssertionFailure; + +/** + * Defines commonality for the JPA {@link javax.persistence.metamodel.ManagedType} hierarchy of interfaces. + * + * @author Steve Ebersole + */ +public abstract class AbstractManagedType + extends AbstractType + implements ManagedType, Serializable { + + private final AbstractManagedType superType; + + private final Map> declaredAttributes + = new HashMap>(); + private final Map> declaredSingularAttributes + = new HashMap>(); + private final Map> declaredPluralAttributes + = new HashMap>(); + + protected AbstractManagedType(Class javaType, AbstractManagedType superType) { + super( javaType ); + this.superType = superType; + } + + protected AbstractManagedType getSupertype() { + return superType; + } + + private boolean locked = false; + + public Builder getBuilder() { + if ( locked ) { + throw new IllegalStateException( "Type has been locked" ); + } + return new Builder() { + public void addAttribute(Attribute attribute) { + declaredAttributes.put( attribute.getName(), attribute ); + final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType(); + switch ( bindableType ) { + case SINGULAR_ATTRIBUTE : { + declaredSingularAttributes.put( attribute.getName(), (SingularAttribute) attribute ); + break; + } + case PLURAL_ATTRIBUTE : { + declaredPluralAttributes.put(attribute.getName(), (PluralAttribute) attribute ); + break; + } + default : { + throw new AssertionFailure( "unknown bindable type: " + bindableType ); + } + } + } + }; + } + + public void lock() { + locked = true; + } + + public static interface Builder { + public void addAttribute(Attribute attribute); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getAttributes() { + HashSet attributes = new HashSet>( declaredAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredAttributes() { + return new HashSet>( declaredAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Attribute getAttribute(String name) { + Attribute attribute = declaredAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getAttribute( name ); + } + return attribute; + } + + /** + * {@inheritDoc} + */ + public Attribute getDeclaredAttribute(String name) { + final Attribute attr = declaredAttributes.get( name ); + checkNotNull( "Attribute ", attr, name ); + return attr; + } + + private void checkNotNull(String attributeType, Attribute attribute, String name) { + if ( attribute == null ) { + throw new IllegalArgumentException( attributeType + " named " + name + " is not present" ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getSingularAttributes() { + HashSet attributes = new HashSet>( declaredSingularAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getSingularAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredSingularAttributes() { + return new HashSet>( declaredSingularAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + return attribute; + } + + /** + * {@inheritDoc} + */ + public SingularAttribute getDeclaredSingularAttribute(String name) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkNotNull( "SingularAttribute ", attr, name ); + return attr; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name, Class type) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + checkTypeForSingleAttribute( "SingularAttribute ", attribute, name, type ); + return ( SingularAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public SingularAttribute getDeclaredSingularAttribute(String name, Class javaType) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkTypeForSingleAttribute( "SingularAttribute ", attr, name, javaType ); + return ( SingularAttribute ) attr; + } + + private void checkTypeForSingleAttribute( + String attributeType, + SingularAttribute attribute, + String name, + Class javaType) { + if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) { + if ( isPrimitiveVariant( attribute, javaType ) ) { + return; + } + throw new IllegalArgumentException( + attributeType + " named " + name + + ( javaType != null ? " and of type " + javaType.getName() : "" ) + + " is not present" + ); + } + } + + @SuppressWarnings({ "SimplifiableIfStatement" }) + protected boolean isPrimitiveVariant(SingularAttribute attribute, Class javaType) { + if ( attribute == null ) { + return false; + } + Class declaredType = attribute.getBindableJavaType(); + + if ( declaredType.isPrimitive() ) { + return ( Boolean.class.equals( javaType ) && Boolean.TYPE.equals( declaredType ) ) + || ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) ) + || ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) ) + || ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) ) + || ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) ) + || ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) ) + || ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) ) + || ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) ); + } + + if ( javaType.isPrimitive() ) { + return ( Boolean.class.equals( declaredType ) && Boolean.TYPE.equals( javaType ) ) + || ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) ) + || ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) ) + || ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) ) + || ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) ) + || ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) ) + || ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) ) + || ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) ); + } + + return false; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getPluralAttributes() { + HashSet attributes = new HashSet>( declaredPluralAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getPluralAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredPluralAttributes() { + return new HashSet>( declaredPluralAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + private PluralAttribute getPluralAttribute(String name) { + return declaredPluralAttributes.get( name ); + } + + private void basicCollectionCheck(PluralAttribute attribute, String name) { + checkNotNull( "CollectionAttribute", attribute, name ); + if ( ! CollectionAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public CollectionAttribute getDeclaredCollection(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicSetCheck( attribute, name ); + return (SetAttribute) attribute; + } + + private void basicSetCheck(PluralAttribute attribute, String name) { + checkNotNull( "SetAttribute", attribute, name ); + if ( ! SetAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a SetAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public SetAttribute getDeclaredSet(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicSetCheck( attribute, name ); + return ( SetAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicListCheck( attribute, name ); + return (ListAttribute) attribute; + } + + private void basicListCheck(PluralAttribute attribute, String name) { + checkNotNull( "ListAttribute", attribute, name ); + if ( ! ListAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a ListAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + public ListAttribute getDeclaredList(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicListCheck( attribute, name ); + return ( ListAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicMapCheck( attribute, name ); + return (MapAttribute) attribute; + } + + private void basicMapCheck(PluralAttribute attribute, String name) { + checkNotNull( "MapAttribute", attribute, name ); + if ( ! MapAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a MapAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + public MapAttribute getDeclaredMap(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicMapCheck( attribute, name ); + return ( MapAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + public CollectionAttribute getDeclaredCollection(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + private void checkCollectionElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "CollectionAttribute", attribute, name, elementType, PluralAttribute.CollectionType.COLLECTION ); + } + + private void checkTypeForPluralAttributes( + String attributeType, + PluralAttribute attribute, + String name, + Class elementType, + PluralAttribute.CollectionType collectionType) { + if ( attribute == null + || ( elementType != null && !attribute.getBindableJavaType().equals( elementType ) ) + || attribute.getCollectionType() != collectionType ) { + throw new IllegalArgumentException( + attributeType + " named " + name + + ( elementType != null ? " and of element type " + elementType : "" ) + + " is not present" + ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + private void checkSetElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "SetAttribute", attribute, name, elementType, PluralAttribute.CollectionType.SET ); + } + + /** + * {@inheritDoc} + */ + public SetAttribute getDeclaredSet(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + private void checkListElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "ListAttribute", attribute, name, elementType, PluralAttribute.CollectionType.LIST ); + } + + /** + * {@inheritDoc} + */ + public ListAttribute getDeclaredList(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name, Class keyType, Class valueType) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } + + private void checkMapValueType(PluralAttribute attribute, String name, Class valueType) { + checkTypeForPluralAttributes( "MapAttribute", attribute, name, valueType, PluralAttribute.CollectionType.MAP); + } + + private void checkMapKeyType(MapAttribute mapAttribute, String name, Class keyType) { + if ( mapAttribute.getKeyJavaType() != keyType ) { + throw new IllegalArgumentException( "MapAttribute named " + name + " does not support a key of type " + keyType ); + } + } + + public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractType.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractType.java new file mode 100644 index 0000000000..a95ff46481 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AbstractType.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import javax.persistence.metamodel.Type; + +/** + * Defines commonality for the JPA {@link javax.persistence.metamodel.Type} hierarchy of interfaces. + * + * @author Steve Ebersole + */ +public abstract class AbstractType implements Type, Serializable { + private final Class javaType; + + public AbstractType(Class javaType) { + this.javaType = javaType; + } + + public Class getJavaType() { + return javaType; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeFactory.java new file mode 100644 index 0000000000..da72385208 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeFactory.java @@ -0,0 +1,1016 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.TypeVariable; +import java.util.Iterator; +import javax.persistence.ManyToMany; +import javax.persistence.OneToOne; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; + +import org.jboss.logging.Logger; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.mapping.Array; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.Component; +import org.hibernate.mapping.Map; +import org.hibernate.mapping.OneToMany; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.PrimitiveArray; +import org.hibernate.mapping.Property; +import org.hibernate.mapping.Value; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.type.ComponentType; +import org.hibernate.type.EntityType; + +/** + * A factory for building {@link javax.persistence.metamodel.Attribute} instances. Exposes 3 main services for building

        + *
      1. {@link #buildAttribute normal attributes}
      2. + *
      3. {@link #buildIdAttribute id attributes}
      4. + *
      5. {@link #buildVersionAttribute version attributes}
      6. + *
          + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class AttributeFactory { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, + AttributeFactory.class.getName()); + + private final MetadataContext context; + + public AttributeFactory(MetadataContext context) { + this.context = context; + } + + /** + * Build a normal attribute. + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param property The Hibernate property descriptor for the attribute + * @param The type of the owner + * @param The attribute type + * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs) + */ + @SuppressWarnings({ "unchecked" }) + public AttributeImplementor buildAttribute(AbstractManagedType ownerType, Property property) { + if ( property.isSynthetic() ) { + // hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel. + LOG.tracef( + "Skipping synthetic property %s(%s)", + ownerType.getJavaType().getName(), + property.getName() + ); + return null; + } + LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]"); + final AttributeContext attributeContext = wrap( ownerType, property ); + final AttributeMetadata attributeMetadata = + determineAttributeMetadata( attributeContext, NORMAL_MEMBER_RESOLVER ); + if (attributeMetadata == null) { + return null; + } + if (attributeMetadata.isPlural()) { + return buildPluralAttribute((PluralAttributeMetadata)attributeMetadata); + } + final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata)attributeMetadata; + final Type metaModelType = getMetaModelType(singularAttributeMetadata.getValueContext()); + return new SingularAttributeImpl( + attributeMetadata.getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + false, + false, + property.isOptional(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + private AttributeContext wrap(final AbstractManagedType ownerType, final Property property) { + return new AttributeContext() { + public AbstractManagedType getOwnerType() { + return ownerType; + } + + public Property getPropertyMapping() { + return property; + } + }; + } + + /** + * Build the identifier attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param property The Hibernate property descriptor for the identifier attribute + * @param The type of the owner + * @param The attribute type + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildIdAttribute(AbstractIdentifiableType ownerType, Property property) { + LOG.trace("Building identifier attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]"); + final AttributeContext attributeContext = wrap( ownerType, property ); + final SingularAttributeMetadata attributeMetadata = + (SingularAttributeMetadata) determineAttributeMetadata( attributeContext, IDENTIFIER_MEMBER_RESOLVER ); + final Type metaModelType = getMetaModelType( attributeMetadata.getValueContext() ); + return new SingularAttributeImpl.Identifier( + property.getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + /** + * Build the version attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param property The Hibernate property descriptor for the version attribute + * @param The type of the owner + * @param The attribute type + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildVersionAttribute(AbstractIdentifiableType ownerType, Property property) { + LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]"); + final AttributeContext attributeContext = wrap( ownerType, property ); + final SingularAttributeMetadata attributeMetadata = + (SingularAttributeMetadata) determineAttributeMetadata( attributeContext, VERSION_MEMBER_RESOLVER ); + final Type metaModelType = getMetaModelType( attributeMetadata.getValueContext() ); + return new SingularAttributeImpl.Version( + property.getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + @SuppressWarnings( "unchecked" ) + private AttributeImplementor buildPluralAttribute(PluralAttributeMetadata attributeMetadata) { + final Type elementType = getMetaModelType( attributeMetadata.getElementValueContext() ); + if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { + final Type keyType = getMetaModelType( attributeMetadata.getMapKeyValueContext() ); + return PluralAttributeImpl.create( attributeMetadata.getOwnerType(), elementType, attributeMetadata.getJavaType(), keyType ) + .member( attributeMetadata.getMember() ) + .property( attributeMetadata.getPropertyMapping() ) + .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) + .build(); + } + return PluralAttributeImpl.create(attributeMetadata.getOwnerType(), elementType, attributeMetadata.getJavaType(), null).member(attributeMetadata.getMember()).property(attributeMetadata.getPropertyMapping()).persistentAttributeType(attributeMetadata.getPersistentAttributeType()).build(); + } + + @SuppressWarnings( "unchecked" ) + private Type getMetaModelType(ValueContext typeContext) { + switch ( typeContext.getValueClassification() ) { + case BASIC: { + return new BasicTypeImpl( + typeContext.getBindableType(), + Type.PersistenceType.BASIC + ); + } + case ENTITY: { + final EntityType type = (EntityType) typeContext.getValue().getType(); + return (Type) context.locateEntityType( type.getAssociatedEntityName() ); + } + case EMBEDDABLE: { + final Component component = (Component) typeContext.getValue(); + final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl( + typeContext.getBindableType(), + typeContext.getAttributeMetadata().getOwnerType(), + (ComponentType) typeContext.getValue().getType() + ); + context.registerEmbeddedableType( embeddableType ); + final Iterator subProperties = component.getPropertyIterator(); + while ( subProperties.hasNext() ) { + final Property property = subProperties.next(); + final AttributeImplementor attribute = buildAttribute( embeddableType, property ); + if ( attribute != null ) { + embeddableType.getBuilder().addAttribute( attribute ); + } + } + embeddableType.lock(); + return embeddableType; + } + default: { + throw new AssertionFailure( "Unknown type : " + typeContext.getValueClassification() ); + } + } + } + + private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType ownerType) { + final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); + if ( persistenceType == Type.PersistenceType.ENTITY) { + return context.getSessionFactory() + .getEntityPersister( ownerType.getJavaType().getName() ) + .getEntityMetamodel(); + } + else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) { + PersistentClass persistentClass = + context.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl) ownerType ); + return context.getSessionFactory() + .getEntityPersister( persistentClass.getClassName() ) + .getEntityMetamodel(); + } + else { + throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType ); + } + } + + /** + * A contract for defining the meta information about a {@link org.hibernate.mapping.Value} + */ + private interface ValueContext { + /** + * Enum of the simplified types a value might be. These relate more to the Hibernate classification + * then the JPA classification + */ + enum ValueClassification { + EMBEDDABLE, + ENTITY, + BASIC + } + + /** + * Retrieve the value itself + * + * @return The value + */ + public Value getValue(); + + public Class getBindableType(); + + /** + * Retrieve the simplified value classification + * + * @return The value type + */ + public ValueClassification getValueClassification(); + + /** + * Retrieve the metadata about the attribute from which this value comes + * + * @return The "containing" attribute metadata. + */ + public AttributeMetadata getAttributeMetadata(); + } + + /** + * Basic contract for describing an attribute. The "description" is partially in terms + * of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType}), partially in + * terms of Hibernate ({@link #getPropertyMapping}) and partially just in terms of the java + * model itself ({@link #getName}, {@link #getMember} and {@link #getJavaType}). + * + * @param The attribute owner type + * @param The attribute type. + */ + private interface AttributeMetadata { + /** + * Retrieve the name of the attribute + * + * @return The attribute name + */ + public String getName(); + + /** + * Retrieve the member defining the attribute + * + * @return The attribute member + */ + public Member getMember(); + + /** + * Retrieve the attribute java type. + * + * @return The java type of the attribute. + */ + public Class getJavaType(); + + /** + * Get the JPA attribute type classification for this attribute. + * + * @return The JPA attribute type classification + */ + public Attribute.PersistentAttributeType getPersistentAttributeType(); + + /** + * Retrieve the attribute owner's metamodel information + * + * @return The metamodel information for the attribute owner + */ + public AbstractManagedType getOwnerType(); + + /** + * Retrieve the Hibernate property mapping related to this attribute. + * + * @return The Hibernate property mapping + */ + public Property getPropertyMapping(); + + /** + * Is the attribute plural (a collection)? + * + * @return True if it is plural, false otherwise. + */ + public boolean isPlural(); + } + + /** + * Attribute metadata contract for a non-plural attribute. + * @param The owner type + * @param The attribute type + */ + private interface SingularAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the value context for this attribute + * + * @return The attributes value context + */ + public ValueContext getValueContext(); + } + + /** + * Attribute metadata contract for a plural attribute. + * @param The owner type + * @param The attribute type (the collection type) + * @param The collection element type + */ + private interface PluralAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the JPA collection type classification for this attribute + * + * @return The JPA collection type classification + */ + public PluralAttribute.CollectionType getAttributeCollectionType(); + + /** + * Retrieve the value context for the collection's elements. + * + * @return The value context for the collection's elements. + */ + public ValueContext getElementValueContext(); + + /** + * Retrieve the value context for the collection's keys (if a map, null otherwise). + * + * @return The value context for the collection's keys (if a map, null otherwise). + */ + public ValueContext getMapKeyValueContext(); + } + + /** + * Bundle's a Hibernate property mapping together with the JPA metamodel information + * of the attribute owner. + * + * @param The owner type. + */ + private interface AttributeContext { + /** + * Retrieve the attribute owner. + * + * @return The owner. + */ + public AbstractManagedType getOwnerType(); + + /** + * Retrieve the Hibernate property mapping. + * + * @return The Hibvernate property mapping. + */ + public Property getPropertyMapping(); + } + + /** + * Contract for how we resolve the {@link java.lang.reflect.Member} for a give attribute context. + */ + private interface MemberResolver { + public Member resolveMember(AttributeContext attributeContext); + } + + /** + * Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata + * against the known Hibernate metadata and build a descriptor for the attribute. + * + * @param attributeContext The attribute to be described + * @param memberResolver Strategy for how to resolve the member defining the attribute. + * @param The owner type + * @param The attribute type + * + * @return The attribute description + */ + @SuppressWarnings({ "unchecked" }) + private AttributeMetadata determineAttributeMetadata( + AttributeContext attributeContext, + MemberResolver memberResolver) { + LOG.trace("Starting attribute metadata determination [" + attributeContext.getPropertyMapping().getName() + "]"); + final Member member = memberResolver.resolveMember( attributeContext ); + LOG.trace(" Determined member [" + member + "]"); + if ( member == null ) { + return null; + } + + final Value value = attributeContext.getPropertyMapping().getValue(); + final org.hibernate.type.Type type = value.getType(); + LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]"); + + if ( type.isAnyType() ) { + context.handleAnyMapping(); + return null; + } + else if ( type.isAssociationType() ) { + // collection or entity + if ( type.isEntityType() ) { + // entity + return new SingularAttributeMetadataImpl( + attributeContext.getPropertyMapping(), + attributeContext.getOwnerType(), + member, + determineSingularAssociationAttributeType( member ) + ); + } + + // collection + if (value instanceof Collection) { + if ( Array.class.isInstance( value ) + || PrimitiveArray.class.isInstance( value ) ) { + context.handleArrayMapping(); + return null; + } + + final Collection collValue = (Collection)value; + final Value elementValue = collValue.getElement(); + final org.hibernate.type.Type elementType = elementValue.getType(); + + // First, determine the type of the elements and use that to help determine the + // collection type) + final Attribute.PersistentAttributeType elementPersistentAttributeType; + final Attribute.PersistentAttributeType persistentAttributeType; + if ( elementType.isAnyType() ) { + context.handleAnyMapping(); + return null; + } + final boolean isManyToMany = isManyToMany(member); + if (elementValue instanceof Component) { + elementPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED; + persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION; + } else if (elementType.isAssociationType()) { + elementPersistentAttributeType = isManyToMany ? Attribute.PersistentAttributeType.MANY_TO_MANY : Attribute.PersistentAttributeType.ONE_TO_MANY; + persistentAttributeType = elementPersistentAttributeType; + } else { + elementPersistentAttributeType = Attribute.PersistentAttributeType.BASIC; + persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION; + } + + final Attribute.PersistentAttributeType keyPersistentAttributeType; + + // Finally, we determine the type of the map key (if needed) + if (value instanceof Map) { + final Value keyValue = ((Map)value).getIndex(); + final org.hibernate.type.Type keyType = keyValue.getType(); + + if ( keyType.isAnyType() ) { + context.handleAnyMapping(); + return null; + } + if (keyValue instanceof Component) { + keyPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED; + } + else if (keyType.isAssociationType()) { + keyPersistentAttributeType = Attribute.PersistentAttributeType.MANY_TO_ONE; + } + else { + keyPersistentAttributeType = Attribute.PersistentAttributeType.BASIC; + } + } + else { + keyPersistentAttributeType = null; + } + return new PluralAttributeMetadataImpl( + attributeContext.getPropertyMapping(), + attributeContext.getOwnerType(), + member, + persistentAttributeType, + elementPersistentAttributeType, + keyPersistentAttributeType + ); + } + else if (value instanceof OneToMany) { + // TODO : is this even possible??? Really OneToMany should be describing the + // element value within a o.h.mapping.Collection (see logic branch above) + throw new IllegalArgumentException("HUH???"); +// final boolean isManyToMany = isManyToMany( member ); +// //one to many with FK => entity +// return new PluralAttributeMetadataImpl( +// attributeContext.getPropertyMapping(), +// attributeContext.getOwnerType(), +// member, +// isManyToMany +// ? Attribute.PersistentAttributeType.MANY_TO_MANY +// : Attribute.PersistentAttributeType.ONE_TO_MANY +// value, +// AttributeContext.TypeStatus.ENTITY, +// Attribute.PersistentAttributeType.ONE_TO_MANY, +// null, null, null +// ); + } + } + else if ( attributeContext.getPropertyMapping().isComposite() ) { + // component + return new SingularAttributeMetadataImpl( + attributeContext.getPropertyMapping(), + attributeContext.getOwnerType(), + member, + Attribute.PersistentAttributeType.EMBEDDED + ); + } + else { + // basic type + return new SingularAttributeMetadataImpl( + attributeContext.getPropertyMapping(), + attributeContext.getOwnerType(), + member, + Attribute.PersistentAttributeType.BASIC + ); + } + throw new UnsupportedOperationException( "oops, we are missing something: " + attributeContext.getPropertyMapping() ); + } + + public static Attribute.PersistentAttributeType determineSingularAssociationAttributeType(Member member) { + if ( Field.class.isInstance( member ) ) { + return ( (Field) member ).getAnnotation( OneToOne.class ) != null + ? Attribute.PersistentAttributeType.ONE_TO_ONE + : Attribute.PersistentAttributeType.MANY_TO_ONE; + } + else { + return ( (Method) member ).getAnnotation( OneToOne.class ) != null + ? Attribute.PersistentAttributeType.ONE_TO_ONE + : Attribute.PersistentAttributeType.MANY_TO_ONE; + } + } + + private abstract class BaseAttributeMetadata implements AttributeMetadata { + private final Property propertyMapping; + private final AbstractManagedType ownerType; + private final Member member; + private final Class javaType; + private final Attribute.PersistentAttributeType persistentAttributeType; + + @SuppressWarnings({ "unchecked" }) + protected BaseAttributeMetadata( + Property propertyMapping, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + this.propertyMapping = propertyMapping; + this.ownerType = ownerType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + final Class declaredType; + // we can support method or field members here. Is there really any other valid type? + if ( Field.class.isInstance( member ) ) { + declaredType = ( (Field) member ).getType(); + } + else if ( Method.class.isInstance( member ) ) { + declaredType = ( (Method) member ).getReturnType(); + } + else { + throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" ); + } + this.javaType = accountForPrimitiveTypes( declaredType ); + } + + public String getName() { + return propertyMapping.getName(); + } + + public Member getMember() { + return member; + } + + public String getMemberDescription() { + return determineMemberDescription( getMember() ); + } + + public String determineMemberDescription(Member member) { + return member.getDeclaringClass().getName() + '#' + member.getName(); + } + + public Class getJavaType() { + return javaType; + } + + public Attribute.PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + public AbstractManagedType getOwnerType() { + return ownerType; + } + + public boolean isPlural() { + return propertyMapping.getType().isCollectionType(); + } + + public Property getPropertyMapping() { + return propertyMapping; + } + } + + @SuppressWarnings({ "unchecked" }) + protected Class accountForPrimitiveTypes(Class declaredType) { +// if ( !declaredType.isPrimitive() ) { +// return declaredType; +// } +// +// if ( Boolean.TYPE.equals( declaredType ) ) { +// return (Class) Boolean.class; +// } +// if ( Character.TYPE.equals( declaredType ) ) { +// return (Class) Character.class; +// } +// if( Byte.TYPE.equals( declaredType ) ) { +// return (Class) Byte.class; +// } +// if ( Short.TYPE.equals( declaredType ) ) { +// return (Class) Short.class; +// } +// if ( Integer.TYPE.equals( declaredType ) ) { +// return (Class) Integer.class; +// } +// if ( Long.TYPE.equals( declaredType ) ) { +// return (Class) Long.class; +// } +// if ( Float.TYPE.equals( declaredType ) ) { +// return (Class) Float.class; +// } +// if ( Double.TYPE.equals( declaredType ) ) { +// return (Class) Double.class; +// } +// +// throw new IllegalArgumentException( "Unexpected type [" + declaredType + "]" ); + // if the field is defined as int, return int not Integer... + return declaredType; + } + + private class SingularAttributeMetadataImpl + extends BaseAttributeMetadata + implements SingularAttributeMetadata { + private final ValueContext valueContext; + + private SingularAttributeMetadataImpl( + Property propertyMapping, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + super( propertyMapping, ownerType, member, persistentAttributeType ); + valueContext = new ValueContext() { + public Value getValue() { + return getPropertyMapping().getValue(); + } + + public Class getBindableType() { + return getAttributeMetadata().getJavaType(); + } + + public ValueClassification getValueClassification() { + switch ( getPersistentAttributeType() ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return SingularAttributeMetadataImpl.this; + } + }; + } + + public ValueContext getValueContext() { + return valueContext; + } + } + + private class PluralAttributeMetadataImpl + extends BaseAttributeMetadata + implements PluralAttributeMetadata { + private final PluralAttribute.CollectionType attributeCollectionType; + private final Attribute.PersistentAttributeType elementPersistentAttributeType; + private final Attribute.PersistentAttributeType keyPersistentAttributeType; + private final Class elementJavaType; + private final Class keyJavaType; + private final ValueContext elementValueContext; + private final ValueContext keyValueContext; + + private PluralAttributeMetadataImpl( + Property propertyMapping, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType, + Attribute.PersistentAttributeType elementPersistentAttributeType, + Attribute.PersistentAttributeType keyPersistentAttributeType) { + super( propertyMapping, ownerType, member, persistentAttributeType ); + this.attributeCollectionType = determineCollectionType( getJavaType() ); + this.elementPersistentAttributeType = elementPersistentAttributeType; + this.keyPersistentAttributeType = keyPersistentAttributeType; + + ParameterizedType signatureType = getSignatureType( member ); + if ( keyPersistentAttributeType == null ) { + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + keyJavaType = null; + } + else { + keyJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) : + Object.class; //FIXME and honor targetEntity? + } + + this.elementValueContext = new ValueContext() { + public Value getValue() { + return ( (Collection) getPropertyMapping().getValue() ).getElement(); + } + + public Class getBindableType() { + return elementJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + + // interpret the key, if one + if ( keyPersistentAttributeType != null ) { + this.keyValueContext = new ValueContext() { + public Value getValue() { + return ( (Map) getPropertyMapping().getValue() ).getIndex(); + } + + public Class getBindableType() { + return keyJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + } + else { + keyValueContext = null; + } + } + + private Class getClassFromGenericArgument(java.lang.reflect.Type type) { + if ( type instanceof Class ) { + return (Class) type; + } + else if ( type instanceof TypeVariable ) { + final java.lang.reflect.Type upperBound = ( ( TypeVariable ) type ).getBounds()[0]; + return getClassFromGenericArgument( upperBound ); + } + else if ( type instanceof ParameterizedType ) { + final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType(); + return getClassFromGenericArgument( rawType ); + } + else { + throw new AssertionFailure( + "Fail to process type argument in a generic declaration. Member : " + getMemberDescription() + + " Type: " + type.getClass() + ); + } + } + + public ValueContext getElementValueContext() { + return elementValueContext; + } + + public PluralAttribute.CollectionType getAttributeCollectionType() { + return attributeCollectionType; + } + + public ValueContext getMapKeyValueContext() { + return keyValueContext; + } + } + + public static ParameterizedType getSignatureType(Member member) { + final java.lang.reflect.Type type = Field.class.isInstance( member ) + ? ( ( Field ) member ).getGenericType() + : ( ( Method ) member ).getGenericReturnType(); + //this is a raw type + if ( type instanceof Class ) return null; + return (ParameterizedType) type; + } + + public static PluralAttribute.CollectionType determineCollectionType(Class javaType) { + if ( java.util.List.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.LIST; + } + else if ( java.util.Set.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.SET; + } + else if ( java.util.Map.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.MAP; + } + else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.COLLECTION; + } + else { + throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" ); + } + } + + public static boolean isManyToMany(Member member) { + return Field.class.isInstance( member ) + ? ( (Field) member ).getAnnotation( ManyToMany.class ) != null + : ( (Method) member ).getAnnotation( ManyToMany.class ) != null; + } + + private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AttributeContext attributeContext) { + final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl ) attributeContext.getOwnerType(); + final String attributeName = attributeContext.getPropertyMapping().getName(); + return embeddableType.getHibernateType() + .getComponentTuplizer() + .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + + private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AttributeContext attributeContext) { + final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType(); + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( entityMetamodel == null ) { + // this happens with badly written custom persisters, like the ones in our test suite :) + return null; + } + if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) { + throw new IllegalArgumentException( "expecting IdClass mapping" ); + } + org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType(); + if ( ! ComponentType.class.isInstance( type ) ) { + throw new IllegalArgumentException( "expecting IdClass mapping" ); + } + + final ComponentType componentType = (ComponentType) type; + final String attributeName = attributeContext.getPropertyMapping().getName(); + return componentType.getComponentTuplizer() + .getGetter( componentType.getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + /** + * A {@link java.lang.reflect.Member} resolver for normal attributes. + */ + private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AttributeContext attributeContext) { + final AbstractManagedType ownerType = attributeContext.getOwnerType(); + final Property property = attributeContext.getPropertyMapping(); + final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); + if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) { + return EMBEDDED_MEMBER_RESOLVER.resolveMember( attributeContext ); + } + else if ( Type.PersistenceType.ENTITY == persistenceType + || Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) { + final IdentifiableType identifiableType = (IdentifiableType) ownerType; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( entityMetamodel == null ) { + // this happens with badly written custom persisters, like the ones in our test suite :) + return null; + } + final String propertyName = property.getName(); + final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName ); + if ( index == null ) { + // just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); + } + else { + return entityMetamodel.getTuplizer() + .getGetter( index ) + .getMember(); + } + } + else { + throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType ); + } + } + }; + + private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AttributeContext attributeContext) { + final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType(); + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( entityMetamodel == null ) { + // this happens with badly written custom persisters, like the ones in our test suite :) + return null; + } + if ( ! attributeContext.getPropertyMapping().getName() + .equals( entityMetamodel.getIdentifierProperty().getName() ) ) { + // this *should* indicate processing part of an IdClass... + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); + } + return entityMetamodel.getTuplizer().getIdentifierGetter().getMember(); + } + }; + + private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AttributeContext attributeContext) { + final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType(); + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( entityMetamodel == null ) { + // this happens with badly written custom persisters, like the ones in our test suite :) + return null; + } + final String versionPropertyName = attributeContext.getPropertyMapping().getName(); + if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) { + // this should never happen, but to be safe... + throw new IllegalArgumentException( "Given property did not match declared version property" ); + } + return entityMetamodel.getTuplizer().getVersionGetter().getMember(); + } + }; +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeImplementor.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeImplementor.java new file mode 100644 index 0000000000..0feb57e302 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/AttributeImplementor.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; +import javax.persistence.metamodel.Attribute; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public interface AttributeImplementor extends Attribute { +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/BasicTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/BasicTypeImpl.java new file mode 100644 index 0000000000..2b0db87b96 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/BasicTypeImpl.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import javax.persistence.metamodel.BasicType; + +/** + * @author Emmanuel Bernard + */ +public class BasicTypeImpl implements BasicType, Serializable { + private final Class clazz; + private PersistenceType persistenceType; + + public PersistenceType getPersistenceType() { + return persistenceType; + } + + public Class getJavaType() { + return clazz; + } + + public BasicTypeImpl(Class clazz, PersistenceType persistenceType) { + this.clazz = clazz; + this.persistenceType = persistenceType; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EmbeddableTypeImpl.java new file mode 100644 index 0000000000..19a9f2e4a0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EmbeddableTypeImpl.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import javax.persistence.metamodel.EmbeddableType; + +import org.hibernate.type.ComponentType; + +/** + * @author Emmanuel Bernard + */ +public class EmbeddableTypeImpl + extends AbstractManagedType + implements EmbeddableType, Serializable { + + private final AbstractManagedType parent; + private final ComponentType hibernateType; + + public EmbeddableTypeImpl(Class javaType, AbstractManagedType parent, ComponentType hibernateType) { + super( javaType, null ); + this.parent = parent; + this.hibernateType = hibernateType; + } + + public PersistenceType getPersistenceType() { + return PersistenceType.EMBEDDABLE; + } + + public AbstractManagedType getParent() { + return parent; + } + + public ComponentType getHibernateType() { + return hibernateType; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EntityTypeImpl.java new file mode 100644 index 0000000000..bde13319d9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/EntityTypeImpl.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import javax.persistence.metamodel.EntityType; + +/** + * Defines the Hibernate implementation of the JPA {@link javax.persistence.metamodel.EntityType} contract. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class EntityTypeImpl + extends AbstractIdentifiableType + implements EntityType, Serializable { + private final String jpaEntityName; + + public EntityTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + String jpaEntityName, + boolean hasIdentifierProperty, + boolean isVersioned) { + super( javaType, superType, hasIdentifierProperty, isVersioned ); + this.jpaEntityName = jpaEntityName; + } + + public String getName() { + return jpaEntityName; + } + + public BindableType getBindableType() { + return BindableType.ENTITY_TYPE; + } + + public Class getBindableJavaType() { + return getJavaType(); + } + + public PersistenceType getPersistenceType() { + return PersistenceType.ENTITY; + } + + @Override + protected boolean requiresSupertypeForNonDeclaredIdentifier() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MappedSuperclassTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MappedSuperclassTypeImpl.java new file mode 100644 index 0000000000..3f5aca31f1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MappedSuperclassTypeImpl.java @@ -0,0 +1,24 @@ +package org.hibernate.jpa.metamodel.internal.legacy; +import javax.persistence.metamodel.MappedSuperclassType; + +/** + * @author Emmanuel Bernard + */ +public class MappedSuperclassTypeImpl extends AbstractIdentifiableType implements MappedSuperclassType { + public MappedSuperclassTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, superType, hasIdentifierProperty, versioned ); + } + + public PersistenceType getPersistenceType() { + return PersistenceType.MAPPED_SUPERCLASS; + } + + @Override + protected boolean requiresSupertypeForNonDeclaredIdentifier() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetadataContext.java new file mode 100644 index 0000000000..3ee0687a66 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetadataContext.java @@ -0,0 +1,510 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.MappedSuperclassType; +import javax.persistence.metamodel.SingularAttribute; + +import org.jboss.logging.Logger; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.mapping.Component; +import org.hibernate.mapping.KeyValue; +import org.hibernate.mapping.MappedSuperclass; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; + +/** + * Defines a context for storing information during the building of the {@link MetamodelImpl}. + *

          + * This contextual information includes data needing to be processed in a second pass as well as + * cross-references into the built metamodel classes. + *

          + * At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeMap} + * results, which represent all the registered {@linkplain #registerEntityType entities} and + * {@linkplain #registerEmbeddedableType embeddables} respectively. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +class MetadataContext { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, + MetadataContext.class.getName()); + + private final SessionFactoryImplementor sessionFactory; + private final boolean ignoreUnsupported; + private final AttributeFactory attributeFactory = new AttributeFactory( this ); + + private Map,EntityTypeImpl> entityTypes + = new HashMap, EntityTypeImpl>(); + private Map> entityTypesByEntityName + = new HashMap>(); + private Map> entityTypesByPersistentClass + = new HashMap>(); + private Map, EmbeddableTypeImpl> embeddables + = new HashMap, EmbeddableTypeImpl>(); + private Map> mappedSuperclassByMappedSuperclassMapping + = new HashMap>(); + //this list contains MappedSuperclass and EntityTypes ordered by superclass first + private List orderedMappings = new ArrayList(); + /** + * Stack of PersistentClass being process. Last in the list is the highest in the stack. + * + */ + private List stackOfPersistentClassesBeingProcessed + = new ArrayList(); + private Map, PersistentClass> mappedSuperClassTypeToPersistentClass + = new HashMap, PersistentClass>(); + + public MetadataContext(SessionFactoryImplementor sessionFactory, boolean ignoreUnsupported) { + this.sessionFactory = sessionFactory; + this.ignoreUnsupported = ignoreUnsupported; + } + + /*package*/ SessionFactoryImplementor getSessionFactory() { + return sessionFactory; + } + + /*package*/ boolean isIgnoreUnsupported() { + return ignoreUnsupported; + } + + /** + * Retrieves the {@linkplain Class java type} to {@link EntityTypeImpl} map. + * + * @return The {@linkplain Class java type} to {@link EntityTypeImpl} map. + */ + public Map, EntityTypeImpl> getEntityTypeMap() { + return Collections.unmodifiableMap( entityTypes ); + } + + public Map, EmbeddableTypeImpl> getEmbeddableTypeMap() { + return Collections.unmodifiableMap( embeddables ); + } + + public Map,MappedSuperclassType> getMappedSuperclassTypeMap() { + // we need to actually build this map... + final Map,MappedSuperclassType> mappedSuperClassTypeMap = CollectionHelper.mapOfSize( + mappedSuperclassByMappedSuperclassMapping.size() + ); + + for ( MappedSuperclassTypeImpl mappedSuperclassType : mappedSuperclassByMappedSuperclassMapping.values() ) { + mappedSuperClassTypeMap.put( + mappedSuperclassType.getJavaType(), + mappedSuperclassType + ); + } + + return mappedSuperClassTypeMap; + } + + /*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl entityType) { + entityTypes.put( entityType.getBindableJavaType(), entityType ); + entityTypesByEntityName.put( persistentClass.getEntityName(), entityType ); + entityTypesByPersistentClass.put( persistentClass, entityType ); + orderedMappings.add( persistentClass ); + } + + /*package*/ void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) { + embeddables.put( embeddableType.getJavaType(), embeddableType ); + } + + /*package*/ void registerMappedSuperclassType(MappedSuperclass mappedSuperclass, + MappedSuperclassTypeImpl mappedSuperclassType) { + mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType ); + orderedMappings.add( mappedSuperclass ); + mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() ); + } + + /** + * Given a Hibernate {@link org.hibernate.mapping.PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType} + * implementation. May retur null if the given {@link org.hibernate.mapping.PersistentClass} has not yet been processed. + * + * @param persistentClass The Hibernate (config time) metamodel instance representing an entity. + * @return Tne corresponding JPA {@link org.hibernate.type.EntityType}, or null if not yet processed. + */ + public EntityTypeImpl locateEntityType(PersistentClass persistentClass) { + return entityTypesByPersistentClass.get( persistentClass ); + } + + /** + * Given a Java {@link Class}, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May + * return null which could means that no such mapping exists at least at this time. + * + * @param javaType The java class. + * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. + */ + public EntityTypeImpl locateEntityType(Class javaType) { + return entityTypes.get( javaType ); + } + + /** + * Given an entity-name, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May + * return null which could means that no such mapping exists at least at this time. + * + * @param entityName The entity-name. + * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. + */ + public EntityTypeImpl locateEntityType(String entityName) { + return entityTypesByEntityName.get( entityName ); + } + + @SuppressWarnings({ "unchecked" }) + public void wrapUp() { + LOG.trace("Wrapping up metadata context..."); + //we need to process types from superclasses to subclasses + for (Object mapping : orderedMappings) { + if ( PersistentClass.class.isAssignableFrom( mapping.getClass() ) ) { + @SuppressWarnings( "unchecked" ) + final PersistentClass safeMapping = (PersistentClass) mapping; + LOG.trace("Starting entity [" + safeMapping.getEntityName() + "]"); + try { + final EntityTypeImpl jpa2Mapping = entityTypesByPersistentClass.get( safeMapping ); + if ( ! safeMapping.getEntityName().equals( jpa2Mapping.getJavaType().getName() ) ) { + // skip it + continue; + } + if ( sessionFactory.getEntityPersister( safeMapping.getEntityName() ).getEntityMetamodel() == null ) { + // skip it + continue; + } + applyIdMetadata( safeMapping, jpa2Mapping ); + applyVersionAttribute( safeMapping, jpa2Mapping ); + Iterator properties = safeMapping.getDeclaredPropertyIterator(); + while ( properties.hasNext() ) { + final Property property = properties.next(); + if ( property.getValue() == safeMapping.getIdentifierMapper() ) { + // property represents special handling for id-class mappings but we have already + // accounted for the embedded property mappings in #applyIdMetadata && + // #buildIdClassAttributes + continue; + } + if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) { + // skip the version property, it was already handled previously. + continue; + } + final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); + if ( attribute != null ) { + jpa2Mapping.getBuilder().addAttribute( attribute ); + } + } + jpa2Mapping.lock(); + populateStaticMetamodel( jpa2Mapping ); + } + finally { + LOG.trace("Completed entity [" + safeMapping.getEntityName() + "]"); + } + } + else if ( MappedSuperclass.class.isAssignableFrom( mapping.getClass() ) ) { + @SuppressWarnings( "unchecked" ) + final MappedSuperclass safeMapping = (MappedSuperclass) mapping; + LOG.trace("Starting mapped superclass [" + safeMapping.getMappedClass().getName() + "]"); + try { + final MappedSuperclassTypeImpl jpa2Mapping = mappedSuperclassByMappedSuperclassMapping.get( + safeMapping + ); + applyIdMetadata( safeMapping, jpa2Mapping ); + applyVersionAttribute( safeMapping, jpa2Mapping ); + Iterator properties = safeMapping.getDeclaredPropertyIterator(); + while ( properties.hasNext() ) { + final Property property = properties.next(); + if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) { + // skip the version property, it was already handled previously. + continue; + } + final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); + if ( attribute != null ) { + jpa2Mapping.getBuilder().addAttribute( attribute ); + } + } + jpa2Mapping.lock(); + populateStaticMetamodel( jpa2Mapping ); + } + finally { + LOG.trace("Completed mapped superclass [" + safeMapping.getMappedClass().getName() + "]"); + } + } + else { + throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() ); + } + } + + for ( EmbeddableTypeImpl embeddable : embeddables.values() ) { + populateStaticMetamodel( embeddable ); + } + } + + + private void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { + if ( persistentClass.hasIdentifierProperty() ) { + final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); + if (declaredIdentifierProperty != null) { + jpaEntityType.getBuilder().applyIdAttribute( + attributeFactory.buildIdAttribute( jpaEntityType, declaredIdentifierProperty ) + ); + } + } + else if ( persistentClass.hasIdentifierMapper() ) { + @SuppressWarnings( "unchecked") + Iterator propertyIterator = persistentClass.getIdentifierMapper().getPropertyIterator(); + Set> attributes = buildIdClassAttributes( jpaEntityType, propertyIterator ); + jpaEntityType.getBuilder().applyIdClassAttributes( attributes ); + } + else { + final KeyValue value = persistentClass.getIdentifier(); + if (value instanceof Component ) { + final Component component = ( Component ) value; + if ( component.getPropertySpan() > 1 ) { + //FIXME we are an Hibernate embedded id (ie not type) + } + else { + //FIXME take care of declared vs non declared property + jpaEntityType.getBuilder().applyIdAttribute( + attributeFactory.buildIdAttribute( + jpaEntityType, + (Property) component.getPropertyIterator().next() ) + ); + } + } + } + } + + private void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) { + if ( mappingType.hasIdentifierProperty() ) { + final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty(); + if (declaredIdentifierProperty != null) { + jpaMappingType.getBuilder().applyIdAttribute( + attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty ) + ); + } + } + //an MappedSuperclass can have no identifier if the id is set below in the hierarchy + else if ( mappingType.getIdentifierMapper() != null ){ + @SuppressWarnings( "unchecked") + Iterator propertyIterator = mappingType.getIdentifierMapper().getPropertyIterator(); + Set> attributes = buildIdClassAttributes( jpaMappingType, propertyIterator ); + jpaMappingType.getBuilder().applyIdClassAttributes( attributes ); + } + } + + private void applyVersionAttribute(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { + final Property declaredVersion = persistentClass.getDeclaredVersion(); + if (declaredVersion != null) { + jpaEntityType.getBuilder().applyVersionAttribute( + attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion ) + ); + } + } + + private void applyVersionAttribute(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) { + final Property declaredVersion = mappingType.getDeclaredVersion(); + if ( declaredVersion != null ) { + jpaMappingType.getBuilder().applyVersionAttribute( + attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion ) + ); + } + } + + private Set> buildIdClassAttributes( + AbstractIdentifiableType ownerType, + Iterator propertyIterator) { + LOG.trace("Building old-school composite identifier [" + ownerType.getJavaType().getName() + "]"); + Set> attributes = new HashSet>(); + while ( propertyIterator.hasNext() ) { + attributes.add( attributeFactory.buildIdAttribute( ownerType, propertyIterator.next() ) ); + } + return attributes; + } + + private void populateStaticMetamodel(AbstractManagedType managedType) { + final Class managedTypeClass = managedType.getJavaType(); + final String metamodelClassName = managedTypeClass.getName() + "_"; + try { + final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); + // we found the class; so populate it... + registerAttributes( metamodelClass, managedType ); + } + catch ( ClassNotFoundException ignore ) { + // nothing to do... + } + + // todo : this does not account for @MappeSuperclass, mainly because this is not being tracked in our + // internal metamodel as populated from the annotatios properly + AbstractManagedType superType = managedType.getSupertype(); + if ( superType != null ) { + populateStaticMetamodel( superType ); + } + } + + private final Set processedMetamodelClasses = new HashSet(); + + private void registerAttributes(Class metamodelClass, AbstractManagedType managedType) { + if ( ! processedMetamodelClasses.add( metamodelClass ) ) { + return; + } + + // push the attributes on to the metamodel class... + for ( Attribute attribute : managedType.getDeclaredAttributes() ) { + registerAttribute( metamodelClass, attribute ); + } + + if ( IdentifiableType.class.isInstance( managedType ) ) { + final AbstractIdentifiableType entityType = ( AbstractIdentifiableType ) managedType; + + // handle version + if ( entityType.hasDeclaredVersionAttribute() ) { + registerAttribute( metamodelClass, entityType.getDeclaredVersion() ); + } + + // handle id-class mappings specially + if ( ! entityType.hasSingleIdAttribute() ) { + final Set> attributes = entityType.getIdClassAttributes(); + if ( attributes != null ) { + for ( SingularAttribute attribute : attributes ) { + registerAttribute( metamodelClass, attribute ); + } + } + } + } + } + + private void registerAttribute(Class metamodelClass, Attribute attribute) { + final String name = attribute.getName(); + try { + // there is a shortcoming in the existing Hibernate code in terms of the way MappedSuperclass + // support was bolted on which comes to bear right here when the attribute is an embeddable type + // defined on a MappedSuperclass. We do not have the correct information to determine the + // appropriate attribute declarer in such cases and so the incoming metamodelClass most likely + // does not represent the declarer in such cases. + // + // As a result, in the case of embeddable classes we simply use getField rather than get + // getDeclaredField + final Field field = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED + ? metamodelClass.getField( name ) + : metamodelClass.getDeclaredField( name ); + try { + if ( ! field.isAccessible() ) { + // should be public anyway, but to be sure... + field.setAccessible( true ); + } + field.set( null, attribute ); + } + catch ( IllegalAccessException e ) { + // todo : exception type? + throw new AssertionFailure( + "Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name, + e + ); + } + catch ( IllegalArgumentException e ) { + // most likely a mismatch in the type we are injecting and the defined field; this represents a + // mismatch in how the annotation processor interpretted the attribute and how our metamodel + // and/or annotation binder did. + +// This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator + +// throw new AssertionFailure( +// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name +// + "; expected type : " + attribute.getClass().getName() +// + "; encountered type : " + field.getType().getName() +// ); + LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(), + name, + attribute.getClass().getName(), + field.getType().getName()); + } + } + catch ( NoSuchFieldException e ) { + LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name); +// throw new AssertionFailure( +// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name +// ); + } + } + + public MappedSuperclassTypeImpl locateMappedSuperclassType(MappedSuperclass mappedSuperclass) { + return mappedSuperclassByMappedSuperclassMapping.get(mappedSuperclass); + } + + public void pushEntityWorkedOn(PersistentClass persistentClass) { + stackOfPersistentClassesBeingProcessed.add(persistentClass); + } + + public void popEntityWorkedOn(PersistentClass persistentClass) { + final PersistentClass stackTop = stackOfPersistentClassesBeingProcessed.remove( + stackOfPersistentClassesBeingProcessed.size() - 1 + ); + if (stackTop != persistentClass) { + throw new AssertionFailure( "Inconsistent popping: " + + persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() ); + } + } + + private PersistentClass getEntityWorkedOn() { + return stackOfPersistentClassesBeingProcessed.get( + stackOfPersistentClassesBeingProcessed.size() - 1 + ); + } + + public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl mappedSuperclassType) { + final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType ); + if (persistentClass == null) { + throw new AssertionFailure( "Could not find PersistentClass for MappedSuperclassType: " + + mappedSuperclassType.getJavaType() ); + } + return persistentClass; + } + + public void handleAnyMapping() { + // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 + if ( isIgnoreUnsupported() ) { + } + else { + throw new UnsupportedOperationException( "ANY not supported" ); + } + } + + public void handleArrayMapping() { + if ( isIgnoreUnsupported() ) { + } + else { + throw new UnsupportedOperationException( "Arrays not supported" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetamodelImpl.java new file mode 100644 index 0000000000..46350b2be8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/MetamodelImpl.java @@ -0,0 +1,238 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.EmbeddableType; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.MappedSuperclassType; +import javax.persistence.metamodel.Metamodel; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.mapping.MappedSuperclass; +import org.hibernate.mapping.PersistentClass; + +/** + * Hibernate implementation of the JPA {@link javax.persistence.metamodel.Metamodel} contract. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class MetamodelImpl implements Metamodel, Serializable { + private final Map,EntityTypeImpl> entities; + private final Map, EmbeddableTypeImpl> embeddables; + private final Map, MappedSuperclassType> mappedSuperclassTypeMap; + + /** + * Build the metamodel using the information from the collection of Hibernate + * {@link org.hibernate.mapping.PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}. + * + * @param persistentClasses Iterator over the Hibernate (config-time) metamodel + * @param sessionFactory The Hibernate session factory. + * @return The built metamodel + * + * @deprecated use {@link #buildMetamodel(java.util.Iterator,org.hibernate.engine.spi.SessionFactoryImplementor,boolean)} instead + */ + @Deprecated + public static MetamodelImpl buildMetamodel( + Iterator persistentClasses, + SessionFactoryImplementor sessionFactory) { + return buildMetamodel(persistentClasses, sessionFactory, false); + } + + /** + * Build the metamodel using the information from the collection of Hibernate + * {@link org.hibernate.mapping.PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}. + * + * @param persistentClasses Iterator over the Hibernate (config-time) metamodel + * @param sessionFactory The Hibernate session factory. + * @param ignoreUnsupported ignore unsupported/unknown annotations (like @Any) + * @return The built metamodel + */ + public static MetamodelImpl buildMetamodel( + Iterator persistentClasses, + SessionFactoryImplementor sessionFactory, + boolean ignoreUnsupported) { + MetadataContext context = new MetadataContext( sessionFactory, ignoreUnsupported ); + while ( persistentClasses.hasNext() ) { + PersistentClass pc = persistentClasses.next(); + if ( pc.getMappedClass() != null ) { + locateOrBuildEntityType( pc, context ); + } + } + context.wrapUp(); + return new MetamodelImpl( context.getEntityTypeMap(), context.getEmbeddableTypeMap(), context.getMappedSuperclassTypeMap() ); + } + + private static EntityTypeImpl locateOrBuildEntityType(PersistentClass persistentClass, MetadataContext context) { + EntityTypeImpl entityType = context.locateEntityType( persistentClass ); + if ( entityType == null ) { + entityType = buildEntityType( persistentClass, context ); + } + return entityType; + } + + //TODO remove / reduce @SW scope + @SuppressWarnings( "unchecked" ) + private static EntityTypeImpl buildEntityType(PersistentClass persistentClass, MetadataContext context) { + final Class javaType = persistentClass.getMappedClass(); + context.pushEntityWorkedOn(persistentClass); + final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); + AbstractIdentifiableType superType = superMappedSuperclass == null + ? null + : locateOrBuildMappedsuperclassType( superMappedSuperclass, context ); + //no mappedSuperclass, check for a super entity + if (superType == null) { + final PersistentClass superPersistentClass = persistentClass.getSuperclass(); + superType = superPersistentClass == null + ? null + : locateOrBuildEntityType( superPersistentClass, context ); + } + EntityTypeImpl entityType = new EntityTypeImpl( + javaType, + superType, + persistentClass.getJpaEntityName(), + persistentClass.hasIdentifierProperty(), + persistentClass.isVersioned() + ); + context.registerEntityType( persistentClass, entityType ); + context.popEntityWorkedOn(persistentClass); + return entityType; + } + + private static MappedSuperclassTypeImpl locateOrBuildMappedsuperclassType( + MappedSuperclass mappedSuperclass, MetadataContext context) { + MappedSuperclassTypeImpl mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass ); + if ( mappedSuperclassType == null ) { + mappedSuperclassType = buildMappedSuperclassType(mappedSuperclass, context); + } + return mappedSuperclassType; + } + + //TODO remove / reduce @SW scope + @SuppressWarnings( "unchecked" ) + private static MappedSuperclassTypeImpl buildMappedSuperclassType(MappedSuperclass mappedSuperclass, + MetadataContext context) { + final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); + AbstractIdentifiableType superType = superMappedSuperclass == null + ? null + : locateOrBuildMappedsuperclassType( superMappedSuperclass, context ); + //no mappedSuperclass, check for a super entity + if (superType == null) { + final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass(); + superType = superPersistentClass == null + ? null + : locateOrBuildEntityType( superPersistentClass, context ); + } + final Class javaType = mappedSuperclass.getMappedClass(); + MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( + javaType, + superType, + mappedSuperclass.hasIdentifierProperty(), + mappedSuperclass.isVersioned() + ); + context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType ); + return mappedSuperclassType; + } + + /** + * Instantiate the metamodel. + * + * @param entities The entity mappings. + * @param embeddables The embeddable (component) mappings. + * @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings + */ + private MetamodelImpl( + Map, EntityTypeImpl> entities, + Map, EmbeddableTypeImpl> embeddables, + Map, MappedSuperclassType> mappedSuperclassTypeMap) { + this.entities = entities; + this.embeddables = embeddables; + this.mappedSuperclassTypeMap = mappedSuperclassTypeMap; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public EntityType entity(Class cls) { + final EntityType entityType = entities.get( cls ); + if ( entityType == null ) { + throw new IllegalArgumentException( "Not an entity: " + cls ); + } + return (EntityType) entityType; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public ManagedType managedType(Class cls) { + ManagedType type = entities.get( cls ); + if ( type == null ) { + type = mappedSuperclassTypeMap.get( cls ); + } + if ( type == null ) { + type = embeddables.get( cls ); + } + if ( type == null ) { + throw new IllegalArgumentException( "Not an managed type: " + cls ); + } + return (ManagedType) type; + } + + @Override + @SuppressWarnings({ "unchecked" }) + public EmbeddableType embeddable(Class cls) { + final EmbeddableType embeddableType = embeddables.get( cls ); + if ( embeddableType == null ) { + throw new IllegalArgumentException( "Not an embeddable: " + cls ); + } + return (EmbeddableType) embeddableType; + } + + @Override + public Set> getManagedTypes() { + final int setSize = CollectionHelper.determineProperSizing( + entities.size() + mappedSuperclassTypeMap.size() + embeddables.size() + ); + final Set> managedTypes = new HashSet>( setSize ); + managedTypes.addAll( entities.values() ); + managedTypes.addAll( mappedSuperclassTypeMap.values() ); + managedTypes.addAll( embeddables.values() ); + return managedTypes; + } + + @Override + public Set> getEntities() { + return new HashSet>( entities.values() ); + } + + @Override + public Set> getEmbeddables() { + return new HashSet>( embeddables.values() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/PluralAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/PluralAttributeImpl.java new file mode 100644 index 0000000000..2df68203da --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/PluralAttributeImpl.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import java.lang.reflect.Member; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.Type; + +import org.hibernate.mapping.Property; + +/** + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public abstract class PluralAttributeImpl + extends AbstractAttribute + implements PluralAttribute, Serializable { + + private final Type elementType; + + private PluralAttributeImpl(Builder builder) { + super( + builder.property.getName(), + builder.collectionClass, + builder.type, + builder.member, + builder.persistentAttributeType + ); + this.elementType = builder.attributeType; + } + + public static class Builder { + private final Type attributeType; + private final AbstractManagedType type; + private Member member; + private PersistentAttributeType persistentAttributeType; + private Property property; + private Class collectionClass; + private Type keyType; + + + private Builder(AbstractManagedType ownerType, Type attrType, Class collectionClass, Type keyType) { + this.type = ownerType; + this.attributeType = attrType; + this.collectionClass = collectionClass; + this.keyType = keyType; + } + + public Builder member(Member member) { + this.member = member; + return this; + } + + public Builder property(Property property) { + this.property = property; + return this; + } + + public Builder persistentAttributeType(PersistentAttributeType attrType) { + this.persistentAttributeType = attrType; + return this; + } + + @SuppressWarnings( "unchecked" ) + public PluralAttributeImpl build() { + //apply strict spec rules first + if ( Map.class.equals( collectionClass ) ) { + final Builder,E,K> builder = (Builder,E,K>) this; + return ( PluralAttributeImpl ) new MapAttributeImpl( + builder + ); + } + else if ( Set.class.equals( collectionClass ) ) { + final Builder, E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new SetAttributeImpl( + builder + ); + } + else if ( List.class.equals( collectionClass ) ) { + final Builder, E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new ListAttributeImpl( + builder + ); + } + else if ( Collection.class.equals( collectionClass ) ) { + final Builder,E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new CollectionAttributeImpl( + builder + ); + } + + //apply loose rules + if ( Map.class.isAssignableFrom( collectionClass ) ) { + final Builder,E,K> builder = (Builder,E,K>) this; + return ( PluralAttributeImpl ) new MapAttributeImpl( + builder + ); + } + else if ( Set.class.isAssignableFrom( collectionClass ) ) { + final Builder, E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new SetAttributeImpl( + builder + ); + } + else if ( List.class.isAssignableFrom( collectionClass ) ) { + final Builder, E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new ListAttributeImpl( + builder + ); + } + else if ( Collection.class.isAssignableFrom( collectionClass ) ) { + final Builder,E,?> builder = (Builder, E,?>) this; + return ( PluralAttributeImpl ) new CollectionAttributeImpl( + builder + ); + } + throw new UnsupportedOperationException( "Unkown collection: " + collectionClass ); + } + } + + public static Builder create( + AbstractManagedType ownerType, + Type attrType, + Class collectionClass, + Type keyType) { + return new Builder(ownerType, attrType, collectionClass, keyType); + } + + /** + * {@inheritDoc} + */ + public Type getElementType() { + return elementType; + } + + /** + * {@inheritDoc} + */ + public boolean isAssociation() { + return true; + } + + /** + * {@inheritDoc} + */ + public boolean isCollection() { + return true; + } + + /** + * {@inheritDoc} + */ + public BindableType getBindableType() { + return BindableType.PLURAL_ATTRIBUTE; + } + + /** + * {@inheritDoc} + */ + public Class getBindableJavaType() { + return elementType.getJavaType(); + } + + static class SetAttributeImpl extends PluralAttributeImpl,E> implements SetAttribute { + SetAttributeImpl(Builder,E,?> xceBuilder) { + super( xceBuilder ); + } + + /** + * {@inheritDoc} + */ + public CollectionType getCollectionType() { + return CollectionType.SET; + } + } + + static class CollectionAttributeImpl extends PluralAttributeImpl,E> implements CollectionAttribute { + CollectionAttributeImpl(Builder,E,?> xceBuilder) { + super( xceBuilder ); + } + + /** + * {@inheritDoc} + */ + public CollectionType getCollectionType() { + return CollectionType.COLLECTION; + } + } + + static class ListAttributeImpl extends PluralAttributeImpl,E> implements ListAttribute { + ListAttributeImpl(Builder,E,?> xceBuilder) { + super( xceBuilder ); + } + + /** + * {@inheritDoc} + */ + public CollectionType getCollectionType() { + return CollectionType.LIST; + } + } + + static class MapAttributeImpl extends PluralAttributeImpl,V> implements MapAttribute { + private final Type keyType; + + MapAttributeImpl(Builder,V,K> xceBuilder) { + super( xceBuilder ); + this.keyType = xceBuilder.keyType; + } + + /** + * {@inheritDoc} + */ + public CollectionType getCollectionType() { + return CollectionType.MAP; + } + + /** + * {@inheritDoc} + */ + public Class getKeyJavaType() { + return keyType.getJavaType(); + } + + /** + * {@inheritDoc} + */ + public Type getKeyType() { + return keyType; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/SingularAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/SingularAttributeImpl.java new file mode 100644 index 0000000000..7b9f355fd2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/internal/legacy/SingularAttributeImpl.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.metamodel.internal.legacy; + +import java.io.Serializable; +import java.lang.reflect.Member; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +/** + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public class SingularAttributeImpl + extends AbstractAttribute + implements SingularAttribute, Serializable { + private final boolean isIdentifier; + private final boolean isVersion; + private final boolean isOptional; + private final Type attributeType; + + public SingularAttributeImpl( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + boolean isIdentifier, + boolean isVersion, + boolean isOptional, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, persistentAttributeType ); + this.isIdentifier = isIdentifier; + this.isVersion = isVersion; + this.isOptional = isOptional; + this.attributeType = attributeType; + } + + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * identifier. + */ + public static class Identifier extends SingularAttributeImpl { + public Identifier( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, true, false, false, attributeType, persistentAttributeType ); + } + } + + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * version. + */ + public static class Version extends SingularAttributeImpl { + public Version( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, false, true, false, attributeType, persistentAttributeType ); + } + } + + /** + * {@inheritDoc} + */ + public boolean isId() { + return isIdentifier; + } + + /** + * {@inheritDoc} + */ + public boolean isVersion() { + return isVersion; + } + + /** + * {@inheritDoc} + */ + public boolean isOptional() { + return isOptional; + } + + /** + * {@inheritDoc} + */ + public Type getType() { + return attributeType; + } + + /** + * {@inheritDoc} + */ + public boolean isAssociation() { + return false; + } + + /** + * {@inheritDoc} + */ + public boolean isCollection() { + return false; + } + + /** + * {@inheritDoc} + */ + public BindableType getBindableType() { + return BindableType.SINGULAR_ATTRIBUTE; + } + + /** + * {@inheritDoc} + */ + public Class getBindableJavaType() { + return attributeType.getJavaType(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/package-info.java b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/package-info.java new file mode 100644 index 0000000000..d08fb682df --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/jpa/metamodel/package-info.java @@ -0,0 +1 @@ +package org.hibernate.jpa.metamodel; \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java b/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java index c415c6e7a4..89fe34838e 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java @@ -792,7 +792,7 @@ public class JoinWalker { protected boolean isDuplicateAssociation(final String lhsTable, final String[] lhsColumnNames, final AssociationType type) { final String foreignKeyTable; final String[] foreignKeyColumns; - if ( type.getForeignKeyDirection()==ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + if ( type.getForeignKeyDirection()==ForeignKeyDirection.FROM_PARENT ) { foreignKeyTable = lhsTable; foreignKeyColumns = lhsColumnNames; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java index 6beab81c01..8b75a28bb7 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java @@ -523,14 +523,14 @@ public abstract class Collection implements Fetchable, Value, Filterable { } public void addFilter(String name, String condition, boolean autoAliasInjection, java.util.Map aliasTableMap, java.util.Map aliasEntityMap) { - filters.add(new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null)); + filters.add(new FilterConfiguration( name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap ) ); } public java.util.List getFilters() { return filters; } public void addManyToManyFilter(String name, String condition, boolean autoAliasInjection, java.util.Map aliasTableMap, java.util.Map aliasEntityMap) { - manyToManyFilters.add(new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null)); + manyToManyFilters.add(new FilterConfiguration( name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap ) ); } public java.util.List getManyToManyFilters() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java index ce58902d7d..bed56d87d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java @@ -21,25 +21,33 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - package org.hibernate.metamodel; +import java.util.List; import java.util.Map; import javax.persistence.SharedCacheMode; +import org.jboss.jandex.IndexView; +import org.xml.sax.EntityResolver; + +import org.hibernate.MultiTenancyStrategy; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.engine.ResultSetMappingDefinition; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.NamedQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.type.BasicType; /** * @author Steve Ebersole @@ -49,52 +57,67 @@ public interface Metadata { * Exposes the options used to produce a {@link Metadata} instance. */ public static interface Options { - public StandardServiceRegistry getServiceRegistry(); + StandardServiceRegistry getServiceRegistry(); - public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder(); - public NamingStrategy getNamingStrategy(); - public SharedCacheMode getSharedCacheMode(); - public AccessType getDefaultAccessType(); - public boolean useNewIdentifierGenerators(); - public boolean isGloballyQuotedIdentifiers(); - public String getDefaultSchemaName(); - public String getDefaultCatalogName(); + MetadataSourceProcessingOrder getMetadataSourceProcessingOrder(); + NamingStrategy getNamingStrategy(); + EntityResolver getEntityResolver(); + SharedCacheMode getSharedCacheMode(); + AccessType getDefaultAccessType(); + boolean useNewIdentifierGenerators(); + boolean isGloballyQuotedIdentifiers(); + String getDefaultSchemaName(); + String getDefaultCatalogName(); + MultiTenancyStrategy getMultiTenancyStrategy(); + IndexView getJandexView(); + List getBasicTypeRegistrations(); } - public Options getOptions(); + /** + * Retrieve the options used to build this {@link Metadata} instance. + * + * @return The options. + */ + Options getOptions(); - public SessionFactoryBuilder getSessionFactoryBuilder(); + /** + * Get the builder for {@link SessionFactory} instances based on this metamodel, + * + * @return The builder for {@link SessionFactory} instances. + */ + SessionFactoryBuilder getSessionFactoryBuilder(); - public SessionFactory buildSessionFactory(); + /** + * Short-hand form of building a {@link SessionFactory} through the builder without any additional + * option overrides. + * + * @return THe built SessionFactory. + */ + SessionFactory buildSessionFactory(); - public Iterable getEntityBindings(); - public EntityBinding getEntityBinding(String entityName); + EntityBinding getEntityBinding(String entityName); /** * Get the "root" entity binding * @param entityName * @return the "root entity binding; simply returns entityBinding if it is the root entity binding */ - public EntityBinding getRootEntityBinding(String entityName); + EntityBinding getRootEntityBinding(String entityName); + IdentifierGeneratorDefinition getIdGenerator(String name); + boolean hasTypeDefinition(String name); + TypeDefinition getTypeDefinition(String name); - public Iterable getCollectionBindings(); + Iterable getCollectionBindings(); + Iterable getEntityBindings(); + Iterable getTypeDefinitions(); + Iterable getNamedQueryDefinitions(); + Iterable getNamedNativeQueryDefinitions(); + Iterable getFetchProfiles(); - public TypeDef getTypeDefinition(String name); - - public Iterable getTypeDefinitions(); - - public Iterable getFilterDefinitions(); - - public Iterable getNamedQueryDefinitions(); - - public Iterable getNamedNativeQueryDefinitions(); - - public Iterable getResultSetMappingDefinitions(); - - public Iterable> getImports(); - - public Iterable getFetchProfiles(); - - public IdGenerator getIdGenerator(String name); + Map getSecondaryTables(); + Map getFilterDefinitions(); + Map getNamedEntityGraphs(); + Map getResultSetMappingDefinitions(); + Map getImports(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java index 1295a80923..7ad7412e25 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java @@ -25,23 +25,129 @@ package org.hibernate.metamodel; import javax.persistence.SharedCacheMode; +import org.jboss.jandex.IndexView; +import org.xml.sax.EntityResolver; + import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.NamingStrategy; +import org.hibernate.type.BasicType; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; /** + * Contract for specifying various overrides to be used in metamodel building. + * * @author Steve Ebersole * @author Hardy Ferentschik */ public interface MetadataBuilder { + /** + * Specify a specific NamingStrategy to use in building the metamodel. + * + * @param namingStrategy The naming strategy to use. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder with(NamingStrategy namingStrategy); + /** + * Specify a specific XML EntityResolver to use in building the metamodel. + * + * @param entityResolver The entity resolver to use. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(EntityResolver entityResolver); + + /** + * Specify the order in which to process metadata sources. + * + * @param metadataSourceProcessingOrder The order. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder with(MetadataSourceProcessingOrder metadataSourceProcessingOrder); + /** + * Specify the second-level cache mode to be used. This is the cache mode in terms of whether or + * not to cache. + * + * @param cacheMode The cache mode. + * + * @return {@code this}, for method chaining + * + * @see #with(org.hibernate.cache.spi.access.AccessType) + */ public MetadataBuilder with(SharedCacheMode cacheMode); + /** + * Specify the second-level access-type to be used by default for entities and collections that define second-level + * caching, but do not specify a granular access-type. + * + * @param accessType The access-type to use as default. + * + * @return {@code this}, for method chaining + * + * @see #with(javax.persistence.SharedCacheMode) + */ public MetadataBuilder with(AccessType accessType); + /** + * Allows specifying a specific Jandex index to use for reading annotation information. + * + * @param jandexView The Jandex index to use. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(IndexView jandexView); + + /** + * Should the new (well "new" since 3.2) identifier generators be used for + * {@link javax.persistence.GenerationType#SEQUENCE}, + * {@link javax.persistence.GenerationType#IDENTITY}, + * {@link javax.persistence.GenerationType#TABLE} and + * {@link javax.persistence.GenerationType#AUTO} handling? + * + * @param enabled {@code true} says to use the new generator mappings; {@code false} says to use the legacy + * generator mappings. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled); + /** + * Specify an additional or overridden basic type mapping. + * + * @param type The type addition or override. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(BasicType type); + + /** + * Register an additional or overridden custom type mapping. + * + * @param type The custom type + * @param keys The keys under which to register the custom type. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(UserType type, String[] keys); + + /** + * Register an additional or overridden composite custom type mapping. + * + * @param type The composite custom type + * @param keys The keys under which to register the composite custom type. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(CompositeUserType type, String[] keys); + + /** + * Actually build the metamodel + * + * @return The built metadata. + */ public Metadata build(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java index 01c2dbd63f..099961edbd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java @@ -26,67 +26,84 @@ package org.hibernate.metamodel; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.Serializable; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import org.hibernate.HibernateException; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.EJB3DTDEntityResolver; -import org.hibernate.cfg.EJB3NamingStrategy; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MappingNotFoundException; -import org.hibernate.metamodel.source.internal.JaxbHelper; -import org.hibernate.metamodel.source.internal.MetadataBuilderImpl; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.SerializationHelper; +import org.hibernate.jaxb.internal.JaxbMappingProcessor; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.jaxb.spi.orm.JaxbEntityMappings; +import org.hibernate.metamodel.internal.MetadataBuilderImpl; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.EntityMappingsMocker; +import org.hibernate.metamodel.spi.source.InvalidMappingException; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.MappingNotFoundException; import org.hibernate.service.ServiceRegistry; - +import org.hibernate.type.SerializationException; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; import org.jboss.logging.Logger; - import org.w3c.dom.Document; -import org.xml.sax.EntityResolver; /** + * Entry point into working with sources of metadata information ({@code hbm.xml}, annotations). Tell Hibernate + * about sources and then call {@link #buildMetadata()}. + * * @author Steve Ebersole + * @author Brett Meyer */ public class MetadataSources { - private static final Logger LOG = Logger.getLogger( MetadataSources.class ); + public static final String UNKNOWN_FILE_PATH = ""; + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, MetadataSources.class.getName()); + + /** + * temporary option + */ + public static final String USE_NEW_METADATA_MAPPINGS = "hibernate.test.new_metadata_mappings"; private final ServiceRegistry serviceRegistry; - + private final JaxbMappingProcessor jaxbProcessor; + private final List externalCacheRegionDefinitions = new ArrayList(); private List jaxbRootList = new ArrayList(); private LinkedHashSet> annotatedClasses = new LinkedHashSet>(); + private LinkedHashSet annotatedClassNames = new LinkedHashSet(); private LinkedHashSet annotatedPackages = new LinkedHashSet(); - private final JaxbHelper jaxbHelper; - - private final EntityResolver entityResolver; - private final NamingStrategy namingStrategy; - - private final MetadataBuilderImpl metadataBuilder; + private boolean hasOrmXmlJaxbRoots; + /** + * Create a metadata sources using the specified service registry. + * + * @param serviceRegistry The service registry to use. + */ public MetadataSources(ServiceRegistry serviceRegistry) { - this( serviceRegistry, EJB3DTDEntityResolver.INSTANCE, EJB3NamingStrategy.INSTANCE ); - } - - public MetadataSources(ServiceRegistry serviceRegistry, EntityResolver entityResolver, NamingStrategy namingStrategy) { - this.serviceRegistry = serviceRegistry; - this.entityResolver = entityResolver; - this.namingStrategy = namingStrategy; - - this.jaxbHelper = new JaxbHelper( this ); - this.metadataBuilder = new MetadataBuilderImpl( this ); - // service registry really should be either BootstrapServiceRegistry or StandardServiceRegistry type... if ( ! isExpectedServiceRegistryType( serviceRegistry ) ) { LOG.debugf( @@ -95,6 +112,8 @@ public class MetadataSources { serviceRegistry.getClass().getName() ); } + this.serviceRegistry = serviceRegistry; + this.jaxbProcessor = new JaxbMappingProcessor( serviceRegistry ); } protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) { @@ -114,12 +133,20 @@ public class MetadataSources { return annotatedClasses; } + public Iterable getAnnotatedClassNames() { + return annotatedClassNames; + } + + public List getExternalCacheRegionDefinitions() { + return externalCacheRegionDefinitions; + } + public ServiceRegistry getServiceRegistry() { return serviceRegistry; } - public NamingStrategy getNamingStrategy() { - return namingStrategy; + public boolean hasOrmXmlJaxbRoots() { + return hasOrmXmlJaxbRoots; } /** @@ -167,6 +194,18 @@ public class MetadataSources { return this; } + /** + * Read metadata from the annotations attached to the given class. + * + * @param annotatedClassName The name of a class containing annotations + * + * @return this (for method chaining) + */ + public MetadataSources addAnnotatedClassName(String annotatedClassName) { + annotatedClassNames.add( annotatedClassName ); + return this; + } + /** * Read package-level metadata. * @@ -211,10 +250,13 @@ public class MetadataSources { private JaxbRoot add(InputStream inputStream, Origin origin, boolean close) { try { - JaxbRoot jaxbRoot = jaxbHelper.unmarshal( inputStream, origin ); - jaxbRootList.add( jaxbRoot ); + JaxbRoot jaxbRoot = jaxbProcessor.unmarshal( inputStream, origin ); + addJaxbRoot( jaxbRoot ); return jaxbRoot; } + catch ( Exception e ) { + throw new InvalidMappingException( origin, e ); + } finally { if ( close ) { try { @@ -288,7 +330,7 @@ public class MetadataSources { * @see #addCacheableFile(java.io.File) */ public MetadataSources addCacheableFile(String path) { - return this; // todo : implement method body + return addCacheableFile( new File( path ) ); } /** @@ -305,7 +347,72 @@ public class MetadataSources { * @return this (for method chaining purposes) */ public MetadataSources addCacheableFile(File file) { - return this; // todo : implement method body + Origin origin = new Origin( SourceType.FILE, file.getAbsolutePath() ); + File cachedFile = determineCachedDomFile( file ); + + try { + return addCacheableFileStrictly( file ); + } + catch ( SerializationException e ) { + LOG.unableToDeserializeCache( cachedFile.getName(), e ); + } + catch ( FileNotFoundException e ) { + LOG.cachedFileNotFound( cachedFile.getName(), e ); + } + + final FileInputStream inputStream; + try { + inputStream = new FileInputStream( file ); + } + catch ( FileNotFoundException e ) { + throw new MappingNotFoundException( origin ); + } + + LOG.readingMappingsFromFile( file.getPath() ); + JaxbRoot metadataXml = add( inputStream, origin, true ); + + try { + LOG.debugf( "Writing cache file for: %s to: %s", file, cachedFile ); + SerializationHelper.serialize( ( Serializable ) metadataXml, new FileOutputStream( cachedFile ) ); + } + catch ( Exception e ) { + LOG.unableToWriteCachedFile( cachedFile.getName(), e.getMessage() ); + } + + return this; + } + + /** + * INTENDED FOR TESTSUITE USE ONLY! + *

          + * Much like {@link #addCacheableFile(File)} except that here we will fail immediately if + * the cache version cannot be found or used for whatever reason + * + * @param xmlFile The xml file, not the bin! + * + * @return The dom "deserialized" from the cached file. + * + * @throws SerializationException Indicates a problem deserializing the cached dom tree + * @throws FileNotFoundException Indicates that the cached file was not found or was not usable. + */ + public MetadataSources addCacheableFileStrictly(File file) throws SerializationException, FileNotFoundException { + File cachedFile = determineCachedDomFile( file ); + + final boolean useCachedFile = file.exists() + && cachedFile.exists() + && file.lastModified() < cachedFile.lastModified(); + + if ( ! useCachedFile ) { + throw new FileNotFoundException( "Cached file could not be found or could not be used" ); + } + + LOG.readingCachedMappings( cachedFile ); + addJaxbRoot( ( JaxbRoot ) SerializationHelper.deserialize( new FileInputStream( cachedFile ) ) ); + return this; + } + + private File determineCachedDomFile(File xmlFile) { + return new File( xmlFile.getAbsolutePath() + ".bin" ); } /** @@ -316,7 +423,7 @@ public class MetadataSources { * @return this (for method chaining purposes) */ public MetadataSources addInputStream(InputStream xmlInputStream) { - add( xmlInputStream, new Origin( SourceType.INPUT_STREAM, "" ), false ); + add( xmlInputStream, new Origin( SourceType.INPUT_STREAM, UNKNOWN_FILE_PATH ), false ); return this; } @@ -349,12 +456,17 @@ public class MetadataSources { * @return this (for method chaining purposes) */ public MetadataSources addDocument(Document document) { - final Origin origin = new Origin( SourceType.DOM, "" ); - JaxbRoot jaxbRoot = jaxbHelper.unmarshal( document, origin ); - jaxbRootList.add( jaxbRoot ); + final Origin origin = new Origin( SourceType.DOM, UNKNOWN_FILE_PATH ); + JaxbRoot jaxbRoot = jaxbProcessor.unmarshal( document, origin ); + addJaxbRoot( jaxbRoot ); return this; } + private void addJaxbRoot(JaxbRoot jaxbRoot) { + hasOrmXmlJaxbRoots = hasOrmXmlJaxbRoots || JaxbEntityMappings.class.isInstance( jaxbRoot.getRoot() ); + jaxbRootList.add( jaxbRoot ); + } + /** * Read all mappings from a jar file. *

          @@ -412,14 +524,138 @@ public class MetadataSources { */ public MetadataSources addDirectory(File dir) { File[] files = dir.listFiles(); - for ( File file : files ) { - if ( file.isDirectory() ) { - addDirectory( file ); - } - else if ( file.getName().endsWith( ".hbm.xml" ) ) { - addFile( file ); + if ( files != null && files.length > 0 ) { + for ( File file : files ) { + if ( file.isDirectory() ) { + addDirectory( file ); + } + else if ( file.getName().endsWith( ".hbm.xml" ) ) { + addFile( file ); + } } } return this; } + + public MetadataSources addCacheRegionDefinitions(List cacheRegionDefinitions) { + externalCacheRegionDefinitions.addAll( cacheRegionDefinitions ); + return this; + } + + @SuppressWarnings("unchecked") + public IndexView wrapJandexView(IndexView jandexView) { + if ( ! hasOrmXmlJaxbRoots ) { + // no need to wrap + return jandexView; + } + + final List collectedOrmXmlMappings = new ArrayList(); + for ( JaxbRoot jaxbRoot : getJaxbRootList() ) { + if ( JaxbEntityMappings.class.isInstance( jaxbRoot.getRoot() ) ) { + collectedOrmXmlMappings.add( ( (JaxbRoot) jaxbRoot ).getRoot() ); + } + } + + if ( collectedOrmXmlMappings.isEmpty() ) { + // log a warning or something + } + + return new EntityMappingsMocker( collectedOrmXmlMappings, jandexView, serviceRegistry ).mockNewIndex(); + } + + public IndexView buildJandexView() { + return buildJandexView( false ); + } + + public IndexView buildJandexView(boolean autoIndexMemberTypes) { + // create a jandex index from the annotated classes + + Indexer indexer = new Indexer(); + + Set> processedClasses = new HashSet>(); + for ( Class clazz : getAnnotatedClasses() ) { + indexClass( clazz, indexer, processedClasses, autoIndexMemberTypes ); + } + + for ( String className : getAnnotatedClassNames() ) { + indexResource( className.replace( '.', '/' ) + ".class", indexer ); + } + + // add package-info from the configured packages + for ( String packageName : getAnnotatedPackages() ) { + indexResource( packageName.replace( '.', '/' ) + "/package-info.class", indexer ); + } + + return wrapJandexView( indexer.complete() ); + } + + private void indexClass(Class clazz, Indexer indexer, Set> processedClasses, boolean autoIndexMemberTypes) { + if ( clazz == null || clazz == Object.class + || processedClasses.contains( clazz ) ) { + return; + } + + processedClasses.add( clazz ); + + ClassInfo classInfo = indexResource( + clazz.getName().replace( '.', '/' ) + ".class", indexer ); + + // index all super classes of the specified class. Using org.hibernate.cfg.Configuration it was not + // necessary to add all annotated classes. Entities would be enough. Mapped superclasses would be + // discovered while processing the annotations. To keep this behavior we index all classes in the + // hierarchy (see also HHH-7484) + indexClass( clazz.getSuperclass(), indexer, processedClasses, autoIndexMemberTypes ); + + // Similarly, index any inner class. + for ( Class innerClass : clazz.getDeclaredClasses() ) { + indexClass( innerClass, indexer, processedClasses, autoIndexMemberTypes ); + } + + if ( autoIndexMemberTypes ) { + // If autoIndexMemberTypes, don't require @Embeddable + // classes to be explicitly identified. + // Automatically find them by checking the fields' types. + for ( Class fieldType : ReflectHelper.getMemberTypes( clazz ) ) { + if ( !fieldType.isPrimitive() && fieldType != Object.class ) { + try { + IndexView fieldIndex = JandexHelper.indexForClass( + serviceRegistry.getService( ClassLoaderService.class ), + fieldType ); + if ( !fieldIndex.getAnnotations( + JPADotNames.EMBEDDABLE ).isEmpty() ) { + indexClass( fieldType, indexer, processedClasses, autoIndexMemberTypes ); + } + } catch ( Exception e ) { + // do nothing + } + } + } + + // Also check for classes within a @Target annotation. + for ( AnnotationInstance targetAnnotation : JandexHelper.getAnnotations( + classInfo, HibernateDotNames.TARGET ) ) { + String targetClassName = targetAnnotation.value().asClass().name() + .toString(); + Class targetClass = serviceRegistry.getService( + ClassLoaderService.class ).classForName( targetClassName ); + indexClass(targetClass, indexer, processedClasses, autoIndexMemberTypes ); + } + } + } + + private ClassInfo indexResource(String resourceName, Indexer indexer) { + ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + + if ( classLoaderService.locateResource( resourceName ) != null ) { + InputStream stream = classLoaderService.locateResourceStream( resourceName ); + try { + return indexer.index( stream ); + } + catch ( IOException e ) { + throw new HibernateException( "Unable to open input stream for resource " + resourceName, e ); + } + } + + return null; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java index c3cb204e36..c9171567fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java @@ -23,18 +23,99 @@ */ package org.hibernate.metamodel; +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.EntityMode; +import org.hibernate.EntityNameResolver; import org.hibernate.Interceptor; import org.hibernate.SessionFactory; +import org.hibernate.SessionFactoryObserver; +import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.tuple.entity.EntityTuplizer; /** + * The contract for building a {@link SessionFactory} given a number of options. + * + * @author Steve Ebersole * @author Gail Badner */ public interface SessionFactoryBuilder { + /** + * Names an interceptor to be applied to the SessionFactory, which in turn means it will be used by all + * Sessions unless one is explicitly specified in {@link org.hibernate.SessionBuilder#interceptor} + * + * @param interceptor The interceptor + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#INTERCEPTOR + */ public SessionFactoryBuilder with(Interceptor interceptor); + /** + * Specifies a custom entity dirtiness strategy to be applied to the SessionFactory. See the contract + * of {@link CustomEntityDirtinessStrategy} for details. + * + * @param customEntityDirtinessStrategy The custom strategy to be used. + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#CUSTOM_ENTITY_DIRTINESS_STRATEGY + */ + public SessionFactoryBuilder with(CustomEntityDirtinessStrategy customEntityDirtinessStrategy); + + /** + * Specifies a strategy for resolving the notion of a "current" tenant-identifier when using multi-tenancy + * together with current sessions + * + * @param currentTenantIdentifierResolver The resolution strategy to use. + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#MULTI_TENANT_IDENTIFIER_RESOLVER + */ + public SessionFactoryBuilder with(CurrentTenantIdentifierResolver currentTenantIdentifierResolver); + + /** + * Specifies one or more observers to be applied to the SessionFactory. Can be called multiple times to add + * additional observers. + * + * @param observers The observers to add + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder add(SessionFactoryObserver... observers); + + /** + * Specifies one or more entity name resolvers to be applied to the SessionFactory (see the {@link EntityNameResolver} + * contract for more information.. Can be called multiple times to add additional resolvers.. + * + * @param entityNameResolvers The entityNameResolvers to add + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder add(EntityNameResolver... entityNameResolvers); + + /** + * Names the {@link EntityNotFoundDelegate} to be applied to the SessionFactory. EntityNotFoundDelegate is a + * strategy that accounts for different exceptions thrown between Hibernate and JPA when an entity cannot be found. + * + * @param entityNotFoundDelegate The delegate/strategy to use. + * + * @return {@code this}, for method chaining + */ public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate); + /** + * Register the default {@link EntityTuplizer} to be applied to the SessionFactory. + * + * @param entityMode The entity mode that which this tuplizer will be applied. + * @param tuplizerClass The custom tuplizer class. + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder with(EntityMode entityMode, Class tuplizerClass); + /** * After all options have been set, build the SessionFactory. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java deleted file mode 100644 index b80066a8a0..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.persister.collection.CollectionPersister; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBinding implements PluralAttributeBinding { - private final CollectionKey collectionKey; - private final AbstractCollectionElement collectionElement; - - private Table collectionTable; - - private FetchTiming fetchTiming; - private FetchStyle fetchStyle; - private int batchSize = -1; - - private CascadeStyle cascadeStyle; - private boolean orphanDelete; - - private Caching caching; - - private boolean inverse; - private boolean mutable = true; - - private Class collectionPersisterClass; - - private String where; - private String orderBy; - private boolean sorted; - private Comparator comparator; - private String comparatorClassName; - - private String customLoaderName; - private CustomSQL customSqlInsert; - private CustomSQL customSqlUpdate; - private CustomSQL customSqlDelete; - private CustomSQL customSqlDeleteAll; - - private String referencedPropertyName; - - private final java.util.Map filters = new HashMap(); - private final java.util.Set synchronizedTables = new HashSet(); - - protected AbstractPluralAttributeBinding( - AttributeBindingContainer container, - PluralAttribute attribute, - CollectionElementNature collectionElementNature) { - super( container, attribute ); - this.collectionKey = new CollectionKey( this ); - this.collectionElement = interpretNature( collectionElementNature ); - } - - private AbstractCollectionElement interpretNature(CollectionElementNature collectionElementNature) { - switch ( collectionElementNature ) { - case BASIC: { - return new BasicCollectionElement( this ); - } - case COMPOSITE: { - return new CompositeCollectionElement( this ); - } - case ONE_TO_MANY: { - return new OneToManyCollectionElement( this ); - } - case MANY_TO_MANY: { - return new ManyToManyCollectionElement( this ); - } - case MANY_TO_ANY: { - return new ManyToAnyCollectionElement( this ); - } - default: { - throw new AssertionFailure( "Unknown collection element nature : " + collectionElementNature ); - } - } - } - -// protected void initializeBinding(PluralAttributeBindingState state) { -// super.initialize( state ); -// fetchMode = state.getFetchMode(); -// extraLazy = state.isExtraLazy(); -// collectionElement.setNodeName( state.getElementNodeName() ); -// collectionElement.setTypeName( state.getElementTypeName() ); -// inverse = state.isInverse(); -// mutable = state.isMutable(); -// subselectLoadable = state.isSubselectLoadable(); -// if ( isSubselectLoadable() ) { -// getEntityBinding().setSubselectLoadableCollections( true ); -// } -// cacheConcurrencyStrategy = state.getCacheConcurrencyStrategy(); -// cacheRegionName = state.getCacheRegionName(); -// orderBy = state.getOrderBy(); -// where = state.getWhere(); -// referencedPropertyName = state.getReferencedPropertyName(); -// sorted = state.isSorted(); -// comparator = state.getComparator(); -// comparatorClassName = state.getComparatorClassName(); -// orphanDelete = state.isOrphanDelete(); -// batchSize = state.getBatchSize(); -// embedded = state.isEmbedded(); -// optimisticLocked = state.isOptimisticLocked(); -// collectionPersisterClass = state.getCollectionPersisterClass(); -// filters.putAll( state.getFilters() ); -// synchronizedTables.addAll( state.getSynchronizedTables() ); -// customSQLInsert = state.getCustomSQLInsert(); -// customSQLUpdate = state.getCustomSQLUpdate(); -// customSQLDelete = state.getCustomSQLDelete(); -// customSQLDeleteAll = state.getCustomSQLDeleteAll(); -// loaderName = state.getLoaderName(); -// } - - @Override - public PluralAttribute getAttribute() { - return (PluralAttribute) super.getAttribute(); - } - - @Override - public boolean isAssociation() { - return collectionElement.getCollectionElementNature() == CollectionElementNature.MANY_TO_ANY - || collectionElement.getCollectionElementNature() == CollectionElementNature.MANY_TO_MANY - || collectionElement.getCollectionElementNature() == CollectionElementNature.ONE_TO_MANY; - } - - @Override - public TableSpecification getCollectionTable() { - return collectionTable; - } - - public void setCollectionTable(Table collectionTable) { - this.collectionTable = collectionTable; - } - - @Override - public CollectionKey getCollectionKey() { - return collectionKey; - } - - @Override - public AbstractCollectionElement getCollectionElement() { - return collectionElement; - } - - @Override - public CascadeStyle getCascadeStyle() { - return cascadeStyle; - } - - @Override - public void setCascadeStyles(Iterable cascadeStyles) { - List cascadeStyleList = new ArrayList(); - for ( CascadeStyle style : cascadeStyles ) { - if ( style != CascadeStyles.NONE ) { - cascadeStyleList.add( style ); - } - if ( style == CascadeStyles.DELETE_ORPHAN || - style == CascadeStyles.ALL_DELETE_ORPHAN ) { - orphanDelete = true; - } - } - - if ( cascadeStyleList.isEmpty() ) { - cascadeStyle = CascadeStyles.NONE; - } - else if ( cascadeStyleList.size() == 1 ) { - cascadeStyle = cascadeStyleList.get( 0 ); - } - else { - cascadeStyle = new CascadeStyles.MultipleCascadeStyle( - cascadeStyleList.toArray( new CascadeStyle[ cascadeStyleList.size() ] ) - ); - } - } - - @Override - public boolean isOrphanDelete() { - return orphanDelete; - } - - @Override - public FetchMode getFetchMode() { - if ( getFetchStyle() == FetchStyle.JOIN ) { - return FetchMode.JOIN; - } - else { - return FetchMode.SELECT; - } - } - - @Override - public FetchTiming getFetchTiming() { - return fetchTiming; - } - - @Override - public void setFetchTiming(FetchTiming fetchTiming) { - this.fetchTiming = fetchTiming; - } - - @Override - public FetchStyle getFetchStyle() { - return fetchStyle; - } - - @Override - public void setFetchStyle(FetchStyle fetchStyle) { - this.fetchStyle = fetchStyle; - } - - @Override - public String getCustomLoaderName() { - return customLoaderName; - } - - public void setCustomLoaderName(String customLoaderName) { - this.customLoaderName = customLoaderName; - } - - @Override - public CustomSQL getCustomSqlInsert() { - return customSqlInsert; - } - - public void setCustomSqlInsert(CustomSQL customSqlInsert) { - this.customSqlInsert = customSqlInsert; - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return customSqlUpdate; - } - - public void setCustomSqlUpdate(CustomSQL customSqlUpdate) { - this.customSqlUpdate = customSqlUpdate; - } - - @Override - public CustomSQL getCustomSqlDelete() { - return customSqlDelete; - } - - public void setCustomSqlDelete(CustomSQL customSqlDelete) { - this.customSqlDelete = customSqlDelete; - } - - @Override - public CustomSQL getCustomSqlDeleteAll() { - return customSqlDeleteAll; - } - - public void setCustomSqlDeleteAll(CustomSQL customSqlDeleteAll) { - this.customSqlDeleteAll = customSqlDeleteAll; - } - - public Class getCollectionPersisterClass() { - return collectionPersisterClass; - } - - public void setCollectionPersisterClass(Class collectionPersisterClass) { - this.collectionPersisterClass = collectionPersisterClass; - } - - public Caching getCaching() { - return caching; - } - - public void setCaching(Caching caching) { - this.caching = caching; - } - - @Override - public String getOrderBy() { - return orderBy; - } - - public void setOrderBy(String orderBy) { - this.orderBy = orderBy; - } - - @Override - public String getWhere() { - return where; - } - - public void setWhere(String where) { - this.where = where; - } - - @Override - public boolean isInverse() { - return inverse; - } - - public void setInverse(boolean inverse) { - this.inverse = inverse; - } - - @Override - public boolean isMutable() { - return mutable; - } - - public void setMutable(boolean mutable) { - this.mutable = mutable; - } - - @Override - public int getBatchSize() { - return batchSize; - } - - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - - - - - - - - - - - public String getReferencedPropertyName() { - return referencedPropertyName; - } - - @Override - public boolean isSorted() { - return sorted; - } - - @Override - public Comparator getComparator() { - return comparator; - } - - public void setComparator(Comparator comparator) { - this.comparator = comparator; - } - - public String getComparatorClassName() { - return comparatorClassName; - } - - public void addFilter(String name, String condition) { - filters.put( name, condition ); - } - - @Override - public java.util.Map getFilterMap() { - return filters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java deleted file mode 100644 index ef7fb1fded..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Tuple; -import org.hibernate.metamodel.relational.Value; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractSingularAttributeBinding - extends AbstractAttributeBinding - implements SingularAttributeBinding { - - private Value value; - private List simpleValueBindings = new ArrayList(); - - private boolean hasDerivedValue; - private boolean isNullable = true; - - protected AbstractSingularAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); - } - - @Override - public SingularAttribute getAttribute() { - return (SingularAttribute) super.getAttribute(); - } - - public Value getValue() { - return value; - } - - public void setSimpleValueBindings(Iterable simpleValueBindings) { - List values = new ArrayList(); - for ( SimpleValueBinding simpleValueBinding : simpleValueBindings ) { - this.simpleValueBindings.add( simpleValueBinding ); - values.add( simpleValueBinding.getSimpleValue() ); - this.hasDerivedValue = this.hasDerivedValue || simpleValueBinding.isDerived(); - this.isNullable = this.isNullable && simpleValueBinding.isNullable(); - } - if ( values.size() == 1 ) { - this.value = values.get( 0 ); - } - else { - final Tuple tuple = values.get( 0 ).getTable().createTuple( getRole() ); - for ( SimpleValue value : values ) { - tuple.addValue( value ); - } - this.value = tuple; - } - } - - private String getRole() { - return getContainer().getPathBase() + '.' + getAttribute().getName(); - } - - @Override - public int getSimpleValueSpan() { - checkValueBinding(); - return simpleValueBindings.size(); - } - - protected void checkValueBinding() { - if ( value == null ) { - throw new AssertionFailure( "No values yet bound!" ); - } - } - - @Override - public Iterable getSimpleValueBindings() { - return simpleValueBindings; - } - - @Override - public boolean hasDerivedValue() { - checkValueBinding(); - return hasDerivedValue; - } - - @Override - public boolean isNullable() { - checkValueBinding(); - return isNullable; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java deleted file mode 100644 index 3224be343e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; - -/** - * Contract describing a binding for attributes which model associations. - * - * @author Steve Ebersole - */ -public interface AssociationAttributeBinding extends AttributeBinding { - /** - * Obtain the cascade style in effect for this association. - * - * @return The (potentially aggregated) cascade style. - */ - public CascadeStyle getCascadeStyle(); - - /** - * Set the cascade styles in effect for this association. - * - * @param cascadeStyles The cascade styles. - */ - public void setCascadeStyles(Iterable cascadeStyles); - - public FetchTiming getFetchTiming(); - public void setFetchTiming(FetchTiming fetchTiming); - - public FetchStyle getFetchStyle(); - public void setFetchStyle(FetchStyle fetchStyle); - - - /** - * Temporary. Needed for integration with legacy org.hibernate.mapping configuration of persisters. - * - * @deprecated - */ - @Deprecated - @SuppressWarnings( {"JavaDoc"}) - public FetchMode getFetchMode(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java deleted file mode 100644 index c208c3911c..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * Common contract for {@link EntityBinding} and {@link ComponentAttributeBinding} in so far as they are both - * containers for {@link AttributeBinding} descriptors - * - * @author Steve Ebersole - */ -public interface AttributeBindingContainer { - /** - * Obtain the path base of this container. Intended to help uniquely identify each attribute binding. - * - * @return The path base for this container. - */ - public String getPathBase(); - - /** - * Obtain the underlying domain attribute container. - * - * @return The attribute container - */ - public AttributeContainer getAttributeContainer(); - - /** - * Obtain all attribute bindings - * - * @return All attribute bindings - */ - public Iterable attributeBindings(); - - /** - * Locate a specific attribute binding, by its local name. - * - * @param name The name of the attribute, local to this container. - * - * @return The attribute binding. - */ - public AttributeBinding locateAttributeBinding(String name); - - /** - * Factory method for basic attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for component attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for many-to-one attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for bag attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * @param nature The nature of the collection elements. - * - * @return The attribute binding instance. - */ - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature); - - /** - * Factory method for bag attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * @param nature The nature of the collection elements. - * - * @return The attribute binding instance. - */ - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature); - - /** - * Seeks out the entity binding that is the root of this component path. - * - * @return The entity binding - */ - public EntityBinding seekEntityBinding(); - - /** - * Obtain the {@link Class} reference for this attribute container. Generally this is used to perform reflection - * on the attributes. - * - * @return The {@link Class} reference - */ - public Class getClassReference(); - - /** - * Obtain the meta-attribute context for this container. - * - * @return The meta-attribute context. - */ - public MetaAttributeContext getMetaAttributeContext(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java deleted file mode 100644 index c867c7b494..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Properties; - -import org.hibernate.MappingException; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class BasicAttributeBinding - extends AbstractSingularAttributeBinding - implements KeyValueBinding { - - private String unsavedValue; - private PropertyGeneration generation; - private boolean includedInOptimisticLocking; - - private boolean forceNonNullable; - private boolean forceUnique; - private boolean keyCascadeDeleteEnabled; - - private MetaAttributeContext metaAttributeContext; - - BasicAttributeBinding( - AttributeBindingContainer container, - SingularAttribute attribute, - boolean forceNonNullable, - boolean forceUnique) { - super( container, attribute ); - this.forceNonNullable = forceNonNullable; - this.forceUnique = forceUnique; - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public String getUnsavedValue() { - return unsavedValue; - } - - public void setUnsavedValue(String unsavedValue) { - this.unsavedValue = unsavedValue; - } - - @Override - public PropertyGeneration getGeneration() { - return generation; - } - - public void setGeneration(PropertyGeneration generation) { - this.generation = generation; - } - - public boolean isIncludedInOptimisticLocking() { - return includedInOptimisticLocking; - } - - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - - @Override - public boolean isKeyCascadeDeleteEnabled() { - return keyCascadeDeleteEnabled; - } - - public void setKeyCascadeDeleteEnabled(boolean keyCascadeDeleteEnabled) { - this.keyCascadeDeleteEnabled = keyCascadeDeleteEnabled; - } - - public boolean forceNonNullable() { - return forceNonNullable; - } - - public boolean forceUnique() { - return forceUnique; - } - - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - IdentifierGenerator createIdentifierGenerator( - IdGenerator idGenerator, - IdentifierGeneratorFactory identifierGeneratorFactory, - Properties properties) { - Properties params = new Properties(); - params.putAll( properties ); - - // use the schema/catalog specified by getValue().getTable() - but note that - // if the schema/catalog were specified as params, they will already be initialized and - //will override the values set here (they are in idGenerator.getParameters().) - Schema schema = getValue().getTable().getSchema(); - if ( schema != null ) { - if ( schema.getName().getSchema() != null ) { - params.setProperty( PersistentIdentifierGenerator.SCHEMA, schema.getName().getSchema().getName() ); - } - if ( schema.getName().getCatalog() != null ) { - params.setProperty( PersistentIdentifierGenerator.CATALOG, schema.getName().getCatalog().getName() ); - } - } - - // TODO: not sure how this works for collection IDs... - //pass the entity-name, if not a collection-id - //if ( rootClass!=null) { - params.setProperty( IdentifierGenerator.ENTITY_NAME, getContainer().seekEntityBinding().getEntity().getName() ); - //} - - //init the table here instead of earlier, so that we can get a quoted table name - //TODO: would it be better to simply pass the qualified table name, instead of - // splitting it up into schema/catalog/table names - String tableName = getValue().getTable().getQualifiedName( identifierGeneratorFactory.getDialect() ); - params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); - - //pass the column name (a generated id almost always has a single column) - if ( getSimpleValueSpan() > 1 ) { - throw new MappingException( - "A SimpleAttributeBinding used for an identifier has more than 1 Value: " + getAttribute().getName() - ); - } - SimpleValue simpleValue = (SimpleValue) getValue(); - if ( !Column.class.isInstance( simpleValue ) ) { - throw new MappingException( - "Cannot create an IdentifierGenerator because the value is not a column: " + - simpleValue.toLoggableString() - ); - } - params.setProperty( - PersistentIdentifierGenerator.PK, - ( (Column) simpleValue ).getColumnName().encloseInQuotesIfQuoted( - identifierGeneratorFactory.getDialect() - ) - ); - - // TODO: is this stuff necessary for SimpleValue??? - //if (rootClass!=null) { - // StringBuffer tables = new StringBuffer(); - // Iterator iter = rootClass.getIdentityTables().iterator(); - // while ( iter.hasNext() ) { - // Table table= (Table) iter.next(); - // tables.append( table.getQuotedName(dialect) ); - // if ( iter.hasNext() ) tables.append(", "); - // } - // params.setProperty( PersistentIdentifierGenerator.TABLES, tables.toString() ); - //} - //else { - params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); - //} - - params.putAll( idGenerator.getParameters() ); - - return identifierGeneratorFactory.createIdentifierGenerator( - idGenerator.getStrategy(), getHibernateTypeDescriptor().getResolvedTypeMapping(), params - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java deleted file mode 100644 index 81661e8e23..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.relational.ForeignKey; -import org.hibernate.metamodel.relational.TableSpecification; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class CollectionKey { - private final AbstractPluralAttributeBinding pluralAttributeBinding; - - private ForeignKey foreignKey; - private boolean inverse; - private HibernateTypeDescriptor hibernateTypeDescriptor; - -// todo : this would be nice to have but we do not always know it, especially in HBM case. -// private BasicAttributeBinding otherSide; - - public CollectionKey(AbstractPluralAttributeBinding pluralAttributeBinding) { - this.pluralAttributeBinding = pluralAttributeBinding; - } - - public AbstractPluralAttributeBinding getPluralAttributeBinding() { - return pluralAttributeBinding; - } - - public void prepareForeignKey(String foreignKeyName, String targetTableName) { - if ( foreignKey != null ) { - throw new AssertionFailure( "Foreign key already initialized" ); - } - final TableSpecification collectionTable = pluralAttributeBinding.getCollectionTable(); - if ( collectionTable == null ) { - throw new AssertionFailure( "Collection table not yet bound" ); - } - - final TableSpecification targetTable = pluralAttributeBinding.getContainer() - .seekEntityBinding() - .locateTable( targetTableName ); - - // todo : handle implicit fk names... - - foreignKey = collectionTable.createForeignKey( targetTable, foreignKeyName ); - } - - public ForeignKey getForeignKey() { - return foreignKey; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java deleted file mode 100644 index b64b79eabe..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.Component; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * @author Steve Ebersole - */ -public class ComponentAttributeBinding extends AbstractSingularAttributeBinding implements AttributeBindingContainer { - private final String path; - private Map attributeBindingMap = new HashMap(); - private SingularAttribute parentReference; - private MetaAttributeContext metaAttributeContext; - - public ComponentAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); - this.path = container.getPathBase() + '.' + attribute.getName(); - } - - @Override - public EntityBinding seekEntityBinding() { - return getContainer().seekEntityBinding(); - } - - @Override - public String getPathBase() { - return path; - } - - @Override - public AttributeContainer getAttributeContainer() { - return getComponent(); - } - - public Component getComponent() { - return (Component) getAttribute().getSingularAttributeType(); - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - @Override - public AttributeBinding locateAttributeBinding(String name) { - return attributeBindingMap.get( name ); - } - - @Override - public Iterable attributeBindings() { - return attributeBindingMap.values(); - } - - @Override - protected void checkValueBinding() { - // do nothing here... - } - - @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { - final BasicAttributeBinding binding = new BasicAttributeBinding( - this, - attribute, - isNullable(), - isAlternateUniqueKey() // todo : is this accurate? - ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - protected void registerAttributeBinding(String name, AttributeBinding attributeBinding) { - // todo : hook this into the EntityBinding notion of "entity referencing attribute bindings" - attributeBindingMap.put( name, attributeBinding ); - } - - @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public Class getClassReference() { - return getComponent().getClassReference(); - } - - public SingularAttribute getParentReference() { - return parentReference; - } - - public void setParentReference(SingularAttribute parentReference) { - this.parentReference = parentReference; - } - - @Override - public PropertyGeneration getGeneration() { - // todo : not sure the correct thing to return here since it essentially relies on the simple sub-attributes. - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java deleted file mode 100644 index 967e2a627a..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.internal.util.collections.JoinedIterable; -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.tuple.entity.EntityTuplizer; - -/** - * Provides the link between the domain and the relational model for an entity. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - * @author Gail Badner - */ -public class EntityBinding implements AttributeBindingContainer { - private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null"; - private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null"; - - private final EntityBinding superEntityBinding; - private final List subEntityBindings = new ArrayList(); - private final HierarchyDetails hierarchyDetails; - - private Entity entity; - private TableSpecification primaryTable; - private String primaryTableName; - private Map secondaryTables = new HashMap(); - - private ValueHolder> proxyInterfaceType; - - private String jpaEntityName; - - private Class customEntityPersisterClass; - private Class customEntityTuplizerClass; - - private String discriminatorMatchValue; - - private Set filterDefinitions = new HashSet(); - private Set entityReferencingAttributeBindings = new HashSet(); - - private MetaAttributeContext metaAttributeContext; - - private boolean lazy; - private boolean mutable; - private String whereFilter; - private String rowId; - - private boolean dynamicUpdate; - private boolean dynamicInsert; - - private int batchSize; - private boolean selectBeforeUpdate; - private boolean hasSubselectLoadableCollections; - - private Boolean isAbstract; - - private String customLoaderName; - private CustomSQL customInsert; - private CustomSQL customUpdate; - private CustomSQL customDelete; - - private Set synchronizedTableNames = new HashSet(); - private Map attributeBindingMap = new HashMap(); - - private List jpaCallbackClasses = new ArrayList(); - - /** - * Used to instantiate the EntityBinding for an entity that is the root of an inheritance hierarchy - * - * @param inheritanceType The inheritance type for the hierarchy - * @param entityMode The entity mode used in this hierarchy. - */ - public EntityBinding(InheritanceType inheritanceType, EntityMode entityMode) { - this.superEntityBinding = null; - this.hierarchyDetails = new HierarchyDetails( this, inheritanceType, entityMode ); - } - - /** - * Used to instantiate the EntityBinding for an entity that is a subclass (sub-entity) in an inheritance hierarchy - * - * @param superEntityBinding The entity binding of this binding's super - */ - public EntityBinding(EntityBinding superEntityBinding) { - this.superEntityBinding = superEntityBinding; - this.superEntityBinding.subEntityBindings.add( this ); - this.hierarchyDetails = superEntityBinding.getHierarchyDetails(); - } - - public HierarchyDetails getHierarchyDetails() { - return hierarchyDetails; - } - - public EntityBinding getSuperEntityBinding() { - return superEntityBinding; - } - - public boolean isRoot() { - return superEntityBinding == null; - } - - public boolean isPolymorphic() { - return superEntityBinding != null || - hierarchyDetails.getEntityDiscriminator() != null || - ! subEntityBindings.isEmpty(); - } - - public boolean hasSubEntityBindings() { - return subEntityBindings.size() > 0; - } - - public int getSubEntityBindingClosureSpan() { - int n = subEntityBindings.size(); - for ( EntityBinding subEntityBinding : subEntityBindings ) { - n += subEntityBinding.getSubEntityBindingClosureSpan(); - } - return n; - } - - /* used for testing */ - public Iterable getDirectSubEntityBindings() { - return subEntityBindings; - } - - /** - * Returns sub-EntityBinding objects in a special 'order', most derived subclasses - * first. Specifically, the sub-entity bindings follow a depth-first, - * post-order traversal - * - * Note that the returned value excludes this entity binding. - * - * @return sub-entity bindings ordered by those entity bindings that are most derived. - */ - public Iterable getPostOrderSubEntityBindingClosure() { - // TODO: why this order? - List> subclassIterables = new ArrayList>( subEntityBindings.size() + 1 ); - for ( EntityBinding subEntityBinding : subEntityBindings ) { - Iterable subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure(); - if ( subSubEntityBindings.iterator().hasNext() ) { - subclassIterables.add( subSubEntityBindings ); - } - } - if ( ! subEntityBindings.isEmpty() ) { - subclassIterables.add( subEntityBindings ); - } - return new JoinedIterable( subclassIterables ); - } - - /** - * Returns sub-EntityBinding ordered as a depth-first, - * pre-order traversal (a subclass precedes its own subclasses). - * - * Note that the returned value specifically excludes this entity binding. - * - * @return sub-entity bindings ordered as a depth-first, - * pre-order traversal - */ - public Iterable getPreOrderSubEntityBindingClosure() { - return getPreOrderSubEntityBindingClosure( false ); - } - - private Iterable getPreOrderSubEntityBindingClosure(boolean includeThis) { - List> iterables = new ArrayList>(); - if ( includeThis ) { - iterables.add( java.util.Collections.singletonList( this ) ); - } - for ( EntityBinding subEntityBinding : subEntityBindings ) { - Iterable subSubEntityBindingClosure = subEntityBinding.getPreOrderSubEntityBindingClosure( true ); - if ( subSubEntityBindingClosure.iterator().hasNext() ) { - iterables.add( subSubEntityBindingClosure ); - } - } - return new JoinedIterable( iterables ); - } - - public Entity getEntity() { - return entity; - } - - public void setEntity(Entity entity) { - this.entity = entity; - } - - public TableSpecification getPrimaryTable() { - return primaryTable; - } - - public void setPrimaryTable(TableSpecification primaryTable) { - this.primaryTable = primaryTable; - } - - public TableSpecification locateTable(String tableName) { - if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) { - return primaryTable; - } - TableSpecification tableSpec = secondaryTables.get( tableName ); - if ( tableSpec == null ) { - throw new AssertionFailure( - String.format( - "Unable to find table %s amongst tables %s", - tableName, - secondaryTables.keySet() - ) - ); - } - return tableSpec; - } - public String getPrimaryTableName() { - return primaryTableName; - } - - public void setPrimaryTableName(String primaryTableName) { - this.primaryTableName = primaryTableName; - } - - public void addSecondaryTable(String tableName, TableSpecification table) { - secondaryTables.put( tableName, table ); - } - - public boolean isVersioned() { - return getHierarchyDetails().getVersioningAttributeBinding() != null; - } - - public boolean isDiscriminatorMatchValueNull() { - return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); - } - - public boolean isDiscriminatorMatchValueNotNull() { - return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); - } - - public String getDiscriminatorMatchValue() { - return discriminatorMatchValue; - } - - public void setDiscriminatorMatchValue(String discriminatorMatchValue) { - this.discriminatorMatchValue = discriminatorMatchValue; - } - - public Iterable getFilterDefinitions() { - return filterDefinitions; - } - - public void addFilterDefinition(FilterDefinition filterDefinition) { - filterDefinitions.add( filterDefinition ); - } - - public Iterable getEntityReferencingAttributeBindings() { - return entityReferencingAttributeBindings; - } - - @Override - public EntityBinding seekEntityBinding() { - return this; - } - - @Override - public String getPathBase() { - return getEntity().getName(); - } - - @Override - public Class getClassReference() { - return getEntity().getClassReference(); - } - - @Override - public AttributeContainer getAttributeContainer() { - return getEntity(); - } - - protected void registerAttributeBinding(String name, AttributeBinding attributeBinding) { - if ( SingularAssociationAttributeBinding.class.isInstance( attributeBinding ) ) { - entityReferencingAttributeBindings.add( (SingularAssociationAttributeBinding) attributeBinding ); - } - attributeBindingMap.put( name, attributeBinding ); - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - public boolean isMutable() { - return mutable; - } - - public void setMutable(boolean mutable) { - this.mutable = mutable; - } - - public boolean isLazy() { - return lazy; - } - - public void setLazy(boolean lazy) { - this.lazy = lazy; - } - - public ValueHolder> getProxyInterfaceType() { - return proxyInterfaceType; - } - - public void setProxyInterfaceType(ValueHolder> proxyInterfaceType) { - this.proxyInterfaceType = proxyInterfaceType; - } - - public String getWhereFilter() { - return whereFilter; - } - - public void setWhereFilter(String whereFilter) { - this.whereFilter = whereFilter; - } - - public String getRowId() { - return rowId; - } - - public void setRowId(String rowId) { - this.rowId = rowId; - } - - public boolean isDynamicUpdate() { - return dynamicUpdate; - } - - public void setDynamicUpdate(boolean dynamicUpdate) { - this.dynamicUpdate = dynamicUpdate; - } - - public boolean isDynamicInsert() { - return dynamicInsert; - } - - public void setDynamicInsert(boolean dynamicInsert) { - this.dynamicInsert = dynamicInsert; - } - - public int getBatchSize() { - return batchSize; - } - - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - public boolean isSelectBeforeUpdate() { - return selectBeforeUpdate; - } - - public void setSelectBeforeUpdate(boolean selectBeforeUpdate) { - this.selectBeforeUpdate = selectBeforeUpdate; - } - - public boolean hasSubselectLoadableCollections() { - return hasSubselectLoadableCollections; - } - - /* package-protected */ - void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) { - this.hasSubselectLoadableCollections = hasSubselectLoadableCollections; - } - - public Class getCustomEntityPersisterClass() { - return customEntityPersisterClass; - } - - public void setCustomEntityPersisterClass(Class customEntityPersisterClass) { - this.customEntityPersisterClass = customEntityPersisterClass; - } - - public Class getCustomEntityTuplizerClass() { - return customEntityTuplizerClass; - } - - public void setCustomEntityTuplizerClass(Class customEntityTuplizerClass) { - this.customEntityTuplizerClass = customEntityTuplizerClass; - } - - public Boolean isAbstract() { - return isAbstract; - } - - public void setAbstract(Boolean isAbstract) { - this.isAbstract = isAbstract; - } - - public Set getSynchronizedTableNames() { - return synchronizedTableNames; - } - - public void addSynchronizedTableNames(java.util.Collection synchronizedTableNames) { - this.synchronizedTableNames.addAll( synchronizedTableNames ); - } - - public String getJpaEntityName() { - return jpaEntityName; - } - - public void setJpaEntityName(String jpaEntityName) { - this.jpaEntityName = jpaEntityName; - } - - public String getCustomLoaderName() { - return customLoaderName; - } - - public void setCustomLoaderName(String customLoaderName) { - this.customLoaderName = customLoaderName; - } - - public CustomSQL getCustomInsert() { - return customInsert; - } - - public void setCustomInsert(CustomSQL customInsert) { - this.customInsert = customInsert; - } - - public CustomSQL getCustomUpdate() { - return customUpdate; - } - - public void setCustomUpdate(CustomSQL customUpdate) { - this.customUpdate = customUpdate; - } - - public CustomSQL getCustomDelete() { - return customDelete; - } - - public void setCustomDelete(CustomSQL customDelete) { - this.customDelete = customDelete; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "EntityBinding" ); - sb.append( "{entity=" ).append( entity != null ? entity.getName() : "not set" ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { - return makeSimpleAttributeBinding( attribute, false, false ); - } - - private BasicAttributeBinding makeSimpleAttributeBinding(SingularAttribute attribute, boolean forceNonNullable, boolean forceUnique) { - final BasicAttributeBinding binding = new BasicAttributeBinding( - this, - attribute, - forceNonNullable, - forceUnique - ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public AttributeBinding locateAttributeBinding(String name) { - return attributeBindingMap.get( name ); - } - - @Override - public Iterable attributeBindings() { - return attributeBindingMap.values(); - } - - /** - * Gets the number of attribute bindings defined on this class, including the - * identifier attribute binding and attribute bindings defined - * as part of a join. - * - * @return The number of attribute bindings - */ - public int getAttributeBindingClosureSpan() { - // TODO: update account for join attribute bindings - return superEntityBinding != null ? - superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() : - attributeBindingMap.size(); - } - - /** - * Gets the attribute bindings defined on this class, including the - * identifier attribute binding and attribute bindings defined - * as part of a join. - * - * @return The attribute bindings. - */ - public Iterable getAttributeBindingClosure() { - // TODO: update size to account for joins - Iterable iterable; - if ( superEntityBinding != null ) { - List> iterables = new ArrayList>( 2 ); - iterables.add( superEntityBinding.getAttributeBindingClosure() ); - iterables.add( attributeBindings() ); - iterable = new JoinedIterable( iterables ); - } - else { - iterable = attributeBindings(); - } - return iterable; - } - - /** - * Gets the attribute bindings for this EntityBinding and all of its - * sub-EntityBinding, starting from the root of the hierarchy; includes - * the identifier and attribute bindings defined as part of a join. - * @return - */ - public Iterable getSubEntityAttributeBindingClosure() { - List> iterables = new ArrayList>(); - iterables.add( getAttributeBindingClosure() ); - for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { - // only add attribute bindings declared for the subEntityBinding - iterables.add( subEntityBinding.attributeBindings() ); - // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here - } - return new JoinedIterable( iterables ); - } - - public void setJpaCallbackClasses( List jpaCallbackClasses ) { - this.jpaCallbackClasses = jpaCallbackClasses; - } - - public Iterable getJpaCallbackClasses() { - return jpaCallbackClasses; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java deleted file mode 100644 index fba5b3c6c4..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Properties; - -import org.hibernate.AssertionFailure; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; - -/** - * Binds the entity identifier. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class EntityIdentifier { - private final EntityBinding entityBinding; - private BasicAttributeBinding attributeBinding; - private IdentifierGenerator identifierGenerator; - private IdGenerator idGenerator; - private boolean isIdentifierMapper = false; - // todo : mappers, etc - - /** - * Create an identifier - * - * @param entityBinding the entity binding for which this instance is the id - */ - public EntityIdentifier(EntityBinding entityBinding) { - this.entityBinding = entityBinding; - } - - public BasicAttributeBinding getValueBinding() { - return attributeBinding; - } - - public void setValueBinding(BasicAttributeBinding attributeBinding) { - if ( this.attributeBinding != null ) { - throw new AssertionFailure( - String.format( - "Identifier value binding already existed for %s", - entityBinding.getEntity().getName() - ) - ); - } - this.attributeBinding = attributeBinding; - } - - public void setIdGenerator(IdGenerator idGenerator) { - this.idGenerator = idGenerator; - } - - public boolean isEmbedded() { - return attributeBinding.getSimpleValueSpan() > 1; - } - - public boolean isIdentifierMapper() { - return isIdentifierMapper; - } - - // todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early - // maybe some sort of visitor pattern here!? (HF) - public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) { - if ( idGenerator != null ) { - identifierGenerator = attributeBinding.createIdentifierGenerator( idGenerator, factory, properties ); - } - return identifierGenerator; - } - - public IdentifierGenerator getIdentifierGenerator() { - return identifierGenerator; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java deleted file mode 100644 index 007b3b305a..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; - -import org.hibernate.internal.util.collections.CollectionHelper; - -/** - * Identifier generator container, Useful to keep named generator in annotations - * - * @author Emmanuel Bernard - */ -public class IdGenerator implements Serializable { - private final String name; - private final String strategy; - private final Map parameters; - - public IdGenerator( String name, - String strategy, - Map parameters ) { - this.name = name; - this.strategy = strategy; - if ( CollectionHelper.isEmpty( parameters ) ) { - this.parameters = Collections.emptyMap(); - } - else { - this.parameters = Collections.unmodifiableMap( parameters ); - } - } - - /** - * @return identifier generator strategy - */ - public String getStrategy() { - return strategy; - } - - /** - * @return generator name - */ - public String getName() { - return name; - } - - /** - * @return generator configuration parameters - */ - public Map getParameters() { - return parameters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java deleted file mode 100644 index ee5b93464a..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.HashMap; - -import org.dom4j.Element; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class ManyToManyCollectionElement extends AbstractCollectionElement { - - private final java.util.Map manyToManyFilters = new HashMap(); - private String manyToManyWhere; - private String manyToManyOrderBy; - - - ManyToManyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.MANY_TO_MANY; - } - - public void fromHbmXml(Element node){ - /* - - - - - - - - - - - - - - - - - */ - } - - public String getManyToManyWhere() { - return manyToManyWhere; - } - - public void setManyToManyWhere(String manyToManyWhere) { - this.manyToManyWhere = manyToManyWhere; - } - - public String getManyToManyOrderBy() { - return manyToManyOrderBy; - } - - public void setManyToManyOrderBy(String manyToManyOrderBy) { - this.manyToManyOrderBy = manyToManyOrderBy; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java deleted file mode 100644 index 66a9f5376b..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.metamodel.domain.SingularAttribute; - -/** - * TODO : javadoc - * - * @author Gail Badner - * @author Steve Ebersole - */ -public class ManyToOneAttributeBinding extends BasicAttributeBinding implements SingularAssociationAttributeBinding { - private String referencedEntityName; - private String referencedAttributeName; - private AttributeBinding referencedAttributeBinding; - - private boolean isLogicalOneToOne; - private String foreignKeyName; - - private CascadeStyle cascadeStyle; - private FetchTiming fetchTiming; - private FetchStyle fetchStyle; - - ManyToOneAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute, false, false ); - } - - @Override - public boolean isAssociation() { - return true; - } - - @Override - public final boolean isPropertyReference() { - return referencedAttributeName != null; - } - - @Override - public final String getReferencedEntityName() { - return referencedEntityName; - } - - @Override - public void setReferencedEntityName(String referencedEntityName) { - this.referencedEntityName = referencedEntityName; - } - - @Override - public final String getReferencedAttributeName() { - return referencedAttributeName; - } - - @Override - public void setReferencedAttributeName(String referencedEntityAttributeName) { - this.referencedAttributeName = referencedEntityAttributeName; - } - - @Override - public CascadeStyle getCascadeStyle() { - return cascadeStyle; - } - - @Override - public void setCascadeStyles(Iterable cascadeStyles) { - List cascadeStyleList = new ArrayList(); - for ( CascadeStyle style : cascadeStyles ) { - if ( style != CascadeStyles.NONE ) { - cascadeStyleList.add( style ); - } - } - if ( cascadeStyleList.isEmpty() ) { - cascadeStyle = CascadeStyles.NONE; - } - else if ( cascadeStyleList.size() == 1 ) { - cascadeStyle = cascadeStyleList.get( 0 ); - } - else { - cascadeStyle = new CascadeStyles.MultipleCascadeStyle( - cascadeStyleList.toArray( new CascadeStyle[ cascadeStyleList.size() ] ) - ); - } - } - - @Override - public FetchTiming getFetchTiming() { - return fetchTiming; - } - - @Override - public void setFetchTiming(FetchTiming fetchTiming) { - this.fetchTiming = fetchTiming; - } - - @Override - public FetchStyle getFetchStyle() { - return fetchStyle; - } - - @Override - public void setFetchStyle(FetchStyle fetchStyle) { - if ( fetchStyle == FetchStyle.SUBSELECT ) { - throw new AssertionFailure( "Subselect fetching not yet supported for singular associations" ); - } - this.fetchStyle = fetchStyle; - } - - @Override - public FetchMode getFetchMode() { - if ( fetchStyle == FetchStyle.JOIN ) { - return FetchMode.JOIN; - } - else if ( fetchStyle == FetchStyle.SELECT ) { - return FetchMode.SELECT; - } - else if ( fetchStyle == FetchStyle.BATCH ) { - // we need the subsequent select... - return FetchMode.SELECT; - } - - throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() ); - } - - @Override - public final boolean isReferenceResolved() { - return referencedAttributeBinding != null; - } - - @Override - public final void resolveReference(AttributeBinding referencedAttributeBinding) { - if ( ! EntityBinding.class.isInstance( referencedAttributeBinding.getContainer() ) ) { - throw new AssertionFailure( "Illegal attempt to resolve many-to-one reference based on non-entity attribute" ); - } - final EntityBinding entityBinding = (EntityBinding) referencedAttributeBinding.getContainer(); - if ( !referencedEntityName.equals( entityBinding.getEntity().getName() ) ) { - throw new IllegalStateException( - "attempt to set EntityBinding with name: [" + - entityBinding.getEntity().getName() + - "; entity name should be: " + referencedEntityName - ); - } - if ( referencedAttributeName == null ) { - referencedAttributeName = referencedAttributeBinding.getAttribute().getName(); - } - else if ( !referencedAttributeName.equals( referencedAttributeBinding.getAttribute().getName() ) ) { - throw new IllegalStateException( - "Inconsistent attribute name; expected: " + referencedAttributeName + - "actual: " + referencedAttributeBinding.getAttribute().getName() - ); - } - this.referencedAttributeBinding = referencedAttributeBinding; -// buildForeignKey(); - } - - @Override - public AttributeBinding getReferencedAttributeBinding() { - if ( !isReferenceResolved() ) { - throw new IllegalStateException( "Referenced AttributeBiding has not been resolved." ); - } - return referencedAttributeBinding; - } - - @Override - public final EntityBinding getReferencedEntityBinding() { - return (EntityBinding) referencedAttributeBinding.getContainer(); - } - -// private void buildForeignKey() { -// // TODO: move this stuff to relational model -// ForeignKey foreignKey = getValue().getTable() -// .createForeignKey( referencedAttributeBinding.getValue().getTable(), foreignKeyName ); -// Iterator referencingValueIterator = getSimpleValues().iterator(); -// Iterator targetValueIterator = referencedAttributeBinding.getSimpleValues().iterator(); -// while ( referencingValueIterator.hasNext() ) { -// if ( !targetValueIterator.hasNext() ) { -// // TODO: improve this message -// throw new MappingException( -// "number of values in many-to-one reference is greater than number of values in target" -// ); -// } -// SimpleValue referencingValue = referencingValueIterator.next(); -// SimpleValue targetValue = targetValueIterator.next(); -// if ( Column.class.isInstance( referencingValue ) ) { -// if ( !Column.class.isInstance( targetValue ) ) { -// // TODO improve this message -// throw new MappingException( "referencing value is a column, but target is not a column" ); -// } -// foreignKey.addColumnMapping( Column.class.cast( referencingValue ), Column.class.cast( targetValue ) ); -// } -// else if ( Column.class.isInstance( targetValue ) ) { -// // TODO: improve this message -// throw new MappingException( "referencing value is not a column, but target is a column." ); -// } -// } -// if ( targetValueIterator.hasNext() ) { -// throw new MappingException( "target value has more simple values than referencing value" ); -// } -// } -// -// public void validate() { -// // can't check this until both the domain and relational states are initialized... -// if ( getCascadeTypes().contains( CascadeType.DELETE_ORPHAN ) ) { -// if ( !isLogicalOneToOne ) { -// throw new MappingException( -// "many-to-one attribute [" + locateAttribute().getName() + "] does not support orphan delete as it is not unique" -// ); -// } -// } -// //TODO: validate that the entity reference is resolved -// } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java deleted file mode 100644 index 0a8dd1afc3..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; - -/** - * @author Steve Ebersole - */ -public class SimpleValueBinding { - private SimpleValue simpleValue; - private boolean includeInInsert; - private boolean includeInUpdate; - - public SimpleValueBinding() { - this( true, true ); - } - - public SimpleValueBinding(SimpleValue simpleValue) { - this(); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(SimpleValue simpleValue, boolean includeInInsert, boolean includeInUpdate) { - this( includeInInsert, includeInUpdate ); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(boolean includeInInsert, boolean includeInUpdate) { - this.includeInInsert = includeInInsert; - this.includeInUpdate = includeInUpdate; - } - - public SimpleValue getSimpleValue() { - return simpleValue; - } - - public void setSimpleValue(SimpleValue simpleValue) { - this.simpleValue = simpleValue; - if ( DerivedValue.class.isInstance( simpleValue ) ) { - includeInInsert = false; - includeInUpdate = false; - } - } - - public boolean isDerived() { - return DerivedValue.class.isInstance( simpleValue ); - } - - public boolean isNullable() { - return isDerived() || Column.class.cast( simpleValue ).isNullable(); - } - - /** - * Is the value to be inserted as part of its binding here? - *

          - * NOTE that a column may be bound to multiple attributes. The purpose of this value is to track this - * notion of "insertability" for this particular binding. - * - * @return {@code true} indicates the value should be included; {@code false} indicates it should not - */ - public boolean isIncludeInInsert() { - return includeInInsert; - } - - public void setIncludeInInsert(boolean includeInInsert) { - this.includeInInsert = includeInInsert; - } - - public boolean isIncludeInUpdate() { - return includeInUpdate; - } - - public void setIncludeInUpdate(boolean includeInUpdate) { - this.includeInUpdate = includeInUpdate; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java deleted file mode 100644 index 6baf951010..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.relational.Value; - -/** - * Specialized binding contract for singular (non-collection) attributes - * - * @author Steve Ebersole - */ -public interface SingularAttributeBinding extends AttributeBinding { - /** - * Obtain the value bound here. This could potentially be a {@link org.hibernate.metamodel.relational.Tuple} - * indicating multiple database values are bound, in which case access to the individual values can be achieved by - * either casting this return to {@link org.hibernate.metamodel.relational.Tuple} and using its - * {@link org.hibernate.metamodel.relational.Tuple#values()} method or using the {@link #getSimpleValueBindings()} - * method here and accessing each bindings {@link SimpleValueBinding#getSimpleValue simple value} - * - * @return The bound value - */ - public Value getValue(); - - /** - * Returns the number of {@link SimpleValueBinding} objects that will be returned by - * {@link #getSimpleValueBindings()} - * - * @return the number of {@link SimpleValueBinding simple value bindings} - * - * @see #getSimpleValueBindings() - */ - public int getSimpleValueSpan(); - - public Iterable getSimpleValueBindings(); - - public void setSimpleValueBindings(Iterable simpleValueBindings); - - /** - * Convenience method to determine if any {@link SimpleValueBinding simple value bindings} are derived values - * (formula mappings). - * - * @return {@code true} indicates that the binding contains a derived value; {@code false} indicates it does not. - */ - public boolean hasDerivedValue(); - - /** - * Convenience method to determine if all {@link SimpleValueBinding simple value bindings} allow nulls. - * - * @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not - */ - public boolean isNullable(); - - /** - * Obtain the generation strategy for this attribute/value. - * - * @return The generation strategy - */ - public PropertyGeneration getGeneration(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java new file mode 100644 index 0000000000..8a9c2908ea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -0,0 +1,3078 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.FetchMode; +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.IdentityGenerator; +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.enhanced.TableGenerator; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.EntityHierarchyHelper.LocalBindingContextExecutionContext; +import org.hibernate.metamodel.internal.EntityHierarchyHelper.LocalBindingContextExecutor; +import org.hibernate.metamodel.internal.HibernateTypeHelper.ReflectedCollectionJavaTypes; +import org.hibernate.metamodel.internal.resolver.AssociationRelationalBindingResolver; +import org.hibernate.metamodel.internal.resolver.MappedByAssociationRelationalBindingResolverImpl; +import org.hibernate.metamodel.internal.resolver.StandardAssociationRelationalBindingResolverImpl; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.BasicPluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.EntityVersion; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.ManyToManyPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.MetaAttribute; +import org.hibernate.metamodel.spi.binding.OneToManyPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SetBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.ConstraintSource; +import org.hibernate.metamodel.spi.source.DerivedValueSource; +import org.hibernate.metamodel.spi.source.DiscriminatorSource; +import org.hibernate.metamodel.spi.source.EntityAttributePluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.IndexConstraintSource; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.JoinedSubclassEntitySource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.MultiTenancySource; +import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.Orderable; +import org.hibernate.metamodel.spi.source.PluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SecondaryTableSource; +import org.hibernate.metamodel.spi.source.SequentialPluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.Sortable; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.hibernate.metamodel.spi.source.UniqueConstraintSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.component.ComponentMetamodel; +import org.hibernate.tuple.component.ComponentTuplizer; +import org.hibernate.tuple.entity.EntityTuplizer; +import org.hibernate.type.ForeignKeyDirection; +import org.hibernate.type.Type; +import org.jboss.logging.Logger; + +/** + * The common binder shared between annotations and {@code hbm.xml} processing. + *

          + * The API consists of {@link #Binder(org.hibernate.metamodel.spi.MetadataImplementor, IdentifierGeneratorFactory)} and {@link #bindEntityHierarchies} + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + * @author Brett Meyer + * @author Strong Liu + */ +public class Binder implements HelperContext { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + Binder.class.getName() + ); + + private final IdentifierGeneratorFactory identifierGeneratorFactory; + + // Entity hierarchies and source index need be available throughout the binding process + private final Map entityHierarchiesByRootEntityName = + new LinkedHashMap(); + private final SourceIndex sourceIndex = new SourceIndex(); + + // todo : apply org.hibernate.metamodel.MetadataSources.getExternalCacheRegionDefinitions() + + private final MetadataImplementor metadata; + + private final EntityHierarchyHelper.LocalBindingContextManager localBindingContextManager; + + private final EntityHierarchyHelper entityHierarchyHelper; + private final HibernateTypeHelper typeHelper; // todo: refactor helper and remove redundant methods in this class + private final RelationalIdentifierHelper relationalIdentifierHelper; + private final TableHelper tableHelper; + private final ForeignKeyHelper foreignKeyHelper; + private final RelationalValueBindingHelper relationalValueBindingHelper; + private final NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper; + + private final StandardAssociationRelationalBindingResolverImpl standardAssociationRelationalBindingResolver; + private final MappedByAssociationRelationalBindingResolverImpl mappedByAssociationRelationalBindingResolver; + + public Binder(final MetadataImplementor metadata, + final IdentifierGeneratorFactory identifierGeneratorFactory) { + this.metadata = metadata; + this.identifierGeneratorFactory = identifierGeneratorFactory; + this.localBindingContextManager = new LocalBindingContextManagerImpl(); + this.entityHierarchyHelper = new EntityHierarchyHelper( localBindingContextManager ); + this.typeHelper = new HibernateTypeHelper( this ); + this.relationalIdentifierHelper = new RelationalIdentifierHelper( this ); + this.tableHelper = new TableHelper( this ); + this.foreignKeyHelper = new ForeignKeyHelper( this ); + this.relationalValueBindingHelper = new RelationalValueBindingHelper( this ); + this.naturalIdUniqueKeyHelper = new NaturalIdUniqueKeyHelper( this ); + this.standardAssociationRelationalBindingResolver = + new StandardAssociationRelationalBindingResolverImpl( this ); + this.mappedByAssociationRelationalBindingResolver = + new MappedByAssociationRelationalBindingResolverImpl( this ); + + } + + /** + * The entry point of {@linkplain Binder} class, adds all the entity hierarchy one by one. + * + * Indexes all {@link EntitySource} objects in an {@link EntityHierarchy} and + * creates all {@link EntityBinding}. + * + * @param entityHierarchies The entity hierarchies resolved from mappings + */ + public void addEntityHierarchies(final Iterable entityHierarchies) { + + LocalBindingContextExecutor executor = new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + sourceIndex.indexEntitySource( + bindingContextContext.getRootEntitySource(), + bindingContextContext.getEntitySource() + ); + createEntityBinding( + bindingContextContext.getSuperEntityBinding(), + bindingContextContext.getEntitySource(), + bindingContextContext.getInheritanceType(), + bindingContextContext.getEntityMode() + ); + } + private void resolveEntityLaziness( + final EntityBinding entityBinding, + final EntitySource entitySource, + final EntityMode entityMode) { + if ( entityMode == EntityMode.POJO ) { + final String proxy = entitySource.getProxy(); + if ( proxy == null ) { + if ( entitySource.isLazy() ) { + entityBinding.setProxyInterfaceType( entityBinding.getEntity().getClassReferenceUnresolved() ); + entityBinding.setLazy( true ); + } + } + else { + entityBinding.setProxyInterfaceType( + bindingContext().makeClassReference( + bindingContext().qualifyClassName( + proxy + ) + ) + ); + entityBinding.setLazy( true ); + } + } + else { + entityBinding.setProxyInterfaceType( null ); + entityBinding.setLazy( entitySource.isLazy() ); + } + } + private EntityBinding createEntityBinding( + final EntityBinding superEntityBinding, + final EntitySource entitySource, + final InheritanceType inheritanceType, + final EntityMode entityMode) { + // Create binding + final EntityBinding entityBinding = + entitySource instanceof RootEntitySource ? + new EntityBinding( inheritanceType, entityMode ) : + new EntityBinding( superEntityBinding ); + // Create domain entity + final String entityClassName = entityMode == EntityMode.POJO ? entitySource.getClassName() : null; + LocalBindingContext bindingContext = bindingContext(); + entityBinding.setEntity( + new Entity( + entitySource.getEntityName(), + entityClassName, + bindingContext.makeClassReference( entityClassName ), + superEntityBinding == null ? null : superEntityBinding.getEntity() + ) + ); + + entityBinding.setEntityName( entitySource.getEntityName() ); + entityBinding.setJpaEntityName( entitySource.getJpaEntityName() ); //must before creating primary table + entityBinding.setDynamicUpdate( entitySource.isDynamicUpdate() ); + entityBinding.setDynamicInsert( entitySource.isDynamicInsert() ); + entityBinding.setBatchSize( entitySource.getBatchSize() ); + entityBinding.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() ); + entityBinding.setAbstract( entitySource.isAbstract() ); + entityBinding.setCustomLoaderName( entitySource.getCustomLoaderName() ); + entityBinding.setCustomInsert( entitySource.getCustomSqlInsert() ); + entityBinding.setCustomUpdate( entitySource.getCustomSqlUpdate() ); + entityBinding.setCustomDelete( entitySource.getCustomSqlDelete() ); + entityBinding.setJpaCallbackClasses( entitySource.getJpaCallbackClasses() ); + + // todo: deal with joined and unioned subclass bindings + // todo: bind fetch profiles + // Configure rest of binding + final String customTuplizerClassName = entitySource.getCustomTuplizerClassName(); + if ( customTuplizerClassName != null ) { + entityBinding.setCustomEntityTuplizerClass( + bindingContext.locateClassByName( + customTuplizerClassName + ) + ); + } + final String customPersisterClassName = entitySource.getCustomPersisterClassName(); + if ( customPersisterClassName != null ) { + entityBinding.setCustomEntityPersisterClass( + bindingContext.locateClassByName( + customPersisterClassName + ) + ); + } + entityBinding.setMetaAttributeContext( + createMetaAttributeContext( + entitySource.getMetaAttributeSources(), + true, + metadata.getGlobalMetaAttributeContext() + ) + ); + + if ( entitySource.getSynchronizedTableNames() != null ) { + entityBinding.addSynchronizedTableNames( entitySource.getSynchronizedTableNames() ); + } + resolveEntityLaziness( entityBinding, entitySource, entityMode ); + if ( entitySource.getFilterSources() != null ) { + for ( FilterSource filterSource : entitySource.getFilterSources() ) { + entityBinding.addFilterConfiguration( createFilterConfiguration( filterSource, entityBinding ) ); + } + } + // Register binding with metadata + metadata.addEntity( entityBinding ); + return entityBinding; + } + }; + for ( EntityHierarchy entityHierarchy : entityHierarchies ) { + entityHierarchiesByRootEntityName.put( + entityHierarchy.getRootEntitySource().getEntityName(), + entityHierarchy + ); + entityHierarchyHelper.applyToEntityHierarchy( entityHierarchy, executor, executor ); + } + } + + public void bindEntityHierarchies() { + // Bind everything except for (non-ID) attributes. + // Need to bind ID attributes before resolving associations. + // TODO: when we know the proper order for processing entity hierarchies, + // then applyToAllEntityHierarchies(...) can replace the following method. + bindEntityHierarchiesExcludingNonIdAttributeBindings(); + + // Bind identifier generator for root entitybinding, we have to wait for all entiybindings created, + // since for union-subclass, it may change the root entitybinding in case of root entity is abstract + // so the root table is not physical + applyToAllEntityHierarchies( bindIdentifierGeneratorExecutor() ); + + // Resolve associations: + // - determine if JPA @OneToOne translates to Hibernate's one-to-one or unique many-to-one; + // - determine if JPA @OneToMany translates to Hibernate's one-to-many or unique many-to-many. + applyToAllEntityHierarchies( resolveAssociationSourcesExecutor() ); + + // At this point, SourceIndex has all necessary information. + + // Bind all composite attribute containers. This excludes composite sub-attributes. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeSource.Nature.COMPOSITE ) ); + + // bind basic singular attributes, including composite sub-attributes that are basic. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeSource.Nature.BASIC ) ); + + // many-to-one needs to be bound before one-to-one (um, can't remember why). + + // bind non-mappedby many-to-one and one-to-one attributes, including composite sub-attributes that are many-to-one/one-to-one. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeSource.Nature.MANY_TO_ONE ) ); + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeSource.Nature.ONE_TO_ONE ) ); + + // bind mappedby many-to-one and one-to-one attributes, including composite sub-attributes that are many-to-one/one-to-one. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( true, SingularAttributeSource.Nature.MANY_TO_ONE ) ); + applyToAllEntityHierarchies( bindSingularAttributesExecutor( true, SingularAttributeSource.Nature.ONE_TO_ONE ) ); + + // bind plural attributes (non-mappedBy first), including composite sub-attributes that are plural + applyToAllEntityHierarchies( bindPluralAttributesExecutor( false ) ); + applyToAllEntityHierarchies( bindPluralAttributesExecutor( true ) ); + + // Bind constraints after all attributes have been bound and the + // columns used by attributes is already determined. + applyToAllEntityHierarchies( bindConstraintsExecutor() ); + + // TODO: check if any many-to-one attribute bindings with logicalOneToOne == false have all columns + // (and no formulas) contained in a defined unique key that only contains these columns. + // if so, mark the many-to-one as a logical one-to-one. + // TODO: when does this have to be done. + } + + @Override + public LocalBindingContext bindingContext() { + return localBindingContextManager.localBindingContext(); + } + + @Override + public HibernateTypeHelper typeHelper() { + return typeHelper; + } + + @Override + public RelationalIdentifierHelper relationalIdentifierHelper() { + return relationalIdentifierHelper; + } + + @Override + public TableHelper tableHelper() { + return tableHelper; + } + + @Override + public ForeignKeyHelper foreignKeyHelper() { + return foreignKeyHelper; + } + + @Override + public RelationalValueBindingHelper relationalValueBindingHelper() { + return relationalValueBindingHelper; + } + + @Override + public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() { + return naturalIdUniqueKeyHelper; + } + + private LocalBindingContextExecutor bindIdentifierGeneratorExecutor() { + return new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + EntityBinding entityBinding = bindingContextContext.getEntityBinding(); + if ( entityBinding.getSuperEntityBinding() == null ) { + bindIdentifierGenerator( entityBinding ); + } + } + }; + } + + private void applyToAllEntityHierarchies(LocalBindingContextExecutor executor) { + applyToAllEntityHierarchies( executor, executor ); + } + + private void applyToAllEntityHierarchies(LocalBindingContextExecutor rootExecutor, LocalBindingContextExecutor subExecutor) { + entityHierarchyHelper.applyToAllEntityHierarchies( + entityHierarchiesByRootEntityName.values(), + rootExecutor, + subExecutor + ); + } + + + private void bindEntityHierarchiesExcludingNonIdAttributeBindings() { + LocalBindingContextExecutor rootEntityCallback = new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + final RootEntitySource rootEntitySource = (RootEntitySource) bindingContextContext.getEntitySource(); + final EntityBinding rootEntityBinding = bindingContextContext.getEntityBinding(); + bindPrimaryTable( rootEntityBinding, rootEntitySource ); + // Create/Bind root-specific information + bindIdentifier( rootEntityBinding, rootEntitySource.getIdentifierSource() ); + bindSecondaryTables( rootEntityBinding, rootEntitySource ); + bindVersion( rootEntityBinding, rootEntitySource.getVersioningAttributeSource() ); + bindDiscriminator( rootEntityBinding, rootEntitySource ); + bindMultiTenancy( rootEntityBinding, rootEntitySource ); + rootEntityBinding.getHierarchyDetails().setCaching( rootEntitySource.getCaching() ); + rootEntityBinding.getHierarchyDetails().setNaturalIdCaching( rootEntitySource.getNaturalIdCaching() ); + rootEntityBinding.getHierarchyDetails() + .setExplicitPolymorphism( rootEntitySource.isExplicitPolymorphism() ); + rootEntityBinding.getHierarchyDetails().setOptimisticLockStyle( rootEntitySource.getOptimisticLockStyle() ); + rootEntityBinding.setMutable( rootEntitySource.isMutable() ); + rootEntityBinding.setWhereFilter( rootEntitySource.getWhere() ); + rootEntityBinding.setRowId( rootEntitySource.getRowId() ); + } + + private void bindSimpleIdentifier( + final EntityBinding rootEntityBinding, + final SimpleIdentifierSource identifierSource) { + // locate the attribute binding + final BasicAttributeBinding idAttributeBinding = (BasicAttributeBinding) bindIdentifierAttribute( + rootEntityBinding, identifierSource.getIdentifierAttributeSource() + ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, rootEntityBinding.getEntity().getName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + + // determine the unsaved value mapping + final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); + + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier( + idAttributeBinding, + generator, + unsavedValue + ); + } + private String interpretIdentifierUnsavedValue( + final IdentifierSource identifierSource, + final IdentifierGeneratorDefinition generator) { + if ( identifierSource == null ) { + throw new IllegalArgumentException( "identifierSource must be non-null." ); + } + if ( generator == null || StringHelper.isEmpty( generator.getStrategy() ) ) { + throw new IllegalArgumentException( "generator must be non-null and its strategy must be non-empty." ); + } + String unsavedValue = null; + if ( identifierSource.getUnsavedValue() != null ) { + unsavedValue = identifierSource.getUnsavedValue(); + } + else if ( "assigned".equals( generator.getStrategy() ) ) { + unsavedValue = "undefined"; + } + else { + switch ( identifierSource.getNature() ) { + case SIMPLE: { + // unsavedValue = null; + break; + } + case NON_AGGREGATED_COMPOSITE: { + // The generator strategy should be "assigned" and processed above. + throw new IllegalStateException( + String.format( + "Expected generator strategy for composite ID: 'assigned'; instead it is: %s", + generator.getStrategy() + ) + ); + } + case AGGREGATED_COMPOSITE: { + // TODO: if the component only contains 1 attribute (when flattened) + // and it is not an association then null should be returned; + // otherwise "undefined" should be returned. + throw new NotYetImplementedException( + String.format( + "Unsaved value for (%s) identifier not implemented yet.", + identifierSource.getNature() + ) + ); + } + default: { + throw new AssertionFailure( + String.format( + "Unexpected identifier nature: %s", + identifierSource.getNature() + ) + ); + } + } + } + return unsavedValue; + } + + private void bindAggregatedCompositeIdentifier( + final EntityBinding rootEntityBinding, + final AggregatedCompositeIdentifierSource identifierSource) { + // locate the attribute binding + final CompositeAttributeBinding idAttributeBinding = + (CompositeAttributeBinding) bindIdentifierAttribute( + rootEntityBinding, identifierSource.getIdentifierAttributeSource() + ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, rootEntityBinding.getEntity().getName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + + // determine the unsaved value mapping + final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); + + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsAggregatedCompositeIdentifier( + idAttributeBinding, generator, unsavedValue + ); + } + + private void bindNonAggregatedCompositeIdentifier( + final EntityBinding rootEntityBinding, + final NonAggregatedCompositeIdentifierSource identifierSource) { + // locate the attribute bindings for the real attributes + List idAttributeBindings = + new ArrayList(); + for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { + SingularAttributeBinding singularAttributeBinding = + bindIdentifierAttribute( rootEntityBinding, attributeSource ); + idAttributeBindings.add( singularAttributeBinding ); + } + + final Class idClassClass = identifierSource.getLookupIdClass(); + final String idClassPropertyAccessorName = + idClassClass == null ? + null : + propertyAccessorName( identifierSource.getIdClassPropertyAccessorName() ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, rootEntityBinding.getEntity().getName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + // Create the synthetic attribute + final SingularAttribute syntheticAttribute = + rootEntityBinding.getEntity().createSyntheticCompositeAttribute( + SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME, + rootEntityBinding.getEntity() + ); + + final CompositeAttributeBinding syntheticAttributeBinding = + rootEntityBinding.makeVirtualCompositeAttributeBinding( + syntheticAttribute, + createMetaAttributeContext( rootEntityBinding, identifierSource.getMetaAttributeSources() ), + idAttributeBindings + ); + // Create the synthetic attribute binding. + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsNonAggregatedCompositeIdentifier( + syntheticAttributeBinding, + generator, + interpretIdentifierUnsavedValue( identifierSource, generator ), + idClassClass, + idClassPropertyAccessorName + ); + + typeHelper.bindNonAggregatedCompositeIdentifierType( syntheticAttributeBinding, syntheticAttribute ); + } + + private void bindIdentifier( + final EntityBinding rootEntityBinding, + final IdentifierSource identifierSource) { + final EntityIdentifierNature nature = identifierSource.getNature(); + switch ( nature ) { + case SIMPLE: { + bindSimpleIdentifier( rootEntityBinding, (SimpleIdentifierSource) identifierSource ); + break; + } + case AGGREGATED_COMPOSITE: { + bindAggregatedCompositeIdentifier( + rootEntityBinding, + (AggregatedCompositeIdentifierSource) identifierSource + ); + break; + } + case NON_AGGREGATED_COMPOSITE: { + bindNonAggregatedCompositeIdentifier( + rootEntityBinding, + (NonAggregatedCompositeIdentifierSource) identifierSource + ); + break; + } + default: { + throw bindingContext().makeMappingException( "Unknown identifier nature : " + nature.name() ); + } + } + } + + private void bindVersion( + final EntityBinding rootEntityBinding, + final VersionAttributeSource versionAttributeSource) { + if ( versionAttributeSource == null ) { + return; + } + final EntityVersion version = rootEntityBinding.getHierarchyDetails().getEntityVersion(); + version.setVersioningAttributeBinding( + (BasicAttributeBinding) bindAttribute( + rootEntityBinding, + versionAttributeSource + ) + ); + // ensure version is non-nullable + for ( RelationalValueBinding valueBinding : version.getVersioningAttributeBinding() + .getRelationalValueBindings() ) { + if ( !valueBinding.isDerived() ) { + ( (Column) valueBinding.getValue() ).setNullable( false ); + } + } + version.setUnsavedValue( + versionAttributeSource.getUnsavedValue() == null ? "undefined" : versionAttributeSource.getUnsavedValue() + ); + } + private void bindMultiTenancy( + final EntityBinding rootEntityBinding, + final RootEntitySource rootEntitySource) { + final MultiTenancySource multiTenancySource = rootEntitySource.getMultiTenancySource(); + if ( multiTenancySource == null ) { + return; + } + + // if (1) the strategy is discriminator based and (2) the entity is not shared, we need to either (a) extract + // the user supplied tenant discriminator value mapping or (b) generate an implicit one + final boolean needsTenantIdentifierValueMapping = + MultiTenancyStrategy.DISCRIMINATOR == metadata.getOptions().getMultiTenancyStrategy() + && !multiTenancySource.isShared(); + + if ( needsTenantIdentifierValueMapping ) { + // NOTE : the table for tenant identifier/discriminator is always the primary table + final Value tenantDiscriminatorValue; + final RelationalValueSource valueSource = multiTenancySource.getRelationalValueSource(); + if ( valueSource == null ) { + // user supplied no explicit information, so use implicit mapping with default name + tenantDiscriminatorValue = rootEntityBinding.getPrimaryTable().locateOrCreateColumn( + metadata.getMappingDefaults().getTenantIdColumnName() + ); + } + else { + tenantDiscriminatorValue = buildDiscriminatorRelationValue( + valueSource, + rootEntityBinding.getPrimaryTable() + ); + } + rootEntityBinding.getHierarchyDetails() + .getTenantDiscrimination() + .setDiscriminatorValue( tenantDiscriminatorValue ); + } + + rootEntityBinding.getHierarchyDetails().getTenantDiscrimination().setShared( multiTenancySource.isShared() ); + rootEntityBinding.getHierarchyDetails() + .getTenantDiscrimination() + .setUseParameterBinding( multiTenancySource.bindAsParameter() ); + } + private Value buildDiscriminatorRelationValue( + final RelationalValueSource valueSource, + final TableSpecification table) { + if ( valueSource.getNature() == RelationalValueSource.Nature.COLUMN ) { + return tableHelper.locateOrCreateColumn( + table, + (ColumnSource) valueSource, + new ColumnNamingStrategyHelper( + bindingContext().getMappingDefaults().getDiscriminatorColumnName(), + false + ), + false, + false + ); + } + else { + return table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() ); + } + } + + + private void bindDiscriminator( + final EntityBinding rootEntityBinding, + final RootEntitySource rootEntitySource) { + final DiscriminatorSource discriminatorSource = rootEntitySource.getDiscriminatorSource(); + if ( discriminatorSource == null ) { + return; + } + final RelationalValueSource valueSource = discriminatorSource.getDiscriminatorRelationalValueSource(); + final TableSpecification table = rootEntityBinding.locateTable( valueSource.getContainingTableName() ); + final Value value = buildDiscriminatorRelationValue( valueSource, table ); + final EntityDiscriminator discriminator = + new EntityDiscriminator( value, discriminatorSource.isInserted(), discriminatorSource.isForced() ); + rootEntityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator ); + final String discriminatorValue = rootEntitySource.getDiscriminatorMatchValue(); + if ( discriminatorValue != null ) { + rootEntityBinding.setDiscriminatorMatchValue( discriminatorValue ); + } + else + // if ( !Modifier.isAbstract( + // bindingContext().locateClassByName( rootEntitySource.getEntityName() ) + // .getModifiers() + // ) ) + { + // Use the class name as a default if no discriminator value. + // However, skip abstract classes -- obviously no discriminators there. + // But this is not correct, since for single table entity hierarchy, even the root class is abstract, it still should has discriminator + rootEntityBinding.setDiscriminatorMatchValue( StringHelper.unqualify( rootEntitySource.getEntityName() ) ); + } + // Configure discriminator hibernate type + typeHelper.bindDiscriminatorType( discriminator, value ); + } + + }; + LocalBindingContextExecutor subEntityCallback = new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + final EntitySource entitySource = bindingContextContext.getEntitySource(); + final EntityBinding entityBinding = bindingContextContext.getEntityBinding(); + final EntityBinding superEntityBinding = bindingContextContext.getSuperEntityBinding(); + entityBinding.setMutable( entityBinding.getHierarchyDetails().getRootEntityBinding().isMutable() ); + markSuperEntityTableAbstractIfNecessary( superEntityBinding ); + bindPrimaryTable( entityBinding, entitySource ); + bindSubEntityPrimaryKey( entityBinding, entitySource ); + bindSecondaryTables( entityBinding, entitySource ); + } + private void bindSubEntityPrimaryKey( + final EntityBinding entityBinding, + final EntitySource entitySource) { + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + if ( superEntityBinding == null ) { + throw new AssertionFailure( "super entitybinding is null " ); + } + if ( inheritanceType == InheritanceType.JOINED ) { + JoinedSubclassEntitySource subclassEntitySource = (JoinedSubclassEntitySource) entitySource; + final List columnSources = subclassEntitySource.getPrimaryKeyColumnSources(); + final TableSpecification table = entityBinding.getPrimaryTable(); + final List joinRelationalValueBindings = + getJoinedPrimaryKeyRelationalValueBindings( superEntityBinding, columnSources, table ); + + entityBinding.setKeyRelationalValueBindings( joinRelationalValueBindings ); + List targetColumns = + foreignKeyHelper.determineForeignKeyTargetColumns( + superEntityBinding, + subclassEntitySource + ); + + ForeignKey foreignKey = locateOrCreateForeignKey( + subclassEntitySource.getExplicitForeignKeyName(), + table, + joinRelationalValueBindings, + foreignKeyHelper.determineForeignKeyTargetTable( superEntityBinding, subclassEntitySource ), + targetColumns + ); + + if ( subclassEntitySource.isCascadeDeleteEnabled() ) { + foreignKey.setDeleteRule( ForeignKey.ReferentialAction.CASCADE ); + entityBinding.setCascadeDeleteEnabled( true ); + } + } + } + private void markSuperEntityTableAbstractIfNecessary( + final EntityBinding superEntityBinding) { + if ( superEntityBinding == null ) { + return; + } + if ( superEntityBinding.getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) { + return; + } + if ( superEntityBinding.isAbstract() != Boolean.TRUE ) { + return; + } + if ( !Table.class.isInstance( superEntityBinding.getPrimaryTable() ) ) { + return; + } + Table.class.cast( superEntityBinding.getPrimaryTable() ).setPhysicalTable( false ); + } + }; + // TODO: need to determine the proper order for processing EntityHierarchy objects + // so that dependent EntityHierarchy is processed after the EntityHierarchy it + // is dependent on. + // For now, just delay processing the dependent entity hierarchies. + Set unresolvedEntityHierarchies = new HashSet( ); + for ( final EntityHierarchy entityHierarchy : entityHierarchiesByRootEntityName.values() ) { + if ( isIdentifierDependentOnOtherEntityHierarchy( entityHierarchy ) ) { + unresolvedEntityHierarchies.add( entityHierarchy ); + } + else { + entityHierarchyHelper.applyToEntityHierarchy( entityHierarchy, rootEntityCallback, subEntityCallback ); + } + } + + // The following is to try to resolve any dependent entity hierarchies. + // It runs through all the dependent entity hierarchies and resolves what it can. + // This process repeats until no more can be resolved. + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + int oldSize = Integer.MAX_VALUE; + while( !unresolvedEntityHierarchies.isEmpty() && unresolvedEntityHierarchies.size() < oldSize ) { + oldSize = unresolvedEntityHierarchies.size(); + for ( Iterator it = unresolvedEntityHierarchies.iterator(); it.hasNext(); ) { + final EntityHierarchy entityHierarchy = it.next(); + try { + entityHierarchyHelper.applyToEntityHierarchy( + entityHierarchy, + rootEntityCallback, + subEntityCallback + ); + // succeeded, so the entityHierarchy is no longer unresolved. + it.remove(); + } + catch (Exception ex) { + // to nothing; + } + } + } + // If any entity hierarchies cannot be resolved, then throw exception. + if ( ! unresolvedEntityHierarchies.isEmpty() ) { + throw new IllegalStateException( "could not resolve all EntityHierarchies." ); + } + } + + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + private boolean isIdentifierDependentOnOtherEntityHierarchy(EntityHierarchy entityHierarchy) { + final RootEntitySource rootEntitySource = entityHierarchy.getRootEntitySource(); + final IdentifierSource identifierSource = rootEntitySource.getIdentifierSource(); + if ( identifierSource.getNature() != EntityIdentifierNature.SIMPLE ) { + List subAttributeSources = + identifierSource.getNature() == EntityIdentifierNature.AGGREGATED_COMPOSITE ? + ( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource().attributeSources() : + ( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier(); + return containsSingularAssociation( subAttributeSources ); + } + else { + return false; + } + } + + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + private boolean containsSingularAssociation(List subAttributeSources) { + for ( AttributeSource attributeSource : subAttributeSources ) { + SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; + // If the attribute source is for a -to-one association, the nature may not be resolved yet. + if ( ToOneAttributeSource.class.isInstance( singularAttributeSource ) ) { + return true; + } + else if ( ( (SingularAttributeSource) attributeSource ).getNature() == SingularAttributeSource.Nature.COMPOSITE ) { + ComponentAttributeSource componentAttributeSource = (ComponentAttributeSource) attributeSource; + return containsSingularAssociation( componentAttributeSource.attributeSources() ); + } + } + return false; + } + + private AttributeBindingContainer locateAttributeBindingContainer(final EntityBinding entityBinding, final String containerPath) { + return StringHelper.isEmpty( containerPath ) ? + entityBinding : + (AttributeBindingContainer) entityBinding.locateAttributeBindingByPath( containerPath, false ); + } + + private LocalBindingContextExecutor resolveAssociationSourcesExecutor() { + return new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + sourceIndex.resolveAssociationSources( bindingContextContext ); + } + }; + } + + private LocalBindingContextExecutor bindSingularAttributesExecutor( + final boolean isMappedBy, + final SingularAttributeSource.Nature nature) { + return new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + bindSingularAttributes( + bindingContextContext.getEntityBinding(), + isMappedBy, + nature + ); + } + }; + } + + // TODO: create separate methods that are more clear for the cases. + private void bindSingularAttributes( + final EntityBinding entityBinding, + final boolean isMappedBy, + final SingularAttributeSource.Nature nature) { + // Get the map of all attributes for the entity binding of the specified nature. + Map map = sourceIndex.getSingularAttributeSources( + entityBinding.getEntityName(), + isMappedBy, + nature + ); + for ( Map.Entry entry : map.entrySet() ){ + final SourceIndex.AttributeSourceKey attributeSourceKey = entry.getKey(); + final SingularAttributeSource attributeSource = entry.getValue(); + final AttributeBindingContainer attributeBindingContainer = + locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() ); + if ( isMappedBy ) { + if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) { + throw new AssertionFailure( + String.format( + "mappedBy is true, but attributeSouce is not an association: %s", + attributeSourceKey + ) + ); + } + bindMappedBySecondaryTableIfNecessary( entityBinding, (ToOneAttributeSource) attributeSource ); + } + + if ( nature == SingularAttributeSource.Nature.COMPOSITE ) { + // This only creates the composite attribute container. + createAggregatedCompositeAttribute( + attributeBindingContainer, + (ComponentAttributeSource) attributeSource, + null ); + } + else if ( attributeBindingContainer instanceof CompositeAttributeBinding ) { + // This attribute source is within a composite; skip binding if it is the parent. + final CompositeAttributeBinding compositeAttributeBinding = (CompositeAttributeBinding) attributeBindingContainer; + final ComponentAttributeSource compositeAttributeSource = + (ComponentAttributeSource) sourceIndex.attributeSource( + entityBinding.getEntityName(), + compositeAttributeBinding.getPathBase() + ); + final SingularAttribute parentReference = compositeAttributeBinding.getParentReference(); + if ( parentReference == null || !parentReference.getName().equals( attributeSource.getName() ) ) { + bindAttribute( attributeBindingContainer, attributeSource ); + completeCompositeAttributeBindingIfPossible( + compositeAttributeBinding, + compositeAttributeSource + ); + } + } + else { + // The container is the EntityBinding itself. + bindAttribute( attributeBindingContainer, attributeSource ); + } + } + } + + // All sub-attributes must be bound before it's type and ComponentMetamodel can be determined. + private void completeCompositeAttributeBindingIfPossible( + CompositeAttributeBinding compositeAttributeBinding, + ComponentAttributeSource compositeAttributeSource + ) { + // Find out the number of sub-attributes, excluding the parent attribute. + final int nAttributeSourcesExcludingParent = + compositeAttributeBinding.getParentReference() != null ? + compositeAttributeSource.attributeSources().size() - 1 : + compositeAttributeSource.attributeSources().size(); + if ( compositeAttributeBinding.attributeBindingSpan() == nAttributeSourcesExcludingParent ) { + // All sub-attribute bindings are present; now check if all sub-attributes have + // their type resolved. + boolean allResolved = true; + for ( AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) { + if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() == null ) { + // Something is not resolved. + allResolved = false; + break; + } + } + if ( allResolved ) { + // All are resolved, so we can bind the type. + typeHelper.bindAggregatedCompositeAttributeType( + false, + (Aggregate) compositeAttributeBinding.getAttribute().getSingularAttributeType(), + null, // TODO: don't have the default value at this point; shouldn't be needed... + compositeAttributeBinding + ); + // Now check the container. + if ( compositeAttributeBinding.getContainer() instanceof CompositeAttributeBindingContainer ) { + // The container is also a CompositeAttributeBindingContainer. + // We need this process for the container. + final CompositeAttributeBinding parentCompositeAttributeBinding = + (CompositeAttributeBinding) compositeAttributeBinding.seekEntityBinding().locateAttributeBinding( + ( compositeAttributeBinding.getContainer() ).getPathBase() + ); + final ComponentAttributeSource parentCompositeAttributeSource = + (ComponentAttributeSource) sourceIndex.attributeSource( + parentCompositeAttributeBinding.seekEntityBinding().getEntityName(), + parentCompositeAttributeBinding.getPathBase() + ); + completeCompositeAttributeBindingIfPossible( + parentCompositeAttributeBinding, + parentCompositeAttributeSource + ); + } + } + } + } + + private LocalBindingContextExecutor bindPluralAttributesExecutor(final boolean isInverse) { + return new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + // TODO: may want bind plural attributes of a particular element nature. + final EntityBinding entityBinding = bindingContextContext.getEntityBinding(); + // Get the map for inverse or non-inverse (as specified) plural attributes + Map map = sourceIndex.getPluralAttributeSources( + entityBinding.getEntityName(), + isInverse + ); + for ( Map.Entry entry : map.entrySet() ){ + final SourceIndex.AttributeSourceKey attributeSourceKey = entry.getKey(); + final PluralAttributeSource attributeSource = entry.getValue(); + // Bind the attribute into the appropriate container. + final AttributeBindingContainer attributeBindingContainer = + locateAttributeBindingContainer( entityBinding, attributeSourceKey.containerPath() ); + bindAttribute( attributeBindingContainer, attributeSource ); + if ( attributeBindingContainer instanceof CompositeAttributeBinding ) { + // We just bound a sub-attribute into a CompositeAttributeBinding. + final CompositeAttributeBinding compositeAttributeBinding = (CompositeAttributeBinding) attributeBindingContainer; + final ComponentAttributeSource compositeAttributeSource = + (ComponentAttributeSource) sourceIndex.attributeSource( + entityBinding.getEntityName(), + compositeAttributeBinding.getPathBase() + ); + // Resolve the type if types are resolved for all sub-attributes now. + completeCompositeAttributeBindingIfPossible( compositeAttributeBinding, compositeAttributeSource ); + } + } + } + }; + } + + + private LocalBindingContextExecutor bindConstraintsExecutor() { + return new LocalBindingContextExecutor() { + @Override + public void execute(LocalBindingContextExecutionContext bindingContextContext) { + final EntityBinding entityBinding = bindingContextContext.getEntityBinding(); + final EntitySource entitySource = bindingContextContext.getEntitySource(); + for ( final ConstraintSource constraintSource : entitySource.getConstraints() ) { + if ( UniqueConstraintSource.class.isInstance( constraintSource ) ) { + final UniqueConstraintSource uniqueConstraintSource = (UniqueConstraintSource) constraintSource; + + final TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); + + final List columns = new ArrayList(); + for ( final String columnName : uniqueConstraintSource.columnNames() ) { + columns.add( tableHelper.locateOrCreateColumn( table, columnName, + new ColumnNamingStrategyHelper( null, false ) ) ); + } + tableHelper.createUniqueKey( table, columns, constraintSource.name() ); + } + else if ( IndexConstraintSource.class.isInstance( constraintSource ) ) { + final IndexConstraintSource indexConstraintSource = (IndexConstraintSource) constraintSource; + + final TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); + + final List columns = new ArrayList(); + for ( final String columnName : indexConstraintSource.columnNames() ) { + columns.add( tableHelper.locateOrCreateColumn( table, columnName, + new ColumnNamingStrategyHelper( null, false ) ) ); + } + tableHelper.createIndex( table, columns, constraintSource.name() ); + } + } + } + }; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Entity binding relates methods + + private EntityBinding locateEntityBinding( + final ValueHolder> entityJavaTypeValue, + final String explicitEntityName) { + final String referencedEntityName = + explicitEntityName != null + ? explicitEntityName + : entityJavaTypeValue.getValue().getName(); + return locateEntityBinding( referencedEntityName ); + } + + private EntityBinding locateEntityBinding(final String entityName) { + // Check if binding has already been created + EntityBinding entityBinding = metadata.getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw bindingContext().makeMappingException( + String.format( "No entity binding with name: %s", entityName ) + ); + } + return entityBinding; + } + + + + private FilterConfiguration createFilterConfiguration(FilterSource filterSource, EntityBinding entityBinding){ + String condition = filterSource.getCondition(); + if(StringHelper.isEmpty( condition )){ + FilterDefinition filterDefinition = metadata.getFilterDefinitions().get( filterSource.getName() ); + if(filterDefinition == null){ + throw bindingContext().makeMappingException( String.format( "Filter[%s] doesn't have a condition", filterSource.getName() ) ); + } + condition = filterDefinition.getDefaultFilterCondition(); + } + return new FilterConfiguration( + filterSource.getName(), + condition, + filterSource.shouldAutoInjectAliases(), + filterSource.getAliasToTableMap(), + filterSource.getAliasToEntityMap(), + entityBinding + ); + } + + private void bindPrimaryTable( + final EntityBinding entityBinding, + final EntitySource entitySource) { + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final TableSpecification table; + final String tableName; + // single table and sub entity + if ( superEntityBinding != null && inheritanceType == InheritanceType.SINGLE_TABLE ) { + table = superEntityBinding.getPrimaryTable(); + tableName = superEntityBinding.getPrimaryTableName(); + // Configure discriminator if present + final String discriminatorValue = entitySource.getDiscriminatorMatchValue() != null ? + entitySource.getDiscriminatorMatchValue() + : StringHelper.unqualify( entitySource.getEntityName() ); + entityBinding.setDiscriminatorMatchValue( discriminatorValue ); + } + + // single table and root entity + // joined + // table per class and non-abstract entity + else { + Table includedTable = null; + if ( superEntityBinding != null + && inheritanceType == InheritanceType.TABLE_PER_CLASS + && Table.class.isInstance( superEntityBinding.getPrimaryTable() ) ) { + includedTable = Table.class.cast( superEntityBinding.getPrimaryTable() ); + } + table = tableHelper.createTable( + entitySource.getPrimaryTable(), new TableNamingStrategyHelper( entityBinding ), includedTable + ); + tableName = table.getLogicalName().getText(); + } + entityBinding.setPrimaryTable( table ); + entityBinding.setPrimaryTableName( tableName ); + } + + private void bindSecondaryTables( + final EntityBinding entityBinding, + final EntitySource entitySource) { + for ( final SecondaryTableSource secondaryTableSource : entitySource.getSecondaryTables() ) { + final TableSpecification table = tableHelper.createTable( + secondaryTableSource.getTableSource(), + new TableNamingStrategyHelper( entityBinding ) + ); + table.addComment( secondaryTableSource.getComment() ); + final List joinRelationalValueBindings = getJoinedPrimaryKeyRelationalValueBindings( + entityBinding, + secondaryTableSource.getPrimaryKeyColumnSources(), + table + ); + + // TODO: make the foreign key column the primary key??? + final List targetColumns = foreignKeyHelper.determineForeignKeyTargetColumns( entityBinding, secondaryTableSource ); + final ForeignKey foreignKey = locateOrCreateForeignKey( + secondaryTableSource.getExplicitForeignKeyName(), + table, + joinRelationalValueBindings, + foreignKeyHelper.determineForeignKeyTargetTable( entityBinding, secondaryTableSource ), + targetColumns + ); + SecondaryTable secondaryTable = new SecondaryTable( table, foreignKey ); + if(secondaryTableSource.getFetchStyle()!=null) + secondaryTable.setFetchStyle( secondaryTableSource.getFetchStyle() ); + secondaryTable.setInverse( secondaryTableSource.isInverse() ); + secondaryTable.setOptional( secondaryTableSource.isOptional() ); + secondaryTable.setCascadeDeleteEnabled( secondaryTableSource.isCascadeDeleteEnabled() ); + secondaryTable.setCustomDelete( secondaryTableSource.getCustomSqlDelete() ); + secondaryTable.setCustomInsert( secondaryTableSource.getCustomSqlInsert() ); + secondaryTable.setCustomUpdate( secondaryTableSource.getCustomSqlUpdate() ); + if ( secondaryTable.isCascadeDeleteEnabled() ) { + foreignKey.setDeleteRule( ForeignKey.ReferentialAction.CASCADE ); + } + entityBinding.addSecondaryTable( secondaryTable ); + metadata.addSecondaryTable( secondaryTable ); + } + } + + private void bindMappedBySecondaryTableIfNecessary(EntityBinding entityBinding, ToOneAttributeSource attributeSource) { + if ( ! attributeSource.isMappedBy() ) { + throw new IllegalArgumentException( "attributeSource does not have mappedBy defined." ); + } + final MappedByAssociationSource mappedByAssociationSource = (MappedByAssociationSource) attributeSource; + + final ToOneAttributeSource ownerAttributeSource = (ToOneAttributeSource) sourceIndex.attributeSource( + mappedByAssociationSource.getReferencedEntityName(), mappedByAssociationSource.getMappedBy() + ); + if ( ownerAttributeSource.isMappedBy() ) { + throw new AssertionFailure( "owner attribute source has mappedBy != null" ); + } + + final EntityBinding ownerEntityBinding = locateEntityBinding( attributeSource.getReferencedEntityName() ); + + if ( ownerAttributeSource.getNature() == SingularAttributeSource.Nature.ONE_TO_ONE || + ownerAttributeSource.getContainingTableName() == null || + ownerAttributeSource.getContainingTableName().equals( ownerEntityBinding.getPrimaryTableName() ) ) { + // primary table is used, so no need to bind an inverse secondary table. + return; + } + + final AttributeBinding ownerAttributeBinding = + ownerEntityBinding.locateAttributeBindingByPath( mappedByAssociationSource.getMappedBy(), true ); + if ( !SingularAssociationAttributeBinding.class.isInstance( ownerAttributeBinding ) ) { + throw new AssertionFailure( "Owner is not a one-to-one or many-to-one association." ); + } + final SingularAssociationAttributeBinding ownerAssociationAttributeBinding = + (SingularAssociationAttributeBinding) ownerAttributeBinding; + + // If the owner side of the association uses a secondary table, then an inverse secondary table needs + // to be bound for the entity binding containing the mappedBy attribute.. + final TableSpecification ownerTable = ownerAssociationAttributeBinding.getTable(); + if ( !ownerEntityBinding.getPrimaryTable().equals( ownerTable ) ) { + final SecondaryTable ownerSecondaryTable = + ownerEntityBinding.getSecondaryTables().get( + ownerTable.getLogicalName() + ); + if ( ownerSecondaryTable == null ) { + throw new AssertionFailure( "Owner association does not use primary table, but no secondary table was found." ); + } + } + + if ( entityBinding.getPrimaryTable().equals( ownerTable ) || + entityBinding.getSecondaryTables().containsKey( ownerTable.getLogicalName() ) ) { + // table already exists; nothing to do. + return; + } + + // locate the foreign key + final List targetColumns = new ArrayList( ownerAssociationAttributeBinding.getRelationalValueBindings().size() ); + for ( Value targetValue : ownerAssociationAttributeBinding.getReferencedAttributeBinding().getValues() ) { + targetColumns.add( (Column) targetValue ); + } + final ForeignKey foreignKey = foreignKeyHelper.locateOrCreateForeignKey( + null, + ownerTable, + extractColumnsFromRelationalValueBindings( ownerAssociationAttributeBinding.getRelationalValueBindings() ), + entityBinding.getPrimaryTable(), + targetColumns + ); + if ( foreignKey == null ) { + throw new AssertionFailure( "Foreign key not found; should have been defined by owner side of association." ); + } + final SecondaryTable ownerSecondaryTable = ownerEntityBinding.getSecondaryTables().get( ownerTable.getLogicalName() ); + SecondaryTable secondaryTable = new SecondaryTable( ownerTable, foreignKey ); + secondaryTable.setInverse( true ); + secondaryTable.setOptional( ownerSecondaryTable.isOptional() ); + // TODO: how should this be set??? + secondaryTable.setCascadeDeleteEnabled( false ); + secondaryTable.setCustomDelete( ownerSecondaryTable.getCustomDelete() ); + secondaryTable.setCustomInsert( ownerSecondaryTable.getCustomInsert() ); + secondaryTable.setCustomUpdate( ownerSecondaryTable.getCustomUpdate() ); + if ( secondaryTable.isCascadeDeleteEnabled() ) { + foreignKey.setDeleteRule( ForeignKey.ReferentialAction.CASCADE ); + } + entityBinding.addSecondaryTable( secondaryTable ); + metadata.addSecondaryTable( secondaryTable ); + } + + + + private List getJoinedPrimaryKeyRelationalValueBindings( + EntityBinding entityBinding, + List joinedPrimaryKeyColumnSources, + TableSpecification table) { + final List primaryKeyColumns = entityBinding.getPrimaryTable().getPrimaryKey().getColumns(); + + final List joinRelationalValueBindings; + // TODO: deal with property-refs??? + if ( joinedPrimaryKeyColumnSources.isEmpty() ) { + joinRelationalValueBindings = new ArrayList( primaryKeyColumns.size() ); + for ( Column joinedColumn : primaryKeyColumns ) { + Column joinColumn = table.locateOrCreateColumn( + bindingContext().getNamingStrategy().joinKeyColumnName( + joinedColumn.getColumnName().getText(), + entityBinding.getPrimaryTable().getLogicalName().getText() + ) + ); + joinColumn.setNullable( false ); + table.getPrimaryKey().addColumn( joinColumn ); + joinRelationalValueBindings.add( new RelationalValueBinding( entityBinding.getPrimaryTable(), joinColumn, true, false ) ); + } + } + else { + joinRelationalValueBindings = new ArrayList( + joinedPrimaryKeyColumnSources + .size() + ); + if ( primaryKeyColumns.size() != joinedPrimaryKeyColumnSources.size() ) { + throw bindingContext().makeMappingException( + String.format( + "The number of primary key column sources provided for a secondary table is not equal to the number of columns in the primary key for [%s].", + entityBinding.getEntityName() + ) + ); + } + for ( int i = 0; i < primaryKeyColumns.size(); i++ ) { + // todo : apply naming strategy to infer missing column name + final ColumnSource joinColumnSource = joinedPrimaryKeyColumnSources.get( i ); + Column column = table.locateColumn( joinColumnSource.getName() ); + if ( column == null ) { + column = tableHelper.locateOrCreateColumn( + table, + joinColumnSource, + new ColumnNamingStrategyHelper( + null, + false + ), + true, + false + ); + table.getPrimaryKey().addColumn( column ); + } + joinRelationalValueBindings.add( new RelationalValueBinding( table, column, true, false ) ); + } + } + typeHelper.bindJdbcDataType( + entityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(), + joinRelationalValueBindings + ); + return joinRelationalValueBindings; + } + + public ForeignKey locateOrCreateForeignKey( + final String foreignKeyName, + final TableSpecification sourceTable, + final List sourceRelationalValueBindings, + final TableSpecification targetTable, + final List targetColumns) { + return foreignKeyHelper.locateOrCreateForeignKey( + foreignKeyName, + sourceTable, + extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), + targetTable, + targetColumns + ); + } + + // TODO: try to get rid of this... + private static List extractColumnsFromRelationalValueBindings( + final List valueBindings) { + List columns = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : valueBindings ) { + final Value value = relationalValueBinding.getValue(); + // todo : currently formulas are not supported here... :( + if ( !Column.class.isInstance( value ) ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + columns.add( (Column) value ); + } + return columns; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ identifier binding relates methods + + + + private void bindIdentifierGenerator(final EntityBinding rootEntityBinding) { + final Properties properties = new Properties(); + properties.putAll( metadata.getServiceRegistry().getService( ConfigurationService.class ).getSettings() ); + if ( !properties.contains( AvailableSettings.PREFER_POOLED_VALUES_LO ) ) { + properties.put( AvailableSettings.PREFER_POOLED_VALUES_LO, "false" ); + } + if ( !properties.contains( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER ) ) { + properties.put( + PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, + metadata.getObjectNameNormalizer() + ); + } + final EntityIdentifier entityIdentifier = rootEntityBinding.getHierarchyDetails().getEntityIdentifier(); + entityIdentifier.createIdentifierGenerator( identifierGeneratorFactory, properties ); + if ( IdentityGenerator.class.isInstance( entityIdentifier.getIdentifierGenerator() ) ) { + if ( rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() != 1 ) { + throw bindingContext().makeMappingException( + String.format( + "ID for %s is mapped as an identity with %d columns. IDs mapped as an identity can only have 1 column.", + rootEntityBinding.getEntity().getName(), + rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() + ) + ); + } + rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).setIdentity( true ); + } + if ( PersistentIdentifierGenerator.class.isInstance( entityIdentifier.getIdentifierGenerator() ) ) { + ( (PersistentIdentifierGenerator) entityIdentifier.getIdentifierGenerator() ).registerExportables( metadata.getDatabase() ); + } + } + + private SingularAttributeBinding bindIdentifierAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return bindSingularAttribute( attributeBindingContainer, attributeSource, true ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Attributes binding relates methods + private void bindAttributes( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSourceContainer attributeSourceContainer) { + for ( final AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) { + bindAttribute( attributeBindingContainer, attributeSource ); + } + } + + private void bindAttributes( + final CompositeAttributeBindingContainer compositeAttributeBindingContainer, + final AttributeSourceContainer attributeSourceContainer) { + if ( compositeAttributeBindingContainer.getParentReference() == null ) { + bindAttributes( + (AttributeBindingContainer) compositeAttributeBindingContainer, + attributeSourceContainer + ); + } + else { + for ( final AttributeSource subAttributeSource : attributeSourceContainer.attributeSources() ) { + if ( !subAttributeSource.getName() + .equals( compositeAttributeBindingContainer.getParentReference().getName() ) ) { + bindAttribute( + compositeAttributeBindingContainer, + subAttributeSource + ); + } + } + } + + } + + private AttributeBinding bindAttribute( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSource attributeSource) { + // Return existing binding if available + final String attributeName = attributeSource.getName(); + final AttributeBinding attributeBinding = attributeBindingContainer.locateAttributeBinding( attributeName ); + if ( attributeBinding != null ) { + return attributeBinding; + } + return attributeSource.isSingular() ? + bindSingularAttribute( + attributeBindingContainer, + SingularAttributeSource.class.cast( attributeSource ), + false + ) : + bindPluralAttribute( attributeBindingContainer, PluralAttributeSource.class.cast( attributeSource ) ); + } + + private BasicAttributeBinding bindBasicAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + final List relationalValueBindings = + relationalValueBindingHelper.createRelationalValueBindings( + attributeBindingContainer, + attributeSource, + attribute, + locateDefaultTableSpecificationForAttribute( attributeBindingContainer, attributeSource ), + false + ); + final BasicAttributeBinding attributeBinding = + attributeBindingContainer.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getGeneration() + ); + typeHelper.bindSingularAttributeType( + attributeSource, + attributeBinding + ); + return attributeBinding; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ singular attributes binding + private SingularAttributeBinding bindSingularAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource, + final boolean isIdentifierAttribute) { + final SingularAttributeSource.Nature nature = attributeSource.getNature(); + final SingularAttribute attribute = + attributeBindingContainer.getAttributeContainer().locateSingularAttribute( attributeSource.getName() ); + switch ( nature ) { + case BASIC: + return bindBasicAttribute( attributeBindingContainer, attributeSource, attribute ); + case ONE_TO_ONE: + return bindOneToOneAttribute( + attributeBindingContainer, + ToOneAttributeSource.class.cast( attributeSource ), + attribute + ); + case MANY_TO_ONE: + return bindManyToOneAttribute( + attributeBindingContainer, + ToOneAttributeSource.class.cast( attributeSource ), + attribute + ); + case COMPOSITE: + return bindAggregatedCompositeAttribute( + attributeBindingContainer, + ComponentAttributeSource.class.cast( attributeSource ), + attribute, + isIdentifierAttribute + ); + default: + throw new NotYetImplementedException( nature.toString() ); + } + } + + private CompositeAttributeBinding bindAggregatedCompositeAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ComponentAttributeSource attributeSource, + SingularAttribute attribute, + boolean isAttributeIdentifier) { + CompositeAttributeBinding attributeBinding = createAggregatedCompositeAttribute( + attributeBindingContainer, attributeSource, attribute + ); + bindAttributes( attributeBinding, attributeSource ); + typeHelper.bindAggregatedCompositeAttributeType( + isAttributeIdentifier, + (Aggregate) attributeBinding.getAttribute().getSingularAttributeType(), + null, // TODO: don't have the default value at this point; shouldn't be needed... + attributeBinding + ); + return attributeBinding; + } + + private CompositeAttributeBinding createAggregatedCompositeAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ComponentAttributeSource attributeSource, + SingularAttribute attribute) { + final Aggregate composite; + final ValueHolder> defaultJavaClassReference; + if ( attribute == null ) { + if ( attributeSource.getClassName() != null ) { + composite = new Aggregate( + attributeSource.getPath(), + attributeSource.getClassName(), + attributeSource.getClassReference() != null ? + attributeSource.getClassReference() : + bindingContext().makeClassReference( attributeSource.getClassName() ), + null + ); + // no need for a default because there's an explicit class name provided + } + else { + defaultJavaClassReference = createSingularAttributeJavaType( + attributeBindingContainer.getClassReference(), attributeSource.getName() + ); + composite = new Aggregate( + attributeSource.getPath(), + defaultJavaClassReference.getValue().getName(), + defaultJavaClassReference, + null + ); + } + attribute = attributeBindingContainer.getAttributeContainer().createCompositeAttribute( + attributeSource.getName(), + composite + ); + } + else { + composite = (Aggregate) attribute.getSingularAttributeType(); + } + + final SingularAttribute referencingAttribute = + StringHelper.isEmpty( attributeSource.getParentReferenceAttributeName() ) ? + null : + composite.createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); + final NaturalIdMutability naturalIdMutability = attributeSource.getNaturalIdMutability(); + final CompositeAttributeBinding attributeBinding = + attributeBindingContainer.makeAggregatedCompositeAttributeBinding( + attribute, + referencingAttribute, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + naturalIdMutability, + createMetaAttributeContext( attributeBindingContainer, attributeSource ) + ); + if ( attributeSource.getExplicitTuplizerClassName() != null ) { + Class tuplizerClass = bindingContext().getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( attributeSource.getExplicitTuplizerClassName() ); + attributeBinding.setCustomComponentTuplizerClass( tuplizerClass ); + } + return attributeBinding; + } + + /** + * todo: if the not found exception is ignored, here we should create an unique key instead of FK + * this guard method should be removed after we implement this. + */ + private void throwExceptionIfNotFoundIgnored(boolean isNotFoundAnException) { + if ( !isNotFoundAnException ) { + throw new NotYetImplementedException( "association of ignored not found exception is not yet implemented" ); + } + } + + private ManyToOneAttributeBinding bindManyToOneAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + throwExceptionIfNotFoundIgnored( attributeSource.isNotFoundAnException() ); + + final ValueHolder> referencedEntityJavaTypeValue = createSingularAttributeJavaType( attribute ); + final EntityBinding referencedEntityBinding = locateEntityBinding( + referencedEntityJavaTypeValue, + attributeSource.getReferencedEntityName() + ); + + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + + //now find the referenced attribute binding, either the referenced entity's id attribute or the referenced attribute + //todo referenced entityBinding null check? + final SingularAttributeBinding referencedAttributeBinding = resolver.resolveManyToOneReferencedAttributeBinding( + attributeBindingContainer, + attributeSource, + referencedEntityBinding + ); + + // todo : currently a chicken-egg problem here between creating the attribute binding and binding its FK values... + // now we have everything to create the attribute binding + final ManyToOneAttributeBinding attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.isNotFoundAnException(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + referencedEntityBinding, + referencedAttributeBinding + ); + + /** + * this is not correct, here, if no @JoinColumn defined, we simply create the FK column only with column calucated + * but what we should do is get all the column info from the referenced column(s), including nullable, size etc. + */ + final List relationalValueBindings = resolver.resolveManyToOneRelationalValueBindings( + attributeSource, + attributeBindingContainer, + referencedAttributeBinding, + referencedEntityBinding + ); + final ForeignKey foreignKey = + relationalValueBindings.isEmpty() || relationalValueBindingHelper.hasDerivedValue( relationalValueBindings ) ? + null : + resolver.resolveManyToOneForeignKey( + attributeSource, + attributeBindingContainer, + relationalValueBindings, + referencedEntityBinding + ); + attributeBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + + // Type resolution... + if ( !attribute.isTypeResolved() ) { + attribute.resolveType( referencedEntityBinding.getEntity() ); + } + + if ( referencedAttributeBinding != referencedEntityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() ) { + referencedAttributeBinding.setAlternateUniqueKey( true ); + } + + final SingularNonAssociationAttributeBinding idAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + final String uniqueKeyAttributeName = idAttributeBinding == referencedAttributeBinding ? + null : + getRelativePathFromEntityName( referencedAttributeBinding ); + + final Type resolvedType = metadata.getTypeResolver().getTypeFactory().manyToOne( + referencedEntityBinding.getEntity().getName(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + !attributeSource.isNotFoundAnException(), + attributeSource.isUnique() + ); + typeHelper.bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + attributeSource.getTypeInformation(), + referencedEntityJavaTypeValue.getValue().getName(), + resolvedType + ); + + typeHelper.bindJdbcDataType( + attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + attributeBinding.getRelationalValueBindings() + ); + + bindToOneDetails( attributeSource, attributeBinding ); + + return attributeBinding; + } + + private OneToOneAttributeBinding bindOneToOneAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + + final ValueHolder> referencedEntityJavaTypeValue = createSingularAttributeJavaType( attribute ); + final EntityBinding referencedEntityBinding = locateEntityBinding( + referencedEntityJavaTypeValue, + attributeSource.getReferencedEntityName() + ); + + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + + //now find the referenced attribute binding, either the referenced entity's id attribute or the referenced attribute + //todo referenced entityBinding null check? + final SingularAttributeBinding referencedAttributeBinding = resolver.resolveOneToOneReferencedAttributeBinding( + attributeSource, + referencedEntityBinding + ); + // todo : currently a chicken-egg problem here between creating the attribute binding and binding its FK values... + // now we have everything to create the attribute binding + final OneToOneAttributeBinding attributeBinding = attributeBindingContainer.makeOneToOneAttributeBinding( + attribute, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + referencedEntityBinding, + referencedAttributeBinding, + attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT + ); + + /** + * this is not correct, here, if no @JoinColumn defined, we simply create the FK column only with column calucated + * but what we should do is get all the column info from the referenced column(s), including nullable, size etc. + */ + final List relationalValueBindings = resolver.resolveOneToOneRelationalValueBindings( + attributeSource, + attributeBindingContainer, + referencedAttributeBinding + ); + final ForeignKey foreignKey; + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { + foreignKey = resolver.resolveOneToOneForeignKey( + attributeSource, + attributeBinding.getContainer().getPrimaryTable(), + attributeBinding.getContainer().getPrimaryTable().getPrimaryKey().getColumns(), + referencedEntityBinding + ); + } + else { + foreignKey = null; + } + attributeBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + + // Type resolution... + if ( !attribute.isTypeResolved() ) { + attribute.resolveType( referencedEntityBinding.getEntity() ); + } + + final String uniqueKeyAttributeName; + final AttributeBinding referencedEntityIdAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + if ( referencedEntityIdAttributeBinding == referencedAttributeBinding || + referencedAttributeBinding.getRelationalValueBindings().isEmpty()) { + uniqueKeyAttributeName = null; + } + else { + uniqueKeyAttributeName = getRelativePathFromEntityName( referencedAttributeBinding ); + } + final Type resolvedType; + if ( attributeSource.isMappedBy() || attributeSource.relationalValueSources().isEmpty() ) { + resolvedType = metadata.getTypeResolver().getTypeFactory().oneToOne( + referencedEntityBinding.getEntity().getName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + attribute.getName() + ); + } + else { + resolvedType = metadata.getTypeResolver().getTypeFactory().specialOneToOne( + referencedEntityBinding.getEntity().getName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + attribute.getName() + ); + } + + typeHelper.bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + attributeSource.getTypeInformation(), + referencedEntityJavaTypeValue.getValue().getName(), + resolvedType + ); + if ( !attributeBinding.getRelationalValueBindings().isEmpty() ) { + typeHelper.bindJdbcDataType( + attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + attributeBinding.getRelationalValueBindings() + ); + } + bindToOneDetails( attributeSource, attributeBinding ); + + return attributeBinding; + } + + private void bindToOneDetails( + final ToOneAttributeSource attributeSource, + final SingularAssociationAttributeBinding attributeBinding) { + final SingularAttributeBinding idAttributeBinding = + attributeBinding.getReferencedEntityBinding().getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + if ( attributeBinding.getReferencedAttributeBinding() != idAttributeBinding ) { + attributeBinding.getReferencedAttributeBinding().setAlternateUniqueKey( true ); + } + attributeBinding.setCascadeStyle( determineCascadeStyle( attributeSource.getCascadeStyles() ) ); + attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); + attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ plural attributes binding + private AbstractPluralAttributeBinding bindPluralAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource) { + final PluralAttributeSource.Nature nature = attributeSource.getNature(); + final PluralAttribute attribute = + attributeBindingContainer.getAttributeContainer().locatePluralAttribute( attributeSource.getName() ); + final AbstractPluralAttributeBinding attributeBinding; + switch ( nature ) { + case BAG: + attributeBinding = bindBagAttribute( attributeBindingContainer, attributeSource, attribute ); + break; + case SET: + attributeBinding = bindSetAttribute( attributeBindingContainer, attributeSource, attribute ); + break; + case LIST: + attributeBinding = bindListAttribute( + attributeBindingContainer, + (IndexedPluralAttributeSource) attributeSource, + attribute + ); + break; + case MAP: + attributeBinding = bindMapAttribute( + attributeBindingContainer, + attributeSource, + attribute + ); + break; + case ARRAY: + attributeBinding = bindArrayAttribute( + attributeBindingContainer, + (IndexedPluralAttributeSource) attributeSource, + attribute + ); + break; + default: + throw new NotYetImplementedException( nature.toString() ); + } + + // Must do first -- sorting/ordering can determine the resolved type + // (ex: Set vs. SortedSet). + bindSortingAndOrdering( attributeBinding, attributeSource ); + + if ( attributeSource.getFilterSources() != null ) { + for ( final FilterSource filterSource : attributeSource.getFilterSources() ) { + attributeBinding.addFilterConfiguration( createFilterConfiguration( filterSource, null ) ); + } + } + + // Note: Collection types do not have a relational model + attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); + attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); + if ( attributeSource.getFetchStyle() == FetchStyle.SUBSELECT ) { + attributeBindingContainer.seekEntityBinding().setSubselectLoadableCollections( true ); + } + attributeBinding.setCaching( attributeSource.getCaching() ); + if ( StringHelper.isNotEmpty( attributeSource.getCustomPersisterClassName() ) ) { + attributeBinding.setExplicitPersisterClass( + bindingContext().locateClassByName( + attributeSource.getCustomPersisterClassName() + ) + ); + } + attributeBinding.setCustomLoaderName( attributeSource.getCustomLoaderName() ); + attributeBinding.setCustomSqlInsert( attributeSource.getCustomSqlInsert() ); + attributeBinding.setCustomSqlUpdate( attributeSource.getCustomSqlUpdate() ); + attributeBinding.setCustomSqlDelete( attributeSource.getCustomSqlDelete() ); + attributeBinding.setCustomSqlDeleteAll( attributeSource.getCustomSqlDeleteAll() ); + attributeBinding.setWhere( attributeSource.getWhere() ); + attributeBinding.setMutable( attributeSource.isMutable() ); + attributeBinding.setBatchSize( attributeSource.getBatchSize() ); + ReflectedCollectionJavaTypes reflectedCollectionJavaTypes = HibernateTypeHelper.getReflectedCollectionJavaTypes( + attributeBinding + ); + switch ( attributeSource.getElementSource().getNature() ) { + case BASIC: + bindBasicPluralAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case ONE_TO_MANY: + bindOneToManyAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case MANY_TO_MANY: + bindManyToManyAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case AGGREGATE: + bindPluralAggregateAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case MANY_TO_ANY: + //todo?? + default: + throw bindingContext().makeMappingException( + String.format( + "Unknown type of collection element: %s", + attributeSource.getElementSource().getNature() + ) + ); + } + // Cannot resolve plural attribute type until after the element binding is bound. + final Type resolvedType = typeHelper.resolvePluralType( attributeBinding, attributeSource, nature ); + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + typeHelper.bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + attributeSource.getTypeInformation(), + HibernateTypeHelper.defaultCollectionJavaTypeName( reflectedCollectionJavaTypes, attributeSource ), + resolvedType + ); + if ( attributeBinding.hasIndex() ) { + bindPluralAttributeIndex( + (IndexedPluralAttributeSource) attributeSource, + (IndexedPluralAttributeBinding) attributeBinding, + reflectedCollectionJavaTypes + ); + } + bindCollectionTablePrimaryKey( attributeBinding, attributeSource ); + metadata.addCollection( attributeBinding ); + return attributeBinding; + } + + private AbstractPluralAttributeBinding bindBagAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createBag( attributeSource.getName() ); + } + return attributeBindingContainer.makeBagAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ) + ); + } + + private AbstractPluralAttributeBinding bindListAttribute( + final AttributeBindingContainer attributeBindingContainer, + final IndexedPluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createList( attributeSource.getName() ); + } + return attributeBindingContainer.makeListAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + getSequentialPluralAttributeIndexBase( attributeSource ) + ); + } + + private AbstractPluralAttributeBinding bindArrayAttribute( + final AttributeBindingContainer attributeBindingContainer, + final IndexedPluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createArray( attributeSource.getName() ); + } + return attributeBindingContainer.makeArrayAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + getSequentialPluralAttributeIndexBase( attributeSource ) + ); + } + + private int getSequentialPluralAttributeIndexBase(IndexedPluralAttributeSource pluralAttributeSource) { + final PluralAttributeIndexSource indexedPluralAttributeSource = pluralAttributeSource.getIndexSource(); + if ( ! SequentialPluralAttributeIndexSource.class.isInstance( indexedPluralAttributeSource ) ) { + throw new IllegalArgumentException( + String.format( + "Expected an argument of type: %s; instead, got %s", + SequentialPluralAttributeIndexSource.class.getName(), + indexedPluralAttributeSource.getClass().getName() + ) + ); + } + return ( (SequentialPluralAttributeIndexSource) indexedPluralAttributeSource ).base(); + } + + private AbstractPluralAttributeBinding bindMapAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createMap( attributeSource.getName() ); + } + return attributeBindingContainer.makeMapAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + pluralAttributeIndexNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + + createMetaAttributeContext( attributeBindingContainer, attributeSource ) + ); + } + + private AbstractPluralAttributeBinding bindSetAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createSet( attributeSource.getName() ); + } + return attributeBindingContainer.makeSetAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ) + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ collection attributes binding + + private void bindBasicCollectionElement( + final BasicPluralAttributeElementBinding elementBinding, + final BasicPluralAttributeElementSource elementSource, + final String defaultElementJavaTypeName) { + bindBasicPluralElementRelationalValues( elementSource, elementBinding ); + typeHelper.bindBasicCollectionElementType( elementBinding, elementSource, defaultElementJavaTypeName ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( + bindingContext().makeJavaType( elementBinding.getHibernateTypeDescriptor().getJavaTypeName() ) + ); + } + + private void bindNonAssociationCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.BASIC && + attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.AGGREGATE ) { + throw new AssertionFailure( + String.format( + "Expected basic or aggregate attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + attributeBinding.getPluralAttributeKeyBinding().setInverse( false ); + TableSpecification collectionTable = tableHelper.createTable( + attributeSource.getCollectionTableSpecificationSource(), + new CollectionTableNamingStrategyHelper( attributeBinding ) + ); + if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableComment() ) ) { + collectionTable.addComment( attributeSource.getCollectionTableComment() ); + } + if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableCheck() ) ) { + collectionTable.addCheckConstraint( attributeSource.getCollectionTableCheck() ); + } + bindCollectionTableJoinRelationalValueBindings( + attributeBinding, + attributeSource, + collectionTable + ); + } + + private void bindCompositeCollectionElement( + final CompositePluralAttributeElementBinding elementBinding, + final CompositePluralAttributeElementSource elementSource, + final String defaultElementJavaTypeName) { + final PluralAttributeBinding pluralAttributeBinding = elementBinding.getPluralAttributeBinding(); + ValueHolder> defaultElementJavaClassReference = null; + // Create the aggregate type + // TODO: aggregateName should be set to elementSource.getPath() (which is currently not implemented) + // or Binder should define AttributeBindingContainer paths instead. + String aggregateName = pluralAttributeBinding.getAttribute().getRole() + ".element"; + final Aggregate aggregate; + if ( elementSource.getClassName() != null ) { + aggregate = new Aggregate( + aggregateName, + elementSource.getClassName(), + elementSource.getClassReference() != null ? + elementSource.getClassReference() : + bindingContext().makeClassReference( elementSource.getClassName() ), + null + ); + } + else { + defaultElementJavaClassReference = bindingContext().makeClassReference( defaultElementJavaTypeName ); + aggregate = new Aggregate( + aggregateName, + defaultElementJavaClassReference.getValue().getName(), + defaultElementJavaClassReference, + null + ); + } + final SingularAttribute parentAttribute = + StringHelper.isEmpty( elementSource.getParentReferenceAttributeName() ) ? + null : + aggregate.createSingularAttribute( elementSource.getParentReferenceAttributeName() ); + final CompositeAttributeBindingContainer compositeAttributeBindingContainer = + elementBinding.createCompositeAttributeBindingContainer( + aggregate, + createMetaAttributeContext( + pluralAttributeBinding.getContainer(), + elementSource.getMetaAttributeSources() + ), + parentAttribute + ); + + bindAttributes( compositeAttributeBindingContainer, elementSource ); + pluralAttributeBinding.getAttribute().setElementType( aggregate ); + Type resolvedType = metadata.getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( compositeAttributeBindingContainer, false, false ) + ); + // TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already + typeHelper.bindHibernateTypeDescriptor( + elementBinding.getHibernateTypeDescriptor(), + aggregate.getClassName(), + null, + defaultElementJavaClassReference == null ? null : defaultElementJavaClassReference.getValue().getName(), + resolvedType + ); + /** + * TODO + * don't know why, but see org.hibernate.mapping.Property#getCompositeCascadeStyle + * + * and not sure if this is the right place to apply this logic, apparently source level is not okay, so here it is, for now. + */ + for ( AttributeBinding ab : compositeAttributeBindingContainer.attributeBindings() ) { + if ( ab.isCascadeable() ) { + final Cascadeable cascadeable; + if ( ab.getAttribute().isSingular() ) { + cascadeable = Cascadeable.class.cast( ab ); + } + else { + cascadeable = Cascadeable.class.cast( ( (PluralAttributeBinding) ab ).getPluralAttributeElementBinding() ); + } + CascadeStyle cascadeStyle = cascadeable.getCascadeStyle(); + if ( cascadeStyle != CascadeStyles.NONE ) { + elementBinding.setCascadeStyle( CascadeStyles.ALL ); + } + } + } + if ( elementBinding.getCascadeStyle() == null || elementBinding.getCascadeStyle() == CascadeStyles.NONE ) { + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + } + } + + private void bindEntityAttributePluralAttributeIndex( + final IndexedPluralAttributeBinding attributeBinding, + final EntityAttributePluralAttributeIndexSource indexSource, + final String defaultIndexJavaTypeName) { + throw new NotYetImplementedException( "Plural attribute index that is an attribute of the referenced entity is not supported yet." ); + } + + private void bindBasicCollectionIndex( + final IndexedPluralAttributeBinding attributeBinding, + final BasicPluralAttributeIndexSource indexSource, + final String defaultIndexJavaTypeName) { + final BasicPluralAttributeIndexBinding indexBinding = + (BasicPluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(); + // TODO: need to resolve default column names. + indexBinding.setRelationalValueBindings( + relationalValueBindingHelper.createRelationalValueBindings( + attributeBinding.getContainer(), + indexSource, + attributeBinding.getPluralAttributeKeyBinding().getCollectionTable(), + indexSource.getDefaultNamingStrategies(), + attributeBinding.getPluralAttributeElementBinding() + .getNature() != PluralAttributeElementBinding.Nature.ONE_TO_MANY + ) + ); + // TODO: create a foreign key if non-inverse and the index is an association + + typeHelper.bindHibernateTypeDescriptor( + indexBinding.getHibernateTypeDescriptor(), + indexSource.getTypeInformation(), + defaultIndexJavaTypeName + ); + typeHelper.bindJdbcDataType( + indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + indexBinding.getRelationalValueBindings() + ); + IndexedPluralAttribute indexedPluralAttribute = + (IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute(); + indexedPluralAttribute.setIndexType( + bindingContext().makeJavaType( indexBinding.getHibernateTypeDescriptor().getJavaTypeName() ) + ); + } + + private void bindCompositeCollectionIndex( + final CompositePluralAttributeIndexBinding indexBinding, + final IndexedPluralAttributeSource indexedPluralAttributeSource, + final String defaultIndexJavaTypeName) { + final PluralAttributeBinding pluralAttributeBinding = indexBinding.getIndexedPluralAttributeBinding(); + final CompositePluralAttributeIndexSource indexSource = + (CompositePluralAttributeIndexSource) indexedPluralAttributeSource.getIndexSource(); + ValueHolder> defaultElementJavaClassReference = null; + // Create the aggregate type + // TODO: aggregateName should be set to elementSource.getPath() (which is currently not implemented) + // or Binder should define AttributeBindingContainer paths instead. + String aggregateName = pluralAttributeBinding.getAttribute().getRole() + ".index"; + final Aggregate aggregate; + if ( indexSource.getClassName() != null ) { + aggregate = new Aggregate( + aggregateName, + indexSource.getClassName(), + indexSource.getClassReference() != null ? + indexSource.getClassReference() : + bindingContext().makeClassReference( indexSource.getClassName() ), + null + ); + } + else { + defaultElementJavaClassReference = bindingContext().makeClassReference( defaultIndexJavaTypeName ); + aggregate = new Aggregate( + aggregateName, + defaultElementJavaClassReference.getValue().getName(), + defaultElementJavaClassReference, + null + ); + } + final CompositeAttributeBindingContainer compositeAttributeBindingContainer = + indexBinding.createCompositeAttributeBindingContainer( + aggregate, + null, + null + ); + + bindAttributes( compositeAttributeBindingContainer, indexSource ); + + Type resolvedType = metadata.getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( compositeAttributeBindingContainer, false, false ) + ); + // TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already + typeHelper.bindHibernateTypeDescriptor( + indexBinding.getHibernateTypeDescriptor(), + aggregate.getClassName(), + null, + defaultElementJavaClassReference == null ? null : defaultElementJavaClassReference.getValue().getName(), + resolvedType + ); + IndexedPluralAttribute indexedPluralAttribute = + (IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute(); + indexedPluralAttribute.setIndexType( aggregate ); + } + + private void bindOneToManyCollectionElement( + final OneToManyPluralAttributeElementBinding elementBinding, + final OneToManyPluralAttributeElementSource elementSource, + final EntityBinding referencedEntityBinding, + final String defaultElementJavaTypeName) { + throwExceptionIfNotFoundIgnored( elementSource.isNotFoundAnException() ); + elementBinding.setElementEntityIdentifier( + referencedEntityBinding.getKeyRelationalValueBindings() + ); + + Type resolvedElementType = metadata.getTypeResolver().getTypeFactory().manyToOne( + referencedEntityBinding.getEntity().getName(), + true, + null, + false, + false, + !elementSource.isNotFoundAnException(), //TODO: should be attributeBinding.isIgnoreNotFound(), + false + ); + final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); + typeHelper.bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + referencedEntityBinding.getEntity().getName(), + null, + defaultElementJavaTypeName, + resolvedElementType + ); + // no need to bind JDBC data types because element is referenced EntityBinding's ID + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() ); + } + + private void bindManyToManyCollectionElement( + final ManyToManyPluralAttributeElementBinding elementBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final EntityBinding referencedEntityBinding, + final String defaultElementJavaTypeName) { + throwExceptionIfNotFoundIgnored( elementSource.isNotFoundAnException() ); + final TableSpecification collectionTable = + elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(); + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( + elementSource.getAttributeSource() + ); + final List relationalValueBindings = + resolver.resolveManyToManyElementRelationalValueBindings( + elementBinding.getPluralAttributeBinding().getContainer().seekEntityBinding(), + elementSource, + collectionTable, + referencedEntityBinding + ); + final ForeignKey foreignKey; + if ( !elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().isInverse() && + !relationalValueBindingHelper.hasDerivedValue( relationalValueBindings ) ) { + foreignKey = resolver.resolveManyToManyElementForeignKey( + elementBinding.getPluralAttributeBinding().getContainer().seekEntityBinding(), + elementSource, + collectionTable, + relationalValueBindings, + referencedEntityBinding + ); + } + else { + foreignKey = null; + } + if ( elementSource.isUnique() ) { + final List columns = new ArrayList(); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( ! relationalValueBinding.isDerived() ) { + columns.add( (Column) relationalValueBinding.getValue() ); + } + } + tableHelper.createUniqueKey( collectionTable, columns, null ); + } + elementBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + typeHelper.bindManyToManyAttributeType( + elementBinding, + elementSource, + referencedEntityBinding, + defaultElementJavaTypeName + ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() ); + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + elementBinding.setManyToManyWhere( elementSource.getWhere() ); + elementBinding.setManyToManyOrderBy( elementSource.getOrder() ); + elementBinding.setFetchMode( elementSource.getFetchTiming() == FetchTiming.IMMEDIATE ? FetchMode.JOIN : FetchMode.SELECT ); + //TODO: initialize filters from elementSource + } + + private void bindOneToManyCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final EntityBinding referencedEntityBinding) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.ONE_TO_MANY ) { + throw new AssertionFailure( + String.format( + "Expected one-to-many attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + // By definition, a one-to-many can only be on a foreign key, so the + // collection table is the referenced entity binding's primary table. + final TableSpecification collectionTable = referencedEntityBinding.getPrimaryTable(); + final boolean isInverse = attributeSource.isInverse(); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + keyBinding.setInverse( isInverse ); + bindCollectionTableJoinRelationalValueBindings( attributeBinding, attributeSource, collectionTable ); + } + + private void bindManyToManyCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final EntityBinding referencedEntityBinding) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.MANY_TO_MANY ) { + throw new AssertionFailure( + String.format( + "Expected many-to-many attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + final TableSpecification collectionTable = resolver.resolveManyToManyCollectionTable( + attributeSource, + createAttributePath( attributeBinding ), + attributeBinding.getContainer().seekEntityBinding(), + referencedEntityBinding + ); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + keyBinding.setInverse( attributeSource.isInverse() ); + bindCollectionTableJoinRelationalValueBindings( attributeBinding, attributeSource, collectionTable ); + } + + private void bindPluralAttributeIndex( + final IndexedPluralAttributeSource attributeSource, + final IndexedPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final String defaultCollectionIndexJavaTypeName = + HibernateTypeHelper.defaultCollectionIndexJavaTypeName( reflectedCollectionJavaTypes ); + final PluralAttributeIndexSource indexSource = attributeSource.getIndexSource(); + if ( indexSource.isReferencedEntityAttribute() ) { + bindEntityAttributePluralAttributeIndex( + attributeBinding, + (EntityAttributePluralAttributeIndexSource) indexSource, + defaultCollectionIndexJavaTypeName + ); + } + else { + switch ( attributeSource.getIndexSource().getNature() ) { + case BASIC: { + bindBasicCollectionIndex( + attributeBinding, + (BasicPluralAttributeIndexSource) attributeSource.getIndexSource(), + defaultCollectionIndexJavaTypeName + ); + break; + } + case AGGREGATE: { + bindCompositeCollectionIndex( + (CompositePluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(), + attributeSource, + defaultCollectionIndexJavaTypeName + ); + break; + } + default: { + throw new NotYetImplementedException( + String.format( + "%s collection indexes are not supported yet.", + attributeSource.getIndexSource().getNature() + ) + ); + } + } + if ( attributeBinding.getPluralAttributeElementBinding() + .getNature() == PluralAttributeElementBinding.Nature.ONE_TO_MANY ) { + for ( RelationalValueBinding relationalValueBinding : attributeBinding.getPluralAttributeIndexBinding().getRelationalValueBindings() ) { + if ( Column.class.isInstance( relationalValueBinding.getValue() ) ) { + // TODO: fix this when column nullability is refactored + Column column = (Column) relationalValueBinding.getValue(); + column.setNullable( true ); + } + } + } + } + } + + private void bindPluralAggregateAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + bindNonAssociationCollectionKey( attributeBinding, attributeSource ); + bindCompositeCollectionElement( + (CompositePluralAttributeElementBinding) attributeBinding.getPluralAttributeElementBinding(), + (CompositePluralAttributeElementSource) attributeSource.getElementSource(), + HibernateTypeHelper.defaultCollectionElementJavaTypeName( reflectedCollectionJavaTypes ) + ); + } + + private void bindManyToManyAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final ManyToManyPluralAttributeElementSource elementSource = + (ManyToManyPluralAttributeElementSource) attributeSource.getElementSource(); + final String defaultElementJavaTypeName = HibernateTypeHelper.defaultCollectionElementJavaTypeName( + reflectedCollectionJavaTypes + ); + String referencedEntityName = + elementSource.getReferencedEntityName() != null ? + elementSource.getReferencedEntityName() : + defaultElementJavaTypeName; + if ( referencedEntityName == null ) { + throw bindingContext().makeMappingException( + String.format( + "The mapping for the entity associated with one-to-many attribute (%s) is undefined.", + createAttributePathQualifiedByEntityName( attributeBinding ) + ) + ); + } + EntityBinding referencedEntityBinding = locateEntityBinding( referencedEntityName ); + ManyToManyPluralAttributeElementBinding manyToManyPluralAttributeElementBinding = (ManyToManyPluralAttributeElementBinding) attributeBinding + .getPluralAttributeElementBinding(); + + if ( elementSource.getFilterSources() != null ) { + for ( FilterSource filterSource : elementSource.getFilterSources() ) { + manyToManyPluralAttributeElementBinding.addFilterConfiguration( + createFilterConfiguration( + filterSource, + null + ) + ); + } + } + bindManyToManyCollectionKey( attributeBinding, attributeSource, referencedEntityBinding ); + bindManyToManyCollectionElement( + manyToManyPluralAttributeElementBinding, + (ManyToManyPluralAttributeElementSource) attributeSource.getElementSource(), + referencedEntityBinding, + defaultElementJavaTypeName + ); + } + + private void bindOneToManyAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final OneToManyPluralAttributeElementSource elementSource = + (OneToManyPluralAttributeElementSource) attributeSource.getElementSource(); + final String defaultElementJavaTypeName = HibernateTypeHelper.defaultCollectionElementJavaTypeName( + reflectedCollectionJavaTypes + ); + String referencedEntityName = + elementSource.getReferencedEntityName() != null ? + elementSource.getReferencedEntityName() : + defaultElementJavaTypeName; + if ( referencedEntityName == null ) { + throw bindingContext().makeMappingException( + String.format( + "The mapping for the entity associated with one-to-many attribute (%s) is undefined.", + createAttributePathQualifiedByEntityName( attributeBinding ) + ) + ); + } + EntityBinding referencedEntityBinding = locateEntityBinding( referencedEntityName ); + bindOneToManyCollectionKey( attributeBinding, attributeSource, referencedEntityBinding ); + bindOneToManyCollectionElement( + (OneToManyPluralAttributeElementBinding) attributeBinding.getPluralAttributeElementBinding(), + (OneToManyPluralAttributeElementSource) attributeSource.getElementSource(), + referencedEntityBinding, + defaultElementJavaTypeName + ); + } + + private void bindBasicPluralAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + bindNonAssociationCollectionKey( attributeBinding, attributeSource ); + bindBasicCollectionElement( + (BasicPluralAttributeElementBinding) attributeBinding.getPluralAttributeElementBinding(), + (BasicPluralAttributeElementSource) attributeSource.getElementSource(), + HibernateTypeHelper.defaultCollectionElementJavaTypeName( reflectedCollectionJavaTypes ) + ); + } + + + private void bindSortingAndOrdering( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + if ( Sortable.class.isInstance( attributeSource ) ) { + final Sortable sortable = (Sortable) attributeSource; + attributeBinding.setSorted( sortable.isSorted() ); + if ( sortable.isSorted() + && !sortable.getComparatorName().equalsIgnoreCase( "natural" ) ) { + Class> comparatorClass = + bindingContext().locateClassByName( sortable.getComparatorName() ); + try { + attributeBinding.setComparator( comparatorClass.newInstance() ); + } + catch ( Exception error ) { + throw bindingContext().makeMappingException( + String.format( + "Unable to create comparator [%s] for attribute [%s]", + sortable.getComparatorName(), + attributeSource.getName() + ), + error + ); + } + } + } + if ( Orderable.class.isInstance( attributeSource ) ) { + final Orderable orderable = (Orderable) attributeSource; + if ( orderable.isOrdered() ) { + attributeBinding.setOrderBy( orderable.getOrder() ); + + } + } + } + + private SingularAttributeBinding determinePluralAttributeKeyReferencedBinding( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource) { + return getAssociationRelationalBindingResolver( attributeSource ).resolvePluralAttributeKeyReferencedBinding( + attributeBindingContainer, + attributeSource + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ relational binding relates methods + private void bindBasicPluralElementRelationalValues( + final RelationalValueSourceContainer relationalValueSourceContainer, + final BasicPluralAttributeElementBinding elementBinding) { + elementBinding.setRelationalValueBindings( + relationalValueBindingHelper.createRelationalValueBindings( + elementBinding.getPluralAttributeBinding().getContainer(), + relationalValueSourceContainer, + elementBinding.getPluralAttributeBinding().getAttribute(), + elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + false + ) + ); + } + + private void bindSetCollectionTablePrimaryKey(final SetBinding attributeBinding) { + // only bind the primary key if there is a non-nullable element value. + if ( !attributeBinding.getPluralAttributeElementBinding().hasNonNullableValue() ) { + return; + } + + + final PluralAttributeElementBinding elementBinding = attributeBinding.getPluralAttributeElementBinding(); + final PrimaryKey primaryKey = attributeBinding.getPluralAttributeKeyBinding() + .getCollectionTable() + .getPrimaryKey(); + final List keyValueBindings = + attributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings(); + for ( final RelationalValueBinding keyRelationalValueBinding : keyValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( final RelationalValueBinding elementValueBinding : elementBinding.getRelationalValueBindings() ) { + if ( !elementValueBinding.isDerived() && !elementValueBinding.isNullable() ) { + primaryKey.addColumn( (Column) elementValueBinding.getValue() ); + } + } + } + + private void bindCollectionTableJoinRelationalValueBindings( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final TableSpecification collectionTable) { + + final EntityBinding referencedEntityBinding = attributeBinding.getContainer().seekEntityBinding(); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + final List sourceRelationalBindings = + resolver.resolvePluralAttributeKeyRelationalValueBindings( + attributeSource, + attributeBinding.getContainer().seekEntityBinding(), + collectionTable, + referencedEntityBinding + ); + + final ForeignKey foreignKey = resolver.resolvePluralAttributeKeyForeignKey( + attributeSource, + attributeBinding.getContainer().seekEntityBinding(), + collectionTable, + sourceRelationalBindings, + referencedEntityBinding + ); + keyBinding.setJoinRelationalValueBindings( sourceRelationalBindings, foreignKey ); + + final HibernateTypeDescriptor pluralAttributeKeyTypeDescriptor = keyBinding.getHibernateTypeDescriptor(); + + pluralAttributeKeyTypeDescriptor.copyFrom( + keyBinding.getReferencedAttributeBinding() + .getHibernateTypeDescriptor() + ); + final Type resolvedKeyType = pluralAttributeKeyTypeDescriptor.getResolvedTypeMapping(); + typeHelper.bindJdbcDataType( resolvedKeyType, keyBinding.getRelationalValueBindings() ); + } + + /** + * TODO : It is really confusing that we have so many different natures + */ + private void bindCollectionTablePrimaryKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + final PluralAttributeSource.Nature pluralAttributeSourceNature = attributeSource.getNature(); + final PluralAttributeElementSource.Nature pluralElementSourceNature = attributeSource.getElementSource().getNature(); + + //TODO what is this case? it would be really good to add a comment + if ( pluralElementSourceNature == PluralAttributeElementSource.Nature.ONE_TO_MANY + || pluralAttributeSourceNature == PluralAttributeSource.Nature.BAG ) { + return; + } + if ( !attributeBinding.getPluralAttributeKeyBinding().isInverse() ) { + switch ( pluralAttributeSourceNature ) { + case SET: + bindSetCollectionTablePrimaryKey( (SetBinding) attributeBinding ); + break; + case LIST: + case MAP: + case ARRAY: + bindIndexedCollectionTablePrimaryKey( (IndexedPluralAttributeBinding) attributeBinding ); + break; + default: + throw new NotYetImplementedException( + String.format( "%s of elements is not supported yet.", pluralAttributeSourceNature ) + ); + } + } + } + + private TableSpecification findConstraintTable(EntityBinding entityBinding, String tableName) { + try { + return entityBinding.locateTable( tableName ); + } + catch ( AssertionFailure e ) { + Identifier identifier = Identifier.toIdentifier( tableName ); + + // TODO: Make TableGenerator & MultipleHiLoPerTableGenerator extend an abstract? + // @TableGenerator + IdentifierGenerator idGenerator = entityBinding.getHierarchyDetails().getEntityIdentifier().getIdentifierGenerator(); + if (idGenerator instanceof TableGenerator) { + Table generatorTable = ((TableGenerator) idGenerator).getTable(); + if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) { + return generatorTable; + } + } + else if (idGenerator instanceof MultipleHiLoPerTableGenerator) { + Table generatorTable = ((MultipleHiLoPerTableGenerator) idGenerator).getTable(); + if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) { + return generatorTable; + } + } + + // @JoinTable and @CollectionTable + for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { + if ( attributeBinding instanceof PluralAttributeBinding ) { + PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + final TableSpecification pluralTable = + pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable(); + if ( pluralTable != null && pluralTable.getLogicalName().equals( identifier ) ) { + return pluralTable; + } + } + } + } + + throw new AssertionFailure( + String.format( + "Unable to find locate table %s", + tableName + ) + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ simple instance helper methods + + private AssociationRelationalBindingResolver getAssociationRelationalBindingResolver(AttributeSource attributeSource) { + if ( ToOneAttributeSource.class.isInstance( attributeSource ) && + ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) { + return mappedByAssociationRelationalBindingResolver; + } + else if ( PluralAttributeSource.class.isInstance( attributeSource ) && + PluralAttributeSource.class.cast( attributeSource ).getMappedBy() != null ) { + return mappedByAssociationRelationalBindingResolver; + } + else { + return standardAssociationRelationalBindingResolver; + + } + } + + + private String propertyAccessorName(final AttributeSource attributeSource) { + return propertyAccessorName( attributeSource.getPropertyAccessorName() ); + } + + private String propertyAccessorName(final String propertyAccessorName) { + return propertyAccessorName == null + ? bindingContext().getMappingDefaults().getPropertyAccessorName() + : propertyAccessorName; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static methods + private static TableSpecification locateDefaultTableSpecificationForAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.getContainingTableName() == null ? + attributeBindingContainer.getPrimaryTable() : + attributeBindingContainer.seekEntityBinding().locateTable( attributeSource.getContainingTableName() ); + } + + private static PluralAttributeElementBinding.Nature pluralAttributeElementNature( + final PluralAttributeSource attributeSource) { + return PluralAttributeElementBinding.Nature.valueOf( attributeSource.getElementSource().getNature().name() ); + } + + private static PluralAttributeIndexBinding.Nature pluralAttributeIndexNature( + final PluralAttributeSource attributeSource) { + if ( !IndexedPluralAttributeSource.class.isInstance( attributeSource ) ) { + return null; + } + return PluralAttributeIndexBinding.Nature.valueOf( + ( (IndexedPluralAttributeSource) attributeSource ).getIndexSource().getNature().name() + ); + } + + private void bindIndexedCollectionTablePrimaryKey( + final IndexedPluralAttributeBinding attributeBinding) { + final TableSpecification collectionTable = attributeBinding.getPluralAttributeKeyBinding().getCollectionTable(); + final PrimaryKey primaryKey = collectionTable.getPrimaryKey(); + + final List keyRelationalValueBindings = + attributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings(); + + final PluralAttributeIndexBinding indexBinding = attributeBinding.getPluralAttributeIndexBinding(); + + // Don't add any columns to the primary key unless there is a non-nullable index or element column. + if ( relationalValueBindingHelper.hasDerivedValue( indexBinding.getRelationalValueBindings() ) ) { + // the index has as formula; + // only create the primary key if there are non-nullable element columns + final PluralAttributeElementBinding pluralAttributeElementBinding = attributeBinding.getPluralAttributeElementBinding(); + if ( pluralAttributeElementBinding.hasNonNullableValue() ) { + for ( final RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( RelationalValueBinding relationalValueBinding : pluralAttributeElementBinding.getRelationalValueBindings() ) { + if ( !relationalValueBinding.isDerived() && + !relationalValueBinding.isNullable() && + relationalValueBinding.getTable().equals( collectionTable ) ){ + primaryKey.addColumn( (Column)relationalValueBinding.getValue() ); + } + } + } + } + else { + for ( final RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) { + if ( relationalValueBinding.getTable().equals( collectionTable ) && + !relationalValueBinding.isNullable() ) { + primaryKey.addColumn( (Column) relationalValueBinding.getValue() ); + } + } + } + } + + + private static String getRelativePathFromEntityName( + final AttributeBinding attributeBinding) { + return StringHelper.isEmpty( attributeBinding.getContainer().getPathBase() ) ? + attributeBinding.getAttribute().getName() : + attributeBinding.getContainer().getPathBase() + "." + attributeBinding.getAttribute().getName(); + } + + // TODO: should this be moved to CascadeStyles as a static method? + // TODO: sources already factor in default cascade; should that be done here instead? + private static CascadeStyle determineCascadeStyle( + final Iterable cascadeStyles) { + CascadeStyle cascadeStyleResult; + List cascadeStyleList = new ArrayList(); + for ( CascadeStyle style : cascadeStyles ) { + if ( style != CascadeStyles.NONE ) { + cascadeStyleList.add( style ); + } + } + if ( cascadeStyleList.isEmpty() ) { + cascadeStyleResult = CascadeStyles.NONE; + } + else if ( cascadeStyleList.size() == 1 ) { + cascadeStyleResult = cascadeStyleList.get( 0 ); + } + else { + cascadeStyleResult = new CascadeStyles.MultipleCascadeStyle( + cascadeStyleList.toArray( new CascadeStyle[cascadeStyleList.size()] ) + ); + } + return cascadeStyleResult; + } + + private static MetaAttributeContext createMetaAttributeContext( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSource attributeSource) { + return createMetaAttributeContext( attributeBindingContainer, attributeSource.getMetaAttributeSources() ); + } + + private static MetaAttributeContext createMetaAttributeContext( + final AttributeBindingContainer attributeBindingContainer, + final Iterable metaAttributeSources) { + return createMetaAttributeContext( + metaAttributeSources, + false, + attributeBindingContainer.getMetaAttributeContext() + ); + } + + private static MetaAttributeContext createMetaAttributeContext( + final Iterable metaAttributeSources, + final boolean onlyInheritable, + final MetaAttributeContext parentContext) { + final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); + for ( final MetaAttributeSource metaAttributeSource : metaAttributeSources ) { + if ( onlyInheritable && !metaAttributeSource.isInheritable() ) { + continue; + } + final String name = metaAttributeSource.getName(); + MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); + if ( metaAttribute == null || metaAttribute == parentContext.getMetaAttribute( name ) ) { + metaAttribute = new MetaAttribute( name ); + subContext.add( metaAttribute ); + } + metaAttribute.addValue( metaAttributeSource.getValue() ); + } + return subContext; + } + + private static SingularAttribute createSingularAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.isVirtualAttribute() ? + attributeBindingContainer.getAttributeContainer().createSyntheticSingularAttribute( + attributeSource.getName() + ) : + attributeBindingContainer.getAttributeContainer().createSingularAttribute( attributeSource.getName() ); + } + + static String createAttributePathQualifiedByEntityName(final AttributeBinding attributeBinding) { + final String entityName = attributeBinding.getContainer().seekEntityBinding().getEntityName(); + return entityName + '.' + createAttributePath( attributeBinding ); + } + static String createAttributePath(final AttributeBinding attributeBinding) { + return StringHelper.isEmpty( attributeBinding.getContainer().getPathBase() ) ? + attributeBinding.getAttribute().getName() : + attributeBinding.getContainer().getPathBase() + '.' + attributeBinding.getAttribute().getName(); + } + + private static ValueHolder> createSingularAttributeJavaType( + final Class attributeContainerClassReference, + final String attributeName) { + ValueHolder.DeferredInitializer> deferredInitializer = + new ValueHolder.DeferredInitializer>() { + @Override + public Class initialize() { + return ReflectHelper.reflectedPropertyClass( + attributeContainerClassReference, + attributeName + ); + } + }; + return new ValueHolder>( deferredInitializer ); + } + + private static ValueHolder> createSingularAttributeJavaType( + final SingularAttribute attribute) { + return createSingularAttributeJavaType( + attribute.getAttributeContainer().getClassReference(), + attribute.getName() + ); + } + + public static interface DefaultNamingStrategy { + + String defaultName(NamingStrategy namingStrategy); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/CollectionTableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/CollectionTableNamingStrategyHelper.java new file mode 100644 index 0000000000..f5f6013178 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/CollectionTableNamingStrategyHelper.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.Table; + +/** + * @author Strong Liu + */ +public class CollectionTableNamingStrategyHelper extends TableNamingStrategyHelper { + private final String ownerTableLogicalName; + private final String propertyName; + + public CollectionTableNamingStrategyHelper(final AbstractPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding.getContainer().seekEntityBinding() ); + this.ownerTableLogicalName = + Table.class.isInstance( entityBinding.getPrimaryTable() ) + ? ( (Table) entityBinding.getPrimaryTable() ).getPhysicalName().getText() + : null; + this.propertyName = Binder.createAttributePath( pluralAttributeBinding ); + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + + + return strategy.collectionTableName( + entityBinding.getEntity().getName(), + ownerTableLogicalName, + null, + null, + propertyName + + ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return strategy.logicalCollectionTableName( + logicalName, + ownerTableLogicalName, + null, + propertyName + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ColumnNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ColumnNamingStrategyHelper.java new file mode 100644 index 0000000000..c077d78dda --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ColumnNamingStrategyHelper.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; + +/** + * @author Strong Liu + */ +public class ColumnNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + private final String defaultName; + private final boolean isDefaultAttributeName; + + public ColumnNamingStrategyHelper( + final String defaultName, + final boolean isDefaultAttributeName) { + this.defaultName = defaultName; + this.isDefaultAttributeName = isDefaultAttributeName; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + if ( isDefaultAttributeName ) { + return strategy.propertyToColumnName( defaultName ); + } + else { + return strategy.columnName( defaultName ); + } + } + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return strategy.columnName( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java new file mode 100644 index 0000000000..9683d7731d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Brett Meyer + */ +public abstract class ConstraintNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + + protected final TableSpecification table; + + protected final List columns; + + public ConstraintNamingStrategyHelper(TableSpecification table, List columns) { + this.table = table; + this.columns = columns; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return doDetermineImplicitName( strategy, table.getLogicalName().getText(), getColumnNames( columns ) ); + } + + protected abstract String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames); + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return name; + } + + public static class UniqueKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public UniqueKeyNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.uniqueKeyName( tableName, columnNames ); + } + } + + public static class ForeignKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + // named using a combo of source/target table/columns + private final String targetTableName; + private final List targetColumnNames; + + public ForeignKeyNamingStrategyHelper(TableSpecification sourceTable, List sourceColumns, + TableSpecification targetTable, List targetColumns) { + super( sourceTable, sourceColumns ); + targetTableName = targetTable.getLogicalName().getText(); + targetColumnNames = getColumnNames( targetColumns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + // combine source and target (if available) to ensure uniqueness + return strategy.foreignKeyName( tableName, columnNames, targetTableName, targetColumnNames ); + } + } + + public static class IndexNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public IndexNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.indexName( tableName, columnNames ); + } + } + + private static List getColumnNames(List columns) { + final List columnNames = new ArrayList(); + for ( final Column column : columns ) { + columnNames.add( column.getColumnName().getText() ); + } + return columnNames; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/DefaultColumnNamingStrategyHelper.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/DefaultColumnNamingStrategyHelper.java index ae141bcbd8..1b63380aa9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/DefaultColumnNamingStrategyHelper.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,42 +21,28 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; - -import java.util.Set; +package org.hibernate.metamodel.internal; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.cfg.ObjectNameNormalizer; /** * @author Gail Badner */ -public interface ColumnRelationalState extends SimpleValueRelationalState { - NamingStrategy getNamingStrategy(); +public class DefaultColumnNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + private final Binder.DefaultNamingStrategy defaultNameStrategy; - boolean isGloballyQuotedIdentifiers(); + public DefaultColumnNamingStrategyHelper(Binder.DefaultNamingStrategy defaultNameStrategy) { + this.defaultNameStrategy = defaultNameStrategy; + } - String getExplicitColumnName(); + @Override + public String determineImplicitName(NamingStrategy strategy) { + return defaultNameStrategy.defaultName( strategy ); + } - boolean isUnique(); - - Size getSize(); - - boolean isNullable(); - - String getCheckCondition(); - - String getDefault(); - - String getSqlType(); - - String getCustomWriteFragment(); - - String getCustomReadFragment(); - - String getComment(); - - Set getUniqueKeys(); - - Set getIndexes(); + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return strategy.columnName( name ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityHierarchyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityHierarchyHelper.java new file mode 100644 index 0000000000..d076813d49 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityHierarchyHelper.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.EntityMode; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; + +/** + * @author Gail Badner + */ +public class EntityHierarchyHelper { + + public interface LocalBindingContextExecutor { + void execute(LocalBindingContextExecutionContext bindingContextContext); + } + + public interface LocalBindingContextExecutionContext { + RootEntitySource getRootEntitySource(); + EntitySource getEntitySource(); + EntityBinding getEntityBinding(); + EntityBinding getSuperEntityBinding(); + InheritanceType getInheritanceType(); + EntityMode getEntityMode(); + } + + public static interface LocalBindingContextManager extends LocalBindingContextExecutionContext { + LocalBindingContext localBindingContext(); + void cleanupLocalBindingContexts(); + void setupLocalBindingContexts(final EntityHierarchy entityHierarchy); + void pushSubEntitySource(EntitySource entitySource); + void popSubEntitySource(); + } + + private LocalBindingContextManager localBindingContextManager; + + EntityHierarchyHelper(final LocalBindingContextManager localBindingContextManager) { + this.localBindingContextManager = localBindingContextManager; + } + + /** + * Apply executors to all entity hierarchies. + */ + public void applyToAllEntityHierarchies( + final Iterable entityHierarchies, + final LocalBindingContextExecutor rootEntityExecutor, + final LocalBindingContextExecutor subEntityExecutor) { + for ( final EntityHierarchy entityHierarchy : entityHierarchies ) { + applyToEntityHierarchy( entityHierarchy, rootEntityExecutor, subEntityExecutor ); + } + } + + /** + * Apply executors to a single entity hierarchy. + * + * @param entityHierarchy The entity hierarchy to be binded. + * @param rootEntityExecutor The executor to be applied to the root {@link EntitySource} + * in the entity hierarchy. + * @param subEntityExecutor The executer to be applied to each {@link SubclassEntitySource} + * in the entity hierarchy. + */ + public void applyToEntityHierarchy( + final EntityHierarchy entityHierarchy, + final LocalBindingContextExecutor rootEntityExecutor, + final LocalBindingContextExecutor subEntityExecutor) { + localBindingContextManager.cleanupLocalBindingContexts(); + localBindingContextManager.setupLocalBindingContexts( entityHierarchy ); + try { + rootEntityExecutor.execute( localBindingContextManager ); + if ( entityHierarchy.getHierarchyInheritanceType() != InheritanceType.NO_INHERITANCE ) { + applyToSubEntities( subEntityExecutor ); + } + } + finally { + localBindingContextManager.cleanupLocalBindingContexts(); + } + } + + private void applyToSubEntities(final LocalBindingContextExecutor subEntityExecutor) { + for ( final SubclassEntitySource subEntitySource : localBindingContextManager.getEntitySource().subclassEntitySources() ) { + applyToSubEntity( subEntitySource, subEntityExecutor ); + } + } + + private void applyToSubEntity(final EntitySource entitySource, final LocalBindingContextExecutor subEntityExecutor) { + localBindingContextManager.pushSubEntitySource( entitySource ); + try { + subEntityExecutor.execute( localBindingContextManager ); + applyToSubEntities( subEntityExecutor ); + } + finally { + localBindingContextManager.popSubEntitySource(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java new file mode 100644 index 0000000000..d21e001fbe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java @@ -0,0 +1,343 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.jboss.logging.Logger; + +/** + * @author Gail Badner + * @author Brett Meyer + */ +public class ForeignKeyHelper { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + ForeignKeyHelper.class.getName() + ); + + private final HelperContext helperContext; + + public ForeignKeyHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + public List determineForeignKeyTargetColumns( + final EntityBinding entityBinding, + final ForeignKeyContributingSource foreignKeyContributingSource) { + + // TODO: This method, JoinColumnResolutionContext, + // and JoinColumnResolutionDelegate need re-worked. There is currently + // no way to bind to a collection's inverse foreign key. + + final ForeignKeyContributingSource.JoinColumnResolutionDelegate fkColumnResolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + + if ( fkColumnResolutionDelegate == null ) { + return entityBinding.getPrimaryTable().getPrimaryKey().getColumns(); + } + else { + final List columns = new ArrayList(); + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); + for ( Value relationalValue : fkColumnResolutionDelegate.getJoinColumns( resolutionContext ) ) { + if ( !Column.class.isInstance( relationalValue ) ) { + throw bindingContext().makeMappingException( + "Foreign keys can currently only name columns, not formulas" + ); + } + columns.add( (Column) relationalValue ); + } + return columns; + } + } + + public TableSpecification determineForeignKeyTargetTable( + final EntityBinding entityBinding, + final ForeignKeyContributingSource foreignKeyContributingSource) { + + final ForeignKeyContributingSource.JoinColumnResolutionDelegate fkColumnResolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + if ( fkColumnResolutionDelegate == null ) { + return entityBinding.getPrimaryTable(); + } + else { + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); + return fkColumnResolutionDelegate.getReferencedTable( resolutionContext ); + } + } + + public SingularAttributeBinding determineReferencedAttributeBinding( + final ForeignKeyContributingSource foreignKeyContributingSource, + final EntityBinding referencedEntityBinding) { + final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = resolutionDelegate == null ? null : new JoinColumnResolutionContextImpl( + referencedEntityBinding + ); + if ( resolutionDelegate == null ) { + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + } + + final String explicitName = resolutionDelegate.getReferencedAttributeName(); + final AttributeBinding referencedAttributeBinding = explicitName != null + ? referencedEntityBinding.locateAttributeBindingByPath( explicitName, true ) + : referencedEntityBinding.locateAttributeBinding( + resolutionDelegate.getReferencedTable( resolutionContext ), + resolutionDelegate.getJoinColumns( resolutionContext ), + true + ); + + if ( referencedAttributeBinding == null ) { + if ( explicitName != null ) { + throw bindingContext().makeMappingException( + String.format( + "No attribute binding found with name: %s.%s", + referencedEntityBinding.getEntityName(), + explicitName + ) + ); + } + else { + throw new NotYetImplementedException( + "No support yet for referenced join columns unless they correspond with columns bound for an attribute binding." + ); + } + } + + if ( !referencedAttributeBinding.getAttribute().isSingular() ) { + throw bindingContext().makeMappingException( + String.format( + "Foreign key references a non-singular attribute [%s]", + referencedAttributeBinding.getAttribute().getName() + ) + ); + } + return (SingularAttributeBinding) referencedAttributeBinding; + } + + public ForeignKey locateOrCreateForeignKey( + String explicitForeignKeyName, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns) { + final String foreignKeyName = helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( + explicitForeignKeyName, new ForeignKeyNamingStrategyHelper( + sourceTable, sourceColumns, targetTable, targetColumns ) ); + + ForeignKey foreignKey = locateAndBindForeignKeyByName( foreignKeyName, sourceTable, sourceColumns, targetTable, targetColumns ); + if ( foreignKey == null ) { + // no foreign key found; create one + foreignKey = sourceTable.createForeignKey( targetTable, foreignKeyName ); + bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns ); + } + return foreignKey; + } + + private void bindForeignKeyColumns( + final ForeignKey foreignKey, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns) { + if ( sourceColumns.size() != targetColumns.size() ) { + throw bindingContext().makeMappingException( + String.format( + "Non-matching number columns in foreign key source columns [%s : %s] and target columns [%s : %s]", + sourceTable.getLogicalName().getText(), + sourceColumns.size(), + targetTable.getLogicalName().getText(), + targetColumns.size() + ) + ); + } + for ( int i = 0; i < sourceColumns.size(); i++ ) { + foreignKey.addColumnMapping( sourceColumns.get( i ), targetColumns.get( i ) ); + } + } + + private ForeignKey locateAndBindForeignKeyByName( + final String foreignKeyName, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns) { + if ( foreignKeyName == null ) { + throw new AssertionFailure( "foreignKeyName must be non-null." ); + } + ForeignKey foreignKey = sourceTable.locateForeignKey( foreignKeyName ); + if ( foreignKey != null ) { + if ( !targetTable.equals( foreignKey.getTargetTable() ) ) { + throw bindingContext().makeMappingException( + String.format( + "Unexpected target table defined for foreign key \"%s\"; expected \"%s\"; found \"%s\"", + foreignKeyName, + targetTable.getLogicalName(), + foreignKey.getTargetTable().getLogicalName() + ) + ); + } + // check if source and target columns have been bound already + if ( foreignKey.getColumnSpan() == 0 ) { + // foreign key was found, but no columns bound to it yet + bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns ); + } + else { + // The located foreign key already has columns bound; + // Make sure they are the same columns. + if ( !foreignKey.getSourceColumns().equals( sourceColumns ) || + !foreignKey.getTargetColumns().equals( targetColumns ) ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to bind exisitng foreign key \"%s\" with different columns.", + foreignKeyName + ) + ); + } + } + } + return foreignKey; + } + + private LocalBindingContext bindingContext() { + return helperContext.bindingContext(); + } + + private class JoinColumnResolutionContextImpl implements ForeignKeyContributingSource.JoinColumnResolutionContext { + private final EntityBinding referencedEntityBinding; + + + public JoinColumnResolutionContextImpl(EntityBinding referencedEntityBinding) { + this.referencedEntityBinding = referencedEntityBinding; + } + + @Override + public Column resolveColumn( + String logicalColumnName, + String logicalTableName, + String logicalSchemaName, + String logicalCatalogName) { + if ( bindingContext().isGloballyQuotedIdentifiers() && !org.hibernate + .internal + .util + .StringHelper + .isQuoted( logicalColumnName ) ) { + logicalColumnName = org.hibernate.internal.util.StringHelper.quote( logicalColumnName ); + } + return resolveTable( logicalTableName, logicalSchemaName, logicalCatalogName ).locateOrCreateColumn( + logicalColumnName + ); + } + + @Override + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName) { + Identifier tableIdentifier = helperContext.relationalIdentifierHelper().createIdentifier( logicalTableName ); + if ( tableIdentifier == null ) { + tableIdentifier = referencedEntityBinding.getPrimaryTable().getLogicalName(); + } + + + Identifier catalogName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ? + Identifier.toIdentifier( logicalCatalogName ) + : referencedEntityBinding.getPrimaryTable().getSchema().getName().getCatalog(); + Identifier schemaName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ? + Identifier.toIdentifier( logicalSchemaName ) + : referencedEntityBinding.getPrimaryTable().getSchema().getName().getSchema(); + Schema schema = bindingContext().getMetadataImplementor().getDatabase().getSchema( catalogName, schemaName ); + return schema.locateTable( tableIdentifier ); + } + + @Override + public List resolveRelationalValuesForAttribute(String attributeName) { + if ( attributeName == null ) { + List values = new ArrayList(); + for ( Column column : referencedEntityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { + values.add( column ); + } + return values; + } + List valueBindings = + resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings(); + List values = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding valueBinding : valueBindings ) { + values.add( valueBinding.getValue() ); + } + return values; + } + + @Override + public TableSpecification resolveTableForAttribute(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getPrimaryTable(); + } + else { + return resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings().get( 0 ).getTable(); + } + } + + private SingularAttributeBinding resolveReferencedAttributeBinding(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + } + final AttributeBinding referencedAttributeBinding = + referencedEntityBinding.locateAttributeBindingByPath( attributeName, true ); + if ( referencedAttributeBinding == null ) { + throw bindingContext().makeMappingException( + String.format( + "Could not resolve named referenced property [%s] against entity [%s]", + attributeName, + referencedEntityBinding.getEntity().getName() + ) + ); + } + if ( !referencedAttributeBinding.getAttribute().isSingular() ) { + throw bindingContext().makeMappingException( + String.format( + "Referenced property [%s] against entity [%s] is a plural attribute; it must be a singular attribute.", + attributeName, + referencedEntityBinding.getEntity().getName() + ) + ); + } + return (SingularAttributeBinding) referencedAttributeBinding; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java new file mode 100644 index 0000000000..e4a83862c8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.HibernateException; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Brett Meyer + */ +public class HashedNameUtil { + + /** + * If a constraint is not explicitly named, this is called to generate + * a unique hash using the table and column names. + * Static so the name can be generated prior to creating the Constraint. + * They're cached, keyed by name, in multiple locations. + * + * @param prefix + * @param table + * @param columnNames + * @return String The generated name + */ + public static String generateName(String prefix, String tableName, String... columnNames ) { + // Use a concatenation that guarantees uniqueness, even if identical names + // exist between all table and column identifiers. + + StringBuilder sb = new StringBuilder( "table`" + tableName + "`" ); + + // Ensure a consistent ordering of columns, regardless of the order + // they were bound. + // Clone the list, as sometimes a set of order-dependent Column + // bindings are given. + String[] alphabeticalColumns = columnNames.clone(); + Arrays.sort( alphabeticalColumns ); + for ( String columnName : alphabeticalColumns ) { + sb.append( "column`" + columnName + "`" ); + } + return prefix + hashedName( sb.toString() ); + } + + /** + * Helper method for {@link #generateName(String, TableSpecification, String...)}. + * + * @param prefix + * @param table + * @param columns + * @return String The generated name + */ + public static String generateName(String prefix, String tableName, List columnNames) { + String[] columnNamesArray = new String[columnNames.size()]; + for ( int i = 0; i < columnNames.size(); i++ ) { + columnNamesArray[i] = columnNames.get( i ); + } + return generateName( prefix, tableName, columnNamesArray ); + } + + /** + * Hash a constraint name using MD5. Convert the MD5 digest to base 35 + * (full alphanumeric), guaranteeing + * that the length of the name will always be smaller than the 30 + * character identifier restriction enforced by a few dialects. + * + * @param s The name to be hashed. + * @return String The hased name. + */ + public static String hashedName(String s) { + try { + MessageDigest md = MessageDigest.getInstance( "MD5" ); + md.reset(); + md.update( s.getBytes() ); + byte[] digest = md.digest(); + BigInteger bigInt = new BigInteger( 1, digest ); + // By converting to base 35 (full alphanumeric), we guarantee + // that the length of the name will always be smaller than the 30 + // character identifier restriction enforced by a few dialects. + return bigInt.toString( 35 ); + } + catch ( NoSuchAlgorithmException e ) { + throw new HibernateException( "Unable to generate a hashed name!", e ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HelperContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HelperContext.java new file mode 100644 index 0000000000..9c63fcb591 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HelperContext.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Gail Badner + */ +public interface HelperContext { + HibernateTypeHelper typeHelper(); + RelationalIdentifierHelper relationalIdentifierHelper(); + TableHelper tableHelper(); + ForeignKeyHelper foreignKeyHelper(); + RelationalValueBindingHelper relationalValueBindingHelper(); + NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper(); + LocalBindingContext bindingContext(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HibernateTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HibernateTypeHelper.java new file mode 100644 index 0000000000..52d84f5941 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HibernateTypeHelper.java @@ -0,0 +1,874 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.beans.BeanInfo; +import java.beans.PropertyDescriptor; +import java.lang.reflect.ParameterizedType; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.jboss.logging.Logger; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.beans.BeanInfoHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.ManyToManyPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.AbstractValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.tuple.component.ComponentMetamodel; +import org.hibernate.type.CompositeType; +import org.hibernate.type.EntityType; +import org.hibernate.type.Type; +import org.hibernate.type.TypeFactory; + +/** + * Delegate for handling:

            + *
          1. + * binding of Hibernate type information ({@link org.hibernate.metamodel.spi.source.HibernateTypeSource} -> + * {@link HibernateTypeDescriptor} + *
          2. + *
          3. + * attempt to resolve the actual {@link Type} instance + *
          4. + *
          5. + * push java type and JDBC type information reported by the {@link Type} instance to relational/ + * domain models. + *
          6. + *
          + *

          + * Methods intended as entry points are:

            + *
          • {@link #bindSingularAttributeType}
          • + *
          + *

          + * Currently the following methods are also required to be non-private because of handling discriminators which + * are currently not modeled using attributes:

            + *
          • {@link #bindJdbcDataType(org.hibernate.type.Type, org.hibernate.metamodel.spi.relational.Value)}
          • + *
          + * + * @author Steve Ebersole + * @author Gail Badner + * @author Brett Meyer + */ +class HibernateTypeHelper { + private static final Logger log = Logger.getLogger( HibernateTypeHelper.class ); + + /** + * package-protected + *

          + * Model a plural attribute's type info, including : + *

            + *
          • collection type, like {@code list}, {@code set} etc
          • + *
          • elements' type, which belongs in this collection
          • + *
          • collection index type
          • + *
          + */ + static class ReflectedCollectionJavaTypes { + private final String collectionTypeName; + private final String collectionElementTypeName; + private final String collectionIndexTypeName; + + private ReflectedCollectionJavaTypes( + Class collectionType, + Class collectionElementType, + Class collectionIndexType) { + this.collectionTypeName = collectionType != null ? collectionType.getName() : null; + this.collectionElementTypeName = collectionElementType != null ? collectionElementType.getName() : null; + this.collectionIndexTypeName = collectionIndexType != null ? collectionIndexType.getName() : null; + } + + String getCollectionElementTypeName() { + return collectionElementTypeName; + } + + String getCollectionIndexTypeName() { + return collectionIndexTypeName; + } + + String getCollectionTypeName() { + return collectionTypeName; + } + } + + static String defaultCollectionElementJavaTypeName( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionElementTypeName() : null; + } + + static String defaultCollectionIndexJavaTypeName( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionIndexTypeName() : null; + } + + static String defaultCollectionJavaTypeName( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes, + final PluralAttributeSource attributeSource) { + return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionTypeName() : attributeSource + .getNature() + .reportedJavaType() + .getName(); + } + static ReflectedCollectionJavaTypes getReflectedCollectionJavaTypes( + final PluralAttributeBinding attributeBinding) { + return determineJavaType( attributeBinding.getAttribute() ); + } + //-------------------------------------------------------------------------------- + + /** + * Bind type info into {@link HibernateTypeDescriptor}. The strategy below applied: + *

          + *

            + *
          • if {@param resolvedType} is not null, then we can get resolvedTypeMapping, javaTypeName, toOne from it.
          • + *
          • Or, we have to use provided {@param explicitTypeName} / {@param defaultJavaTypeName} to resolve hibernate type
          • + *
          + * + * @param hibernateTypeDescriptor + * The target {@link HibernateTypeDescriptor} to be bind. Can not be null. + * + * @param explicitTypeName + * + * Explicit type name defined in the mapping or resolved from referenced attribute. + * null is accepted. + * + * @param explictTypeParameters + * + * Explicit type parameters defined in the mapping or resolved from refrenced attribute type. + * null is accepted. + * + * @param defaultJavaTypeName + * + * Attribute java type. null is accepted. + * + * @param resolvedType + * + * Provided hibernate type. null is accepted. + */ + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explictTypeParameters, + final String defaultJavaTypeName, + final Type resolvedType) { + Type type; + if ( resolvedType != null ) { + type = resolvedType; + } + else { + //1. pre processing, resolve either explicitType or javaType + preProcessHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + explictTypeParameters, + defaultJavaTypeName + ); + //2. resolve hibernate type + type = heuristicType( hibernateTypeDescriptor ); + } + if ( type == null ) { + //todo how to deal with this? + } + //3. now set hibernateTypeDescripter's ResolvedTypeMapping and defaultJavaType (if not yet) + hibernateTypeDescriptor.setResolvedTypeMapping( type ); + } + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explictTypeParameters, + final String defaultJavaTypeName) { + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + explictTypeParameters, + defaultJavaTypeName, + null + ); + } + + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final HibernateTypeSource explicitTypeSource, + final String defaultJavaTypeName){ + bindHibernateTypeDescriptor( hibernateTypeDescriptor, explicitTypeSource, defaultJavaTypeName, null); + } + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final HibernateTypeSource explicitTypeSource, + final String defaultJavaTypeName, + final Type resolvedType) { + final String explicitTypeName = explicitTypeSource != null ? explicitTypeSource.getName() : null; + final Map parameters = explicitTypeSource != null ? explicitTypeSource.getParameters() : null; + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + parameters, + defaultJavaTypeName, + resolvedType + ); + } + //-------------------------------------------------------------------------------- + + private final HelperContext helperContext; + + //package scope methods + HibernateTypeHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + /** + * Bind relational types using hibernate type just resolved. + * + * @param resolvedHibernateType The hibernate type resolved from metadata. + * @param value The relational value to be binded. + */ + void bindJdbcDataType( + final Type resolvedHibernateType, + final Value value) { + if ( value != null && value.getJdbcDataType() == null && resolvedHibernateType != null ) { + final Type resolvedRelationalType = + resolvedHibernateType.isEntityType() + ? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata() ) + : resolvedHibernateType; + if ( AbstractValue.class.isInstance( value ) ) { + ( (AbstractValue) value ).setJdbcDataType( + new JdbcDataType( + resolvedRelationalType.sqlTypes( metadata() )[0], + resolvedRelationalType.getName(), + resolvedRelationalType.getReturnedClass() + ) + ); + } + } + } + + void bindJdbcDataType( + final Type resolvedHibernateType, + final List relationalValueBindings) { + if ( resolvedHibernateType == null ) { + throw new IllegalArgumentException( "resolvedHibernateType must be non-null." ); + } + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new IllegalArgumentException( "relationalValueBindings must be non-null." ); + } + if ( relationalValueBindings.size() == 1 ) { + bindJdbcDataType( resolvedHibernateType, relationalValueBindings.get( 0 ).getValue() ); + } + else { + final Type resolvedRelationalType = + resolvedHibernateType.isEntityType() + ? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata() ) + : resolvedHibernateType; + if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) { + throw bindingContext() + .makeMappingException( "Column number mismatch" ); // todo refine the exception message + } + Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes(); + for ( int i = 0; i < subTypes.length; i++ ) { + bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() ); + } + } + } + + void bindAggregatedCompositeAttributeType( + final boolean isAttributeIdentifier, + final Aggregate composite, + final ValueHolder> defaultJavaClassReference, + final CompositeAttributeBinding attributeBinding) { + Type resolvedType = typeFactory().component( + new ComponentMetamodel( attributeBinding, isAttributeIdentifier, false ) + ); + bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + composite.getClassName(), + null, + defaultJavaClassReference == null ? null : defaultJavaClassReference.getValue().getName(), + resolvedType + ); + } + + void bindBasicCollectionElementType( + final BasicPluralAttributeElementBinding elementBinding, + final BasicPluralAttributeElementSource elementSource, + final String defaultElementJavaTypeName) { + bindHibernateTypeDescriptor( + elementBinding.getHibernateTypeDescriptor(), + elementSource.getExplicitHibernateTypeSource(), + defaultElementJavaTypeName + ); + bindJdbcDataType( + elementBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + elementBinding.getRelationalValueBindings() + ); + } + void bindNonAggregatedCompositeIdentifierType( + final CompositeAttributeBinding syntheticAttributeBinding, + final SingularAttribute syntheticAttribute) { + final Type resolvedType = typeFactory().embeddedComponent( + new ComponentMetamodel( syntheticAttributeBinding, true, false ) + ); + final HibernateTypeDescriptor typeDescriptor = syntheticAttributeBinding.getHibernateTypeDescriptor(); + bindHibernateTypeDescriptor( + typeDescriptor, + syntheticAttribute.getSingularAttributeType().getClassName(), + null, + null, + resolvedType + ); + } + void bindManyToManyAttributeType( + final ManyToManyPluralAttributeElementBinding elementBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final EntityBinding referencedEntityBinding, + final String defaultElementJavaTypeName) { + final Type resolvedElementType = typeFactory().manyToOne( + referencedEntityBinding.getEntity().getName(), + elementSource.getReferencedEntityAttributeName(), + false, + false, + !elementSource.isNotFoundAnException(), + false + ); + final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + referencedEntityBinding.getEntity().getName(), + null, + defaultElementJavaTypeName, + resolvedElementType + ); + bindJdbcDataType( + resolvedElementType, + elementBinding.getRelationalValueBindings() + ); + } + + void bindDiscriminatorType(EntityDiscriminator discriminator, Value value) { + bindHibernateTypeDescriptor( + discriminator.getExplicitHibernateTypeDescriptor(), + null, + null, + String.class.getName() + ); + bindJdbcDataType( discriminator.getExplicitHibernateTypeDescriptor().getResolvedTypeMapping(), value ); + } + + void bindSingularAttributeType( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding + .getHibernateTypeDescriptor(); + final Class attributeJavaType = determineJavaType( attributeSource, attributeBinding); + //try to resolve this attribute's java type first + final String defaultJavaTypeName; + if ( attributeJavaType != null ) { + attributeBinding.getAttribute().resolveType( + makeJavaType( + attributeJavaType.getName() + ) + ); + defaultJavaTypeName = attributeJavaType.getName(); + } else { + defaultJavaTypeName = null; + } + //do our best to full fill hibernateTypeDescriptor + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + attributeSource.getTypeInformation(), + defaultJavaTypeName + ); + + processSingularAttributeTypeInformation( + attributeSource, + attributeBinding + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hibernate type resolver + Type resolvePluralType( + final PluralAttributeBinding pluralAttributeBinding, + final PluralAttributeSource pluralAttributeSource, + final PluralAttributeSource.Nature nature) { + if ( pluralAttributeBinding.getHibernateTypeDescriptor().getExplicitTypeName() != null ) { + return resolveCustomCollectionType( pluralAttributeBinding ); + } + else { + final String role = pluralAttributeBinding.getAttribute().getRole(); + final String propertyRef = getReferencedPropertyNameIfNotId( pluralAttributeBinding ); + switch ( nature ) { + case BAG: + return typeFactory().bag( role, propertyRef ); + case LIST: + return typeFactory().list( role, propertyRef ); + case ARRAY: + return typeFactory().array( + role, + propertyRef, + pluralAttributeSource.getElementClassReference().getValue() + ); + case MAP: + if ( pluralAttributeBinding.isSorted() ) { + return typeFactory().sortedMap( + role, + propertyRef, + pluralAttributeBinding.getComparator() + ); + } + // TODO: else if ( pluralAttributeBinding.hasOrder() ) { orderedMap... } + else { + return typeFactory().map( role, propertyRef ); + } + case SET: + if ( pluralAttributeBinding.isSorted() ) { + return typeFactory().sortedSet( + role, + propertyRef, + pluralAttributeBinding.getComparator() + ); + } + else if ( pluralAttributeBinding.getOrderBy() != null ) { + return typeFactory().orderedSet( role, propertyRef ); + } + else if ( pluralAttributeBinding.getPluralAttributeElementBinding().getNature() == PluralAttributeElementBinding.Nature.MANY_TO_MANY && + ( (ManyToManyPluralAttributeElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding() ).getManyToManyOrderBy() != null ) { + return typeFactory().orderedSet( role, propertyRef ); + } + else { + return typeFactory().set( role, propertyRef ); + } + default: + throw new NotYetImplementedException( nature + " is to be implemented" ); + } + } + } + + private TypeFactory typeFactory(){ + return metadata().getTypeResolver().getTypeFactory(); + } + + private Type determineHibernateTypeFromAttributeJavaType( + final SingularAttribute singularAttribute) { + if ( singularAttribute.getSingularAttributeType() != null ) { + return getHeuristicType( + singularAttribute.getSingularAttributeType().getClassName(), + null + ); + } + return null; + } + private Type resolveCustomCollectionType( + final PluralAttributeBinding pluralAttributeBinding) { + final HibernateTypeDescriptor hibernateTypeDescriptor = pluralAttributeBinding.getHibernateTypeDescriptor(); + Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); + return typeFactory().customCollection( + hibernateTypeDescriptor.getExplicitTypeName(), + typeParameters, + pluralAttributeBinding.getAttribute().getName(), + getReferencedPropertyNameIfNotId( pluralAttributeBinding ) + ); + } + /** + * Resolve hibernate type with info from {@link HibernateTypeDescriptor} using {@link org.hibernate.type.TypeResolver}. + *

          + * return null if can't resolve. + */ + private Type heuristicType( + final HibernateTypeDescriptor hibernateTypeDescriptor) { + if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { + return hibernateTypeDescriptor.getResolvedTypeMapping(); + } + String typeName = determineTypeName( hibernateTypeDescriptor ); + Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); + Type type = getHeuristicType( typeName, typeParameters ); + hibernateTypeDescriptor.setResolvedTypeMapping( type ); + return type; + } + + private Type getHeuristicType( + final String typeName, + final Properties typeParameters) { + if ( typeName != null ) { + try { + return metadata().getTypeResolver().heuristicType( typeName, typeParameters ); + } + catch ( Exception ignore ) { + } + } + + return null; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private scope methods + + /** + * Given an attribute, process all of its type information. This includes resolving the actual + * {@link Type} instance and pushing JDBC/java information from that type down. + * + * @param attributeSource The attribute source. + * @param attributeBinding The attribute. + */ + private void processSingularAttributeTypeInformation( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding) { + Type resolvedType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + if ( resolvedType == null ) { + // we can determine the Hibernate Type if either: + // 1) the user explicitly named a Type in a HibernateTypeDescriptor + // 2) we know the java type of the attribute + resolvedType = heuristicType( attributeBinding.getHibernateTypeDescriptor() ); + if ( resolvedType == null ) { + resolvedType = determineHibernateTypeFromAttributeJavaType( attributeBinding.getAttribute() ); + } + } + + if ( resolvedType != null ) { + pushHibernateTypeInformationDown( attributeSource, attributeBinding, resolvedType ); + } else{ + //todo throw exception?? + } + } + + private void preProcessHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explictTypeParameters, + final String defaultJavaTypeName) { + if ( explicitTypeName == null ) { + if ( defaultJavaTypeName != null && hibernateTypeDescriptor.getJavaTypeName() != null ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to re-initialize (non-explicit) Java type name; current=%s new=%s", + hibernateTypeDescriptor.getJavaTypeName(), + defaultJavaTypeName + ) + ); + } + hibernateTypeDescriptor.setJavaTypeName( defaultJavaTypeName ); + } + else { + // Check if user-specified name is of a User-Defined Type (UDT) + final TypeDefinition typeDef = metadata().getTypeDefinition( explicitTypeName ); + if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to re-initialize explicity-mapped Java type name; current=%s new=%s", + hibernateTypeDescriptor.getExplicitTypeName(), + explicitTypeName + ) + ); + } + if ( typeDef == null ) { + hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName ); + } + else { + hibernateTypeDescriptor.setExplicitTypeName( typeDef.getTypeImplementorClass().getName() ); + // Don't use set() -- typeDef#parameters is unmodifiable + hibernateTypeDescriptor.getTypeParameters().putAll( typeDef.getParameters() ); + } + if ( explictTypeParameters != null ) { + hibernateTypeDescriptor.getTypeParameters().putAll( explictTypeParameters ); + } + } + } + + private void pushHibernateTypeInformationDown( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + if ( resolvedHibernateType == null ) { + throw bindingContext().makeMappingException( "Resolved hibernate type can't be null" ); + } + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) { + hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType ); + } + + // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDown( + (BasicAttributeBinding) attributeBinding, + resolvedHibernateType + ); + } + else if ( CompositeAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDown( + (ComponentAttributeSource) attributeSource, + (CompositeAttributeBinding) attributeBinding, + resolvedHibernateType + ); + } + } + + /** + * Resolve domain type for this attribute and also bind jdbc type. + * + * hibernateTypeDescriptor from this binding must already be set with same resolvedHibernateType. + */ + private void pushHibernateTypeInformationDown( + final BasicAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + final SingularAttribute singularAttribute = attributeBinding.getAttribute(); + if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { + singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); + } + bindJdbcDataType( resolvedHibernateType, attributeBinding.getRelationalValueBindings() ); + } + + @SuppressWarnings({ "UnusedParameters" }) + private void pushHibernateTypeInformationDown( + final ComponentAttributeSource attributeSource, + final CompositeAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + final SingularAttribute singularAttribute = attributeBinding.getAttribute(); + if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { + singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); + } + + Iterator subAttributeSourceIterator = attributeSource.attributeSources().iterator(); + for ( AttributeBinding subAttributeBinding : attributeBinding.attributeBindings() ) { + AttributeSource subAttributeSource = subAttributeSourceIterator.next(); + if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + processSingularAttributeTypeInformation( + (SingularAttributeSource) subAttributeSource, + SingularAttributeBinding.class.cast( subAttributeBinding ) + ); + } + else { + throw new AssertionFailure( + "Unknown type of AttributeBinding: " + attributeBinding.getClass() + .getName() + ); + } + } + } + + private LocalBindingContext bindingContext() { + return helperContext.bindingContext(); + } + + private MetadataImplementor metadata() { + return bindingContext().getMetadataImplementor(); + } + + private org.hibernate.metamodel.spi.domain.Type makeJavaType(String name) { + return bindingContext().makeJavaType( name ); + } + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private static methods + private static String determineTypeName( + final HibernateTypeDescriptor hibernateTypeDescriptor) { + return hibernateTypeDescriptor.getExplicitTypeName() != null + ? hibernateTypeDescriptor.getExplicitTypeName() + : hibernateTypeDescriptor.getJavaTypeName(); + } + + + private static Class determineJavaType(final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding) { + Class clazz = attributeSource.getTypeInformation().getJavaType(); + if ( clazz != null ) { + return clazz; + } + final SingularAttribute attribute = attributeBinding.getAttribute(); + try { + final EntityMode entityMode = attributeBinding.getContainer() + .seekEntityBinding() + .getHierarchyDetails() + .getEntityMode(); + if ( entityMode != EntityMode.POJO ) { + return null; + } + final Class ownerClass = attribute.getAttributeContainer().getClassReference(); + return ReflectHelper.reflectedPropertyClass( ownerClass, attribute.getName() ); + } + catch ( Exception ignore ) { + log.debugf( + "Unable to locate attribute [%s] on class [%s]", + attribute.getName(), + attribute.getAttributeContainer().getClassName() + ); + } + return null; + } + + + private static ReflectedCollectionJavaTypes determineJavaType(PluralAttribute attribute) { + try { + final Class ownerClass = attribute.getAttributeContainer().getClassReference(); + PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate( + ownerClass, + attribute.getName() + ); + BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); + return delegate.collectionJavaTypes; + } + catch ( Exception ignore ) { + log.debugf( + "Unable to locate attribute [%s] on class [%s]", + attribute.getName(), + attribute.getAttributeContainer().getClassName() + ); + } + return null; + } + + /** + * + * @return type parameters defined in the hibernate type descriptor or {@code empty property}. + */ + private static Properties getTypeParameters( + final HibernateTypeDescriptor hibernateTypeDescriptor) { + if ( CollectionHelper.isEmpty( hibernateTypeDescriptor.getTypeParameters() ) ) { + return null; + } + else { + Properties typeParameters = new Properties(); + typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() ); + return typeParameters; + } + } + + /** + * Find the referenced attribute name, if it is not id attribute. + * @param pluralAttributeBinding Plural attribute binding that has this reference info + * @return Plural attribute referenced attribute name, or null if it is id. + */ + private static String getReferencedPropertyNameIfNotId( + final PluralAttributeBinding pluralAttributeBinding) { + EntityIdentifier entityIdentifier = + pluralAttributeBinding.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + final String idAttributeName = + entityIdentifier.getAttributeBinding().getAttribute().getName(); + return pluralAttributeBinding.getReferencedPropertyName().equals( idAttributeName ) ? + null : + pluralAttributeBinding.getReferencedPropertyName(); + } + + /** + * @see HibernateTypeHelper#determineJavaType(PluralAttribute) + */ + private static class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { + private final Class ownerClass; + private final String attributeName; + + private ReflectedCollectionJavaTypes collectionJavaTypes; + + private PluralAttributeJavaTypeDeterminerDelegate(Class ownerClass, String attributeName) { + this.ownerClass = ownerClass; + this.attributeName = attributeName; + } + + @Override + public void processBeanInfo(BeanInfo beanInfo) throws Exception { + Class collectionType = null; + Class elementJavaType = null; + Class indexJavaType = null; + + java.lang.reflect.Type collectionAttributeType = null; + if ( beanInfo.getPropertyDescriptors() == null || beanInfo.getPropertyDescriptors().length == 0 ) { + // we need to look for the field and look at it... + //TODO this only works when the field is public accessable or NoSuchElementException will be thrown + collectionAttributeType = ownerClass.getField( attributeName ).getGenericType(); + } + else { + for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { + if ( propertyDescriptor.getName().equals( attributeName ) ) { + if ( propertyDescriptor.getReadMethod() != null ) { + collectionType = propertyDescriptor.getReadMethod().getReturnType(); + collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType(); + } + else if ( propertyDescriptor.getWriteMethod() != null ) { + collectionType = propertyDescriptor.getWriteMethod().getParameterTypes()[0]; + collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0]; + } + } + } + } + + if ( collectionAttributeType != null ) { + if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) { + final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments(); + if ( types == null ) { + } + else if ( types.length == 1 ) { + elementJavaType = (Class) types[0]; + } + else if ( types.length == 2 ) { + // Map + indexJavaType = (Class) types[0]; + elementJavaType = (Class) types[1]; + } + } + else if ( collectionType != null && collectionType.isArray() ) { + elementJavaType = collectionType.getComponentType(); + } + else { + } + } + collectionJavaTypes = new ReflectedCollectionJavaTypes( collectionType, elementJavaType, indexJavaType ); + } + + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/LocalBindingContextManagerImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/LocalBindingContextManagerImpl.java new file mode 100644 index 0000000000..636c364e7e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/LocalBindingContextManagerImpl.java @@ -0,0 +1,176 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.LinkedList; + +import org.hibernate.EntityMode; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.RootEntitySource; + +/** + * @author Gail Badner + */ +public class LocalBindingContextManagerImpl implements EntityHierarchyHelper.LocalBindingContextManager { + private final LocalBindingContextsImpl localBindingContexts = new LocalBindingContextsImpl(); + + @Override + public void cleanupLocalBindingContexts() { + localBindingContexts.cleanup(); + } + + @Override + public void setupLocalBindingContexts(final EntityHierarchy entityHierarchy) { + localBindingContexts.setup( entityHierarchy ); + } + + @Override + public void pushSubEntitySource(EntitySource entitySource) { + localBindingContexts.pushEntitySource( entitySource ); + } + + @Override + public void popSubEntitySource() { + localBindingContexts.popEntitySource(); + } + + @Override + public EntityMode getEntityMode() { + return entityHierarchy().getRootEntitySource().getEntityMode(); + } + + @Override + public InheritanceType getInheritanceType() { + return entityHierarchy().getHierarchyInheritanceType(); + } + + @Override + public RootEntitySource getRootEntitySource() { + return entityHierarchy().getRootEntitySource(); + } + + @Override + public EntitySource getEntitySource() { + if ( localBindingContexts.isEmpty() ) { + throw new IllegalStateException( "No LocalBindingContext defined." ); + } + return localBindingContexts.entitySource(); + } + + @Override + public EntityBinding getEntityBinding() { + return getMetadataImplementor().getEntityBinding( getEntitySource().getEntityName() ); + } + + @Override + public EntityBinding getSuperEntityBinding() { + final EntitySource superEntitySource = getSuperEntitySource(); + return superEntitySource == null ? + null : + getMetadataImplementor().getEntityBinding( superEntitySource.getEntityName() ); + } + + @Override + public LocalBindingContext localBindingContext() { + return getEntitySource().getLocalBindingContext(); + } + + private MetadataImplementor getMetadataImplementor() { + return localBindingContext().getMetadataImplementor(); + } + + private EntitySource getSuperEntitySource() { + if ( localBindingContexts.isEmpty() ) { + throw new IllegalStateException( "No LocalBindingContext defined." ); + } + return localBindingContexts.superEntitySource(); + } + + private EntityHierarchy entityHierarchy() { + if ( localBindingContexts.isEmpty() ) { + throw new IllegalStateException( "No LocalBindingContext defined." ); + } + return localBindingContexts.entityHierarchy(); + } + + // Each EntitySource contains its LocalBindingContext. + private class LocalBindingContextsImpl { + private EntityHierarchy entityHierarchy; + private final LinkedList entitySources = new LinkedList( ); + + private boolean isEmpty() { + return entityHierarchy == null; + } + + private void setup(final EntityHierarchy entityHierarchy) { + // Inheritance type and entity mode applies to entire hierarchy + if ( entityHierarchy == null || entityHierarchy.getRootEntitySource() == null ) { + throw new IllegalArgumentException( + "entityHierarchy and entityHierarchy.getRootEntitySource() must be non-null." + ); + } + if ( this.entityHierarchy != null ) { + throw new IllegalStateException( "Attempt to initialize entityHierarchy when it is already initialized." ); + } + this.entityHierarchy = entityHierarchy; + this.entitySources.push( entityHierarchy.getRootEntitySource() ); + } + + private void cleanup() { + entityHierarchy = null; + entitySources.clear(); + } + + private void pushEntitySource(EntitySource entitySource) { + entitySources.push( entitySource ); + } + + private void popEntitySource() { + entitySources.pop(); + } + + private EntityHierarchy entityHierarchy() { + return entityHierarchy; + } + + private EntitySource entitySource() { + return entitySources.peek(); + } + + private EntitySource superEntitySource() { + if ( entitySources.size() == 1 ) { + return null; + } + final EntitySource currentEntitySource = entitySources.pop(); + final EntitySource superEntitySource = entitySources.peek(); + entitySources.push( currentEntitySource ); + return superEntitySource; + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManyToManyCollectionTableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManyToManyCollectionTableNamingStrategyHelper.java new file mode 100644 index 0000000000..f3a5520322 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManyToManyCollectionTableNamingStrategyHelper.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Table; + +/** + * @author Strong Liu + */ +public class ManyToManyCollectionTableNamingStrategyHelper extends TableNamingStrategyHelper { + private final EntityBinding ownerEntityBinding; + private final EntityBinding inverseEntityBinding; + private final String ownerTableLogicalName; + private final String inverseTableLogicalName; + private final String propertyName; + + public ManyToManyCollectionTableNamingStrategyHelper( + final String attributePath, + final boolean isInverse, + final EntityBinding entityBinding, + final EntityBinding associatedEntityBinding) { + super( entityBinding ); + if ( isInverse ) { + ownerEntityBinding = associatedEntityBinding; + inverseEntityBinding = entityBinding; + } + else { + ownerEntityBinding = entityBinding; + inverseEntityBinding = associatedEntityBinding; + } + ownerTableLogicalName = + Table.class.isInstance( ownerEntityBinding.getPrimaryTable() ) + ? ( (Table) ownerEntityBinding.getPrimaryTable() ).getPhysicalName().getText() + : null; + inverseTableLogicalName = + Table.class.isInstance( inverseEntityBinding.getPrimaryTable() ) + ? ( (Table) inverseEntityBinding.getPrimaryTable() ).getPhysicalName().getText() + : null; + propertyName = attributePath; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return strategy.collectionTableName( + ownerEntityBinding.getEntity().getName(), + ownerTableLogicalName, + inverseEntityBinding.getEntity().getName(), + inverseTableLogicalName, + propertyName + ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return strategy.logicalCollectionTableName( + logicalName, + ownerEntityBinding.getPrimaryTable().getLogicalName().getText(), + inverseEntityBinding.getPrimaryTable().getLogicalName().getText(), + propertyName + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java index ae7818fe1e..78ecebf9f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java @@ -21,28 +21,44 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal; +import java.util.ArrayList; +import java.util.List; import javax.persistence.SharedCacheMode; +import org.jboss.jandex.IndexView; +import org.jboss.logging.Logger; +import org.xml.sax.EntityResolver; + import org.hibernate.HibernateException; +import org.hibernate.MultiTenancyStrategy; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.EJB3DTDEntityResolver; import org.hibernate.cfg.EJB3NamingStrategy; import org.hibernate.cfg.NamingStrategy; import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.metamodel.Metadata; import org.hibernate.metamodel.MetadataBuilder; import org.hibernate.metamodel.MetadataSourceProcessingOrder; import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataSourcesContributor; import org.hibernate.service.ServiceRegistry; - -import org.jboss.logging.Logger; +import org.hibernate.type.BasicType; +import org.hibernate.type.CompositeCustomType; +import org.hibernate.type.CustomType; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; /** + * The implementation of the {@link MetadataBuilder} contract. + * * @author Steve Ebersole */ public class MetadataBuilderImpl implements MetadataBuilder { @@ -85,6 +101,12 @@ public class MetadataBuilderImpl implements MetadataBuilder { public MetadataBuilderImpl(MetadataSources sources, StandardServiceRegistry serviceRegistry) { this.sources = sources; + + for ( MetadataSourcesContributor contributor : + sources.getServiceRegistry().getService( ClassLoaderService.class ) + .loadJavaServices( MetadataSourcesContributor.class ) ) { + contributor.contribute( sources, null ); + } this.options = new OptionsImpl( serviceRegistry ); } @@ -94,6 +116,12 @@ public class MetadataBuilderImpl implements MetadataBuilder { return this; } + @Override + public MetadataBuilder with(EntityResolver entityResolver) { + this.options.entityResolver = entityResolver; + return this; + } + @Override public MetadataBuilder with(MetadataSourceProcessingOrder metadataSourceProcessingOrder) { this.options.metadataSourceProcessingOrder = metadataSourceProcessingOrder; @@ -112,12 +140,36 @@ public class MetadataBuilderImpl implements MetadataBuilder { return this; } + @Override + public MetadataBuilder with(IndexView jandexView) { + this.options.jandexView = jandexView; + return this; + } + @Override public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled) { this.options.useNewIdentifierGenerators = enabled; return this; } + @Override + public MetadataBuilder with(BasicType type) { + options.basicTypeRegistrations.add( type ); + return this; + } + + @Override + public MetadataBuilder with(UserType type, String[] keys) { + options.basicTypeRegistrations.add( new CustomType( type, keys ) ); + return this; + } + + @Override + public MetadataBuilder with(CompositeUserType type, String[] keys) { + options.basicTypeRegistrations.add( new CompositeCustomType( type, keys ) ); + return this; + } + @Override public Metadata build() { return new MetadataImpl( sources, options ); @@ -128,12 +180,18 @@ public class MetadataBuilderImpl implements MetadataBuilder { private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST; private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE; + // todo : entity-resolver maybe needed for ServiceRegistry building also + // maybe move there and default to looking up that value somehow? + private EntityResolver entityResolver = EJB3DTDEntityResolver.INSTANCE; private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE; private AccessType defaultCacheAccessType; private boolean useNewIdentifierGenerators; private boolean globallyQuotedIdentifiers; private String defaultSchemaName; private String defaultCatalogName; + private MultiTenancyStrategy multiTenancyStrategy; + public IndexView jandexView; + public List basicTypeRegistrations = new ArrayList(); public OptionsImpl(StandardServiceRegistry serviceRegistry) { this.serviceRegistry = serviceRegistry; @@ -153,47 +211,29 @@ public class MetadataBuilderImpl implements MetadataBuilder { useNewIdentifierGenerators = configService.getSetting( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( value.toString() ); - } - }, + StandardConverters.BOOLEAN, false ); defaultSchemaName = configService.getSetting( AvailableSettings.DEFAULT_SCHEMA, - new ConfigurationService.Converter() { - @Override - public String convert(Object value) { - return value.toString(); - } - }, + StandardConverters.STRING, null ); defaultCatalogName = configService.getSetting( AvailableSettings.DEFAULT_CATALOG, - new ConfigurationService.Converter() { - @Override - public String convert(Object value) { - return value.toString(); - } - }, + StandardConverters.STRING, null ); globallyQuotedIdentifiers = configService.getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( value.toString() ); - } - }, + StandardConverters.BOOLEAN, false ); + + multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() ); } @Override @@ -211,6 +251,11 @@ public class MetadataBuilderImpl implements MetadataBuilder { return namingStrategy; } + @Override + public EntityResolver getEntityResolver() { + return entityResolver; + } + @Override public AccessType getDefaultAccessType() { return defaultCacheAccessType; @@ -240,5 +285,20 @@ public class MetadataBuilderImpl implements MetadataBuilder { public String getDefaultCatalogName() { return defaultCatalogName; } + + @Override + public MultiTenancyStrategy getMultiTenancyStrategy() { + return multiTenancyStrategy; + } + + @Override + public IndexView getJandexView() { + return jandexView; + } + + @Override + public List getBasicTypeRegistrations() { + return basicTypeRegistrations; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java new file mode 100644 index 0000000000..a305e082ff --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java @@ -0,0 +1,977 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.IndexView; +import org.jboss.logging.Logger; + +import org.hibernate.AssertionFailure; +import org.hibernate.DuplicateMappingException; +import org.hibernate.EntityMode; +import org.hibernate.MappingException; +import org.hibernate.SessionFactory; +import org.hibernate.annotations.common.util.StringHelper; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.engine.spi.NamedQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.SyntheticAttributeHelper; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.internal.source.annotations.AnnotationMetadataSourceProcessorImpl; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.hbm.HbmMetadataSourceProcessorImpl; +import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer; +import org.hibernate.metamodel.spi.MetadataContributor; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.TypeContributor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.domain.BasicType; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.FilterParameterSource; +import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource; +import org.hibernate.metamodel.spi.source.MappingDefaults; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.BasicTypeRegistry; +import org.hibernate.type.TypeFactory; +import org.hibernate.type.TypeResolver; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; + +/** + * Container for configuration data collected during binding the metamodel. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class MetadataImpl implements MetadataImplementor, Serializable { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + MetadataImpl.class.getName() + ); + + private final ServiceRegistry serviceRegistry; + private final Options options; + + private final ClassLoaderService classLoaderService; +// private final ValueHolder persisterClassResolverService; + + private final TypeResolver typeResolver; + + private final MutableIdentifierGeneratorFactory identifierGeneratorFactory; + + private final Database database; + + private final MappingDefaults mappingDefaults; + private final ObjectNameNormalizer nameNormalizer; + + private final Map typeDefinitionMap = new HashMap(); + private final Map filterDefinitionMap = new HashMap(); + + private final Map entityBindingMap = new HashMap(); + private final Map collectionBindingMap = new HashMap(); + private final Map fetchProfiles = new HashMap(); + private final Map imports = new HashMap(); + private final Map idGenerators = new HashMap(); + private final Map namedQueryDefs = new HashMap(); + private final Map namedNativeQueryDefs = new HashMap(); + private final Map resultSetMappings = new HashMap(); + private final Map namedEntityGraphMap = new HashMap( ); + private final Map secondaryTableMap = new HashMap( ); + + private boolean globallyQuotedIdentifiers = false; + + public MetadataImpl(MetadataSources metadataSources, Options options) { + this.serviceRegistry = options.getServiceRegistry(); + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + this.options = options; + this.identifierGeneratorFactory = serviceRegistry.getService( MutableIdentifierGeneratorFactory.class ); + this.database = new Database( options, serviceRegistry.getService( JdbcServices.class ).getJdbcEnvironment() ); + + this.mappingDefaults = new MappingDefaultsImpl(); + this.nameNormalizer = new ObjectNameNormalizer() { + + @Override + protected NamingStrategy getNamingStrategy() { + return MetadataImpl.this.getNamingStrategy(); + } + + @Override + protected boolean isUseQuotedIdentifiersGlobally() { + return MetadataImpl.this.isGloballyQuotedIdentifiers(); + } + }; + + // todo : cache the built index if no inputs have changed (look at gradle-style hashing for up-to-date checking) + boolean autoIndexMemberTypes = serviceRegistry.getService( ConfigurationService.class ).getSetting( + AvailableSettings.ENABLE_AUTO_INDEX_MEMBER_TYPES, StandardConverters.BOOLEAN, false ); + final IndexView jandexView = options.getJandexView() != null + ? metadataSources.wrapJandexView( options.getJandexView() ) + : metadataSources.buildJandexView( autoIndexMemberTypes ); + Collection tables = jandexView.getAnnotations( JPADotNames.TABLE ); + final MetadataSourceProcessor[] metadataSourceProcessors; + if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) { + metadataSourceProcessors = new MetadataSourceProcessor[] { + new HbmMetadataSourceProcessorImpl( this, metadataSources ), + new AnnotationMetadataSourceProcessorImpl( this, jandexView ) + }; + } + else { + metadataSourceProcessors = new MetadataSourceProcessor[] { + new AnnotationMetadataSourceProcessorImpl( this, jandexView ), + new HbmMetadataSourceProcessorImpl( this, metadataSources ) + }; + } + +// this.persisterClassResolverService = new ValueHolder( +// new ValueHolder.DeferredInitializer() { +// @Override +// public PersisterClassResolver initialize() { +// return serviceRegistry.getService( PersisterClassResolver.class ); +// } +// } +// ); + + processTypeDefinitions( metadataSourceProcessors ); + + + // build BasicTypeRegistry and TypeResolver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ultimately this needs to change a little bit to account for HHH-7792 + final BasicTypeRegistry basicTypeRegistry = new BasicTypeRegistry(); + + { + final TypeContributions typeContributions = new TypeContributions() { + @Override + public void contributeType(org.hibernate.type.BasicType type) { + basicTypeRegistry.register( type ); + } + + @Override + public void contributeType(UserType type, String[] keys) { + basicTypeRegistry.register( type, keys ); + } + + @Override + public void contributeType(CompositeUserType type, String[] keys) { + basicTypeRegistry.register( type, keys ); + } + }; + + // add Dialect contributed types + final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); + dialect.contributeTypes( typeContributions, serviceRegistry ); + + // add TypeContributor contributed types. + for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) { + contributor.contribute( typeContributions, serviceRegistry ); + } + } + + // add explicit application registered types + for ( org.hibernate.type.BasicType basicType : options.getBasicTypeRegistrations() ) { + basicTypeRegistry.register( basicType ); + } + + typeResolver = new TypeResolver( basicTypeRegistry, new TypeFactory() ); + + processFilterDefinitions( metadataSourceProcessors ); + processIdentifierGenerators( metadataSourceProcessors ); + processMappings( metadataSourceProcessors ); + bindMappingDependentMetadata( metadataSourceProcessors ); + + for ( MetadataContributor contributor : classLoaderService.loadJavaServices( MetadataContributor.class ) ) { + contributor.contribute( this, jandexView ); + } + + final List jaxbRoots = new ArrayList(); + for ( AdditionalJaxbRootProducer producer : classLoaderService.loadJavaServices( AdditionalJaxbRootProducer.class ) ) { + jaxbRoots.addAll( producer.produceRoots( this, jandexView ) ); + } + final HbmMetadataSourceProcessorImpl processor = new HbmMetadataSourceProcessorImpl( this, jaxbRoots ); + final Binder binder = new Binder( this, identifierGeneratorFactory ); + binder.addEntityHierarchies( processor.extractEntityHierarchies() ); + binder.bindEntityHierarchies(); + + secondPass(metadataSources); + } + + + + // type definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private void processTypeDefinitions(MetadataSourceProcessor[] metadataSourceProcessors) { + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( TypeDescriptorSource typeDescriptorSource : processor.extractTypeDefinitionSources() ) { + addTypeDefinition( + new TypeDefinition( + typeDescriptorSource.getName(), + classLoaderService.classForName( typeDescriptorSource.getTypeImplementationClassName() ), + typeDescriptorSource.getRegistrationKeys(), + typeDescriptorSource.getParameters() + ) + ); + } + } + } + + private void secondPass(MetadataSources metadataSources) { + // This must be done outside of Table, rather than statically, to ensure + // deterministic alias names. See HHH-2448. + int uniqueInteger = 0; + for ( Schema schema : database.getSchemas() ) { + for ( Table table : schema.getTables() ) { + table.setTableNumber( uniqueInteger++ ); + } + } + + if ( metadataSources.getExternalCacheRegionDefinitions().isEmpty() ) { + return; + } + for ( CacheRegionDefinition cacheRegionDefinition : metadataSources.getExternalCacheRegionDefinitions() ) { + final String role = cacheRegionDefinition.getRole(); + if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) { + EntityBinding entityBinding = entityBindingMap.get( role ); + if ( entityBinding != null ) { + entityBinding.getHierarchyDetails() + .setCaching( + new Caching( + cacheRegionDefinition.getRegion(), + AccessType.fromExternalName( cacheRegionDefinition.getUsage() ), + cacheRegionDefinition.isCacheLazy() + ) + ); + }else{ + //logging? + throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" ); + } + + } + else if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.COLLECTION ) { + PluralAttributeBinding pluralAttributeBinding = collectionBindingMap.get( role ); + if(pluralAttributeBinding!=null){ + AbstractPluralAttributeBinding.class.cast( pluralAttributeBinding ).setCaching( new Caching( + cacheRegionDefinition.getRegion(), + AccessType.fromExternalName( cacheRegionDefinition.getUsage() ), + cacheRegionDefinition.isCacheLazy() + ) ); + } else { + //logging? + throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" ); + } + } + } + + } + + @Override + public ObjectNameNormalizer getObjectNameNormalizer() { + return nameNormalizer; + } + + @Override + public void addTypeDefinition( TypeDefinition typeDefinition ) { + if ( typeDefinition == null ) { + throw new IllegalArgumentException( "Type definition is null" ); + } + + // Need to register both by name and registration keys. + if ( !StringHelper.isEmpty( typeDefinition.getName() ) ) { + addTypeDefinition( typeDefinition.getName(), typeDefinition ); + } + + for ( String registrationKey : typeDefinition.getRegistrationKeys() ) { + addTypeDefinition( registrationKey, typeDefinition ); + } + } + + private void addTypeDefinition( String registrationKey, + TypeDefinition typeDefinition ) { + final TypeDefinition previous = typeDefinitionMap.put( + registrationKey, typeDefinition ); + if ( previous != null ) { + LOG.debugf( "Duplicate typedef name [%s] now -> %s", + registrationKey, + typeDefinition.getTypeImplementorClass().getName() ); + } + } + + @Override + public Iterable getTypeDefinitions() { + return typeDefinitionMap.values(); + } + + @Override + public boolean hasTypeDefinition(String registrationKey) { + return typeDefinitionMap.containsKey( registrationKey ); + } + + @Override + public TypeDefinition getTypeDefinition(String registrationKey) { + return typeDefinitionMap.get( registrationKey ); + } + + @Override + public void addNamedEntityGraph(NamedEntityGraphDefinition definition) { + final String name = definition.getRegisteredName(); + final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition ); + if ( previous != null ) { + throw new DuplicateMappingException( "NamedEntityGraph", name ); + } + } + + @Override + public Map getNamedEntityGraphs() { + return namedEntityGraphMap; + } + + // filter definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private void processFilterDefinitions(MetadataSourceProcessor[] metadataSourceProcessors) { + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( FilterDefinitionSource filterDefinitionSource : processor.extractFilterDefinitionSources() ) { + addFilterDefinition( + new FilterDefinition( + filterDefinitionSource.getName(), + filterDefinitionSource.getCondition(), + resolveFilterDefinitionParamType(filterDefinitionSource.getParameterSources()) + ) + ); + } + } + } + + private Map resolveFilterDefinitionParamType(Iterable filterParameterSources){ + if( CollectionHelper.isEmpty( filterParameterSources )){ + return Collections.EMPTY_MAP; + } + Map params = new HashMap( ); + for(final FilterParameterSource parameterSource : filterParameterSources){ + final String name = parameterSource.getParameterName(); + final String typeName = parameterSource.getParameterValueTypeName(); + final org.hibernate.type.Type type = getTypeResolver().heuristicType( typeName ); + params.put( name, type ); + } + return params; + } + + @Override + public void addFilterDefinition(FilterDefinition filterDefinition) { + if ( filterDefinition == null || filterDefinition.getFilterName() == null ) { + throw new IllegalArgumentException( "Filter definition object or name is null: " + filterDefinition ); + } + filterDefinitionMap.put( filterDefinition.getFilterName(), filterDefinition ); + } + @Override + public Map getFilterDefinitions() { + return filterDefinitionMap; + } + + + // identifier generators ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private void processIdentifierGenerators(MetadataSourceProcessor[] metadataSourceProcessors) { + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( IdentifierGeneratorSource identifierGeneratorSource : processor.extractGlobalIdentifierGeneratorSources() ) { + addIdGenerator( + new IdentifierGeneratorDefinition( + identifierGeneratorSource.getGeneratorName(), + identifierGeneratorSource.getGeneratorImplementationName(), + identifierGeneratorSource.getParameters() + ) + ); + } + } + } + + @Override + public void addIdGenerator(IdentifierGeneratorDefinition generator) { + if ( generator == null || generator.getName() == null ) { + throw new IllegalArgumentException( "ID generator object or name is null." ); + } + idGenerators.put( generator.getName(), generator ); + } + + @Override + public IdentifierGeneratorDefinition getIdGenerator(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid generator name" ); + } + return idGenerators.get( name ); + } + + @Override + public void registerIdentifierGenerator(String name, String generatorClassName) { + identifierGeneratorFactory.register( name, classLoaderService.classForName( generatorClassName ) ); + } + + private void processMappings(MetadataSourceProcessor[] metadataSourceProcessors) { + final Binder binder = new Binder( this, identifierGeneratorFactory ); + // Add all hierarchies first, before binding. + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + binder.addEntityHierarchies( processor.extractEntityHierarchies() ); + } + binder.bindEntityHierarchies(); + } + + private void bindMappingDependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors) { + // Create required back references, which are required for one-to-many associations with key bindings that are non-inverse, + // non-nullable, and unidirectional + for ( PluralAttributeBinding pluralAttributeBinding : collectionBindingMap.values() ) { + // Find one-to-many associations with key bindings that are non-inverse and non-nullable + PluralAttributeKeyBinding keyBinding = pluralAttributeBinding.getPluralAttributeKeyBinding(); + if ( keyBinding.isInverse() || keyBinding.isNullable() || + pluralAttributeBinding.getPluralAttributeElementBinding().getNature() != + PluralAttributeElementBinding.Nature.ONE_TO_MANY ) { + continue; + } + // Ensure this isn't a bidirectional association by ensuring FK columns don't match relational columns of any + // many-to-one on opposite side + EntityBinding referencedEntityBinding = + entityBindingMap.get( + pluralAttributeBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor(). + getResolvedTypeMapping().getName() ); + List keyValueBindings = keyBinding.getRelationalValueBindings(); + boolean bidirectional = false; + for ( AttributeBinding attributeBinding : referencedEntityBinding.attributeBindings() ) { + if ( !(attributeBinding instanceof ManyToOneAttributeBinding) ) { + continue; + } + // Check if the opposite many-to-one attribute binding references the one-to-many attribute binding being processed + ManyToOneAttributeBinding manyToOneAttributeBinding = ( ManyToOneAttributeBinding ) attributeBinding; + if ( !manyToOneAttributeBinding.getReferencedEntityBinding().equals( + pluralAttributeBinding.getContainer().seekEntityBinding() ) ) { + continue; + } + // Check if the many-to-one attribute binding's columns match the one-to-many attribute binding's FK columns + // (meaning this is a bidirectional association, and no back reference should be created) + List valueBindings = manyToOneAttributeBinding.getRelationalValueBindings(); + if ( keyValueBindings.size() != valueBindings.size() ) { + continue; + } + bidirectional = true; + for ( int ndx = valueBindings.size(); --ndx >= 0; ) { + if ( keyValueBindings.get(ndx) != valueBindings.get( ndx ) ) { + bidirectional = false; + break; + } + } + if ( bidirectional ) { + break; + } + } + if ( bidirectional ) continue; + + // Create the synthetic back reference attribute + SingularAttribute syntheticAttribute = + referencedEntityBinding.getEntity().createSyntheticSingularAttribute( + SyntheticAttributeHelper.createBackRefAttributeName( pluralAttributeBinding.getAttribute().getRole() ) ); + // Create the back reference attribute binding. + BackRefAttributeBinding backRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding( + syntheticAttribute, pluralAttributeBinding, false + ); + backRefAttributeBinding.getHibernateTypeDescriptor().copyFrom( keyBinding.getHibernateTypeDescriptor() ); + backRefAttributeBinding.getAttribute().resolveType( + keyBinding.getReferencedAttributeBinding().getAttribute().getSingularAttributeType() ); + if ( pluralAttributeBinding.hasIndex() ) { + SingularAttribute syntheticIndexAttribute = + referencedEntityBinding.getEntity().createSyntheticSingularAttribute( + SyntheticAttributeHelper.createIndexBackRefAttributeName( pluralAttributeBinding.getAttribute().getRole() ) ); + BackRefAttributeBinding indexBackRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding( + syntheticIndexAttribute, pluralAttributeBinding, true + ); + final PluralAttributeIndexBinding indexBinding = + ( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding(); + indexBackRefAttributeBinding.getHibernateTypeDescriptor().copyFrom( + indexBinding.getHibernateTypeDescriptor() + ); + indexBackRefAttributeBinding.getAttribute().resolveType( + indexBinding.getPluralAttributeIndexType() + ); + } + } + + for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { + metadataSourceProcessor.processMappingDependentMetadata(); + } + } + + @Override + public void addFetchProfile(FetchProfile profile) { + if ( profile == null || profile.getName() == null ) { + throw new IllegalArgumentException( "Fetch profile object or name is null: " + profile ); + } + FetchProfile old = fetchProfiles.put( profile.getName(), profile ); + if ( old != null ) { + LOG.warn( "Duplicated fetch profile with same name [" + profile.getName() + "] found." ); + } + } + + @Override + public void addNamedNativeQuery(NamedSQLQueryDefinition def) { + if ( def == null ) { + throw new IllegalArgumentException( "Named native query definition object is null" ); + } + if ( def.getName() == null ) { + throw new IllegalArgumentException( "Named native query definition name is null: " + def.getQueryString() ); + } + NamedSQLQueryDefinition old = namedNativeQueryDefs.put( def.getName(), def ); + if ( old != null ) { + LOG.warn( "Duplicated named query with same name["+ old.getName() +"] found" ); + //todo mapping exception?? + // in the old metamodel, the NamedQueryDefinition.name actually not exactly is the one defined in the hbm + // there are two cases: + // if this or is a sub-element of then, then name is as it is + // but if these two are defined in a ( or sub class ), then the name actually is + // entityName.query_name, and the referenced sql resultset mapping's name should also in this form. + // same as result mapping definition + } + } + + public NamedSQLQueryDefinition getNamedNativeQuery(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid native query name" ); + } + return namedNativeQueryDefs.get( name ); + } + + @Override + public Iterable getNamedNativeQueryDefinitions() { + return namedNativeQueryDefs.values(); + } + + @Override + public void addNamedQuery(NamedQueryDefinition def) { + if ( def == null ) { + throw new IllegalArgumentException( "Named query definition is null" ); + } + else if ( def.getName() == null ) { + throw new IllegalArgumentException( "Named query definition name is null: " + def.getQueryString() ); + } + NamedQueryDefinition old = namedQueryDefs.put( def.getName(), def ); + if ( old != null ) { + LOG.warn( "Duplicated named query with same name["+ old.getName() +"] found" ); + //todo mapping exception?? + // in the old metamodel, the NamedQueryDefinition.name actually not exactly is the one defined in the hbm + // there are two cases: + // if this or is a sub-element of then, then name is as it is + // but if these two are defined in a ( or sub class ), then the name actually is + // entityName.query_name, and the referenced sql resultset mapping's name should also in this form. + // same as result mapping definition + } + } + + public NamedQueryDefinition getNamedQuery(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid query name" ); + } + return namedQueryDefs.get( name ); + } + + @Override + public Iterable getNamedQueryDefinitions() { + return namedQueryDefs.values(); + } + + @Override + public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition) { + if ( resultSetMappingDefinition == null || resultSetMappingDefinition.getName() == null ) { + throw new IllegalArgumentException( "Result-set mapping object or name is null: " + resultSetMappingDefinition ); + } + ResultSetMappingDefinition old = resultSetMappings.put( + resultSetMappingDefinition.getName(), + resultSetMappingDefinition + ); + if ( old != null ) { + LOG.warn( "Duplicated sql result set mapping with same name["+ resultSetMappingDefinition.getName() +"] found" ); + //todo mapping exception?? + } + } + + @Override + public Map getResultSetMappingDefinitions() { + return resultSetMappings; + } + +// private PersisterClassResolver persisterClassResolverService() { +// return persisterClassResolverService.getValue(); +// } + + @Override + public Options getOptions() { + return options; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + @SuppressWarnings( {"unchecked"}) + public Class locateClassByName(String name) { + return classLoaderService.classForName( name ); + } + + @Override + public Type makeJavaType(String className) { + // todo : have this perform some analysis of the incoming type name to determine appropriate return + return new BasicType( className, makeClassReference( className ) ); + } + + // TODO: ClassLoaderService.classForName( className ) does not work for primitives, so add mapping + // from primitive class names -> class. + private static final Map> primitiveClassesByName = new HashMap>(); + static { + primitiveClassesByName.put("int", Integer.TYPE ); + primitiveClassesByName.put( "long", Long.TYPE ); + primitiveClassesByName.put( "double", Double.TYPE ); + primitiveClassesByName.put( "float", Float.TYPE ); + primitiveClassesByName.put( "bool", Boolean.TYPE ); + primitiveClassesByName.put( "char", Character.TYPE ); + primitiveClassesByName.put( "byte", Byte.TYPE ); + primitiveClassesByName.put( "void", Void.TYPE ); + primitiveClassesByName.put( "short", Short.TYPE ); + } + + @Override + public ValueHolder> makeClassReference(final String className) { + return new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Class initialize() { + Class primitiveClass = primitiveClassesByName.get( className ); + return primitiveClass == null ? + classLoaderService.classForName( className ) : + primitiveClass; + } + } + ); + } + + @Override + public String qualifyClassName(String name) { + return name; + } + + @Override + public Database getDatabase() { + return database; + } + + public EntityBinding getEntityBinding(String entityName) { + return entityBindingMap.get( entityName ); + } + + @Override + public EntityBinding getRootEntityBinding(String entityName) { + EntityBinding binding = entityBindingMap.get( entityName ); + if ( binding == null ) { + throw new IllegalStateException( "Unknown entity binding: " + entityName ); + } + + do { + if ( binding.isRoot() ) { + return binding; + } + binding = binding.getSuperEntityBinding(); + } while ( binding != null ); + + throw new AssertionFailure( "Entity binding has no root: " + entityName ); + } + @Override + public Iterable getEntityBindings() { + return entityBindingMap.values(); + } + @Override + public void addEntity(EntityBinding entityBinding) { + final String entityName = entityBinding.getEntity().getName(); + if ( entityBindingMap.containsKey( entityName ) ) { + throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName ); + } + entityBindingMap.put( entityName, entityBinding ); + final boolean isPOJO = entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO; + final String className = isPOJO ? entityBinding.getEntity().getClassName() : null; + if ( isPOJO && StringHelper.isEmpty( className ) ) { + throw new MappingException( "Entity[" + entityName + "] is mapped as pojo but don't have a class name" ); + } + if ( StringHelper.isNotEmpty( className ) && !entityBindingMap.containsKey( className ) ) { + entityBindingMap.put( className, entityBinding ); + } + } + + @Override + public void addSecondaryTable(SecondaryTable secondaryTable) { + secondaryTableMap.put( secondaryTable.getSecondaryTableReference().getLogicalName(), secondaryTable ); + } + + @Override + public Map getSecondaryTables() { + return secondaryTableMap; + } + + public PluralAttributeBinding getCollection(String collectionRole) { + return collectionBindingMap.get( collectionRole ); + } + + @Override + public Iterable getCollectionBindings() { + return collectionBindingMap.values(); + } + + @Override + public void addCollection(PluralAttributeBinding pluralAttributeBinding) { + final String owningEntityName = pluralAttributeBinding.getContainer().seekEntityBinding().getEntityName(); + final String containerPathBase = pluralAttributeBinding.getContainer().getPathBase(); + final String attributeName = pluralAttributeBinding.getAttribute().getName(); + final String collectionRole; + if ( StringHelper.isEmpty( containerPathBase ) ) { + collectionRole = owningEntityName + '.' + attributeName; + } + else { + collectionRole = owningEntityName + '.' + containerPathBase + '.' + attributeName; + } + if ( collectionBindingMap.containsKey( collectionRole ) ) { + throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, collectionRole ); + } + collectionBindingMap.put( collectionRole, pluralAttributeBinding ); + } + @Override + public void addImport(String importName, String entityName) { + if ( importName == null || entityName == null ) { + throw new IllegalArgumentException( "Import name or entity name is null" ); + } + LOG.tracev( "Import: {0} -> {1}", importName, entityName ); + String old = imports.put( importName, entityName ); + if ( old != null ) { + LOG.debug( "import name [" + importName + "] overrode previous [{" + old + "}]" ); + } + } + + @Override + public Map getImports() { + return imports; + } + + @Override + public Iterable getFetchProfiles() { + return fetchProfiles.values(); + } + + public TypeResolver getTypeResolver() { + return typeResolver; + } + + @Override + public SessionFactoryBuilder getSessionFactoryBuilder() { + return new SessionFactoryBuilderImpl( this ); + } + + @Override + public SessionFactory buildSessionFactory() { + return getSessionFactoryBuilder().build(); + } + + @Override + public NamingStrategy getNamingStrategy() { + return options.getNamingStrategy(); + } + + @Override + public boolean isGloballyQuotedIdentifiers() { + return globallyQuotedIdentifiers || getOptions().isGloballyQuotedIdentifiers(); + } + + public void setGloballyQuotedIdentifiers(boolean globallyQuotedIdentifiers){ + this.globallyQuotedIdentifiers = globallyQuotedIdentifiers; + } + + @Override + public MappingDefaults getMappingDefaults() { + return mappingDefaults; + } + + private final MetaAttributeContext globalMetaAttributeContext = new MetaAttributeContext(); + + @Override + public MetaAttributeContext getGlobalMetaAttributeContext() { + return globalMetaAttributeContext; + } + + @Override + public MetadataImplementor getMetadataImplementor() { + return this; + } + + private static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id"; + private static final String DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME = "tenant_id"; + private static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class"; + private static final String DEFAULT_CASCADE = "none"; + private static final String DEFAULT_PROPERTY_ACCESS = "property"; + + @Override + public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { + return identifierGeneratorFactory; + } + + @Override + public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + @Override + public String getIdentifierPropertyName(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + return idBinding == null ? null : idBinding.getAttribute().getName(); + } + + @Override + public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding attributeBinding = entityBinding.locateAttributeBindingByPath( propertyName, true ); + if ( attributeBinding == null ) { + throw new MappingException( "unknown property: " + entityName + '.' + propertyName ); + } + return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + } + + private class MappingDefaultsImpl implements MappingDefaults { + + @Override + public String getPackageName() { + return null; + } + + @Override + public String getSchemaName() { + return options.getDefaultSchemaName(); + } + + @Override + public String getCatalogName() { + return options.getDefaultCatalogName(); + } + + @Override + public String getIdColumnName() { + return DEFAULT_IDENTIFIER_COLUMN_NAME; + } + + @Override + public String getTenantIdColumnName() { + return DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME; + } + + @Override + public String getDiscriminatorColumnName() { + return DEFAULT_DISCRIMINATOR_COLUMN_NAME; + } + + @Override + public String getCascadeStyle() { + return DEFAULT_CASCADE; + } + + @Override + public String getPropertyAccessorName() { + return DEFAULT_PROPERTY_ACCESS; + } + + @Override + public boolean areAssociationsLazy() { + return true; + } + + @Override + public AccessType getCacheAccessType() { + return options.getDefaultAccessType(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java new file mode 100644 index 0000000000..4908bffcae --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; + +/** + * @author Brett Meyer + */ +public class NaturalIdUniqueKeyHelper { + + private final HelperContext helperContext; + + private Map naturalIdUniqueKeys + = new HashMap(); + + public NaturalIdUniqueKeyHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + /** + * Natural ID columns must reside in one single UniqueKey within the Table. + * To prevent separate UniqueKeys from being created, this keeps track of + * them in a HashMap. + * + * @param table + * @param column + */ + public void addUniqueConstraintForNaturalIdColumn( + final TableSpecification table, final Column column) { + UniqueKey uniqueKey; + if ( naturalIdUniqueKeys.containsKey( table ) ) { + uniqueKey = naturalIdUniqueKeys.get( table ); + } + else { + // TODO: For now, leave this out of the naming strategy. It has nothing to do with the columns. + String keyName = "UK_" + HashedNameUtil.hashedName( table.getLogicalName().getText() + "_NaturalID" ); + uniqueKey = new UniqueKey(); + uniqueKey.setTable( table ); + uniqueKey.setName( keyName ); + table.addUniqueKey( uniqueKey ); + naturalIdUniqueKeys.put( table, uniqueKey ); + } + uniqueKey.addColumn( column ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalIdentifierHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalIdentifierHelper.java new file mode 100644 index 0000000000..789bf748d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalIdentifierHelper.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Gail Badner + */ +public class RelationalIdentifierHelper { + + private final HelperContext helperContext; + + RelationalIdentifierHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + public String normalizeDatabaseIdentifier( + final String explicitName, + final ObjectNameNormalizer.NamingStrategyHelper helper) { + return getObjectNameNormalizer().normalizeDatabaseIdentifier( explicitName, helper ); + } + + public Identifier createIdentifier(final String name){ + return createIdentifier( name, null ); + } + + public Identifier createIdentifier(final String name, final String defaultName) { + String identifier = StringHelper.isEmpty( name ) ? defaultName : name; + identifier = quotedIdentifier( identifier ); + return Identifier.toIdentifier( identifier ); + } + + public String quotedIdentifier(final String name) { + return getObjectNameNormalizer().normalizeIdentifierQuoting( name ); + } + + private ObjectNameNormalizer getObjectNameNormalizer() { + return helperContext.bindingContext().getMetadataImplementor().getObjectNameNormalizer(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalValueBindingHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalValueBindingHelper.java new file mode 100644 index 0000000000..fa89b674e1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RelationalValueBindingHelper.java @@ -0,0 +1,194 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.TruthValue; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.DerivedValueSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; + +/** + * @author Gail Badner + */ +public class RelationalValueBindingHelper { + + private final HelperContext helperContext; + + public RelationalValueBindingHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + public boolean hasDerivedValue(List relationalValueBindings) { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if (relationalValueBinding.isDerived() ) { + return true; + } + } + return false; + } + + public List createRelationalValueBindings( + final AttributeBindingContainer attributeBindingContainer, + final RelationalValueSourceContainer valueSourceContainer, + final Attribute attribute, + final TableSpecification defaultTable, + final boolean forceNonNullable) { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( attribute.getName() ); + } + }; + return createRelationalValueBindings( + attributeBindingContainer, + valueSourceContainer, + defaultTable, + Collections.singletonList( defaultNamingStrategy ), + forceNonNullable + ); + } + + public List createRelationalValueBindings( + final AttributeBindingContainer attributeBindingContainer, + final RelationalValueSourceContainer valueSourceContainer, + final TableSpecification defaultTable, + final List defaultNameStrategies, + final boolean forceNonNullable) { + final List valueBindings = new ArrayList(); + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = SingularAttributeSource.class.isInstance( + valueSourceContainer + ) ? SingularAttributeSource.class.cast( valueSourceContainer ).getNaturalIdMutability() + : SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + final boolean isNaturalId = naturalIdMutability != SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + final boolean isImmutableNaturalId = isNaturalId && ( naturalIdMutability == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE ); + final boolean reallyForceNonNullable = forceNonNullable ; //|| isNaturalId; todo is a natural id column should be not nullable? + + if ( valueSourceContainer.relationalValueSources().isEmpty() ) { + for ( Binder.DefaultNamingStrategy defaultNameStrategy : defaultNameStrategies ) { + final Column column = helperContext.tableHelper().locateOrCreateColumn( + defaultTable, + null, + new DefaultColumnNamingStrategyHelper( defaultNameStrategy ) + ); + column.setNullable( !reallyForceNonNullable && valueSourceContainer.areValuesNullableByDefault() ); + if ( isNaturalId ) { + helperContext.naturalIdUniqueKeyHelper().addUniqueConstraintForNaturalIdColumn( defaultTable, column ); + } + valueBindings.add( + new RelationalValueBinding( + defaultTable, + column, + valueSourceContainer.areValuesIncludedInInsertByDefault(), + valueSourceContainer.areValuesIncludedInUpdateByDefault() && !isImmutableNaturalId + ) + ); + } + + } + else { + for ( int i = 0 ; i < valueSourceContainer.relationalValueSources().size(); i++ ) { + final RelationalValueSource valueSource = valueSourceContainer.relationalValueSources().get( i ); + final TableSpecification table = + valueSource.getContainingTableName() == null + ? defaultTable + : attributeBindingContainer.seekEntityBinding() + .locateTable( valueSource.getContainingTableName() ); + if ( valueSource.getNature() == RelationalValueSource.Nature.COLUMN ) { + final ColumnSource columnSource = (ColumnSource) valueSource; + final DefaultColumnNamingStrategyHelper defaultColumnNamingStrategyHelper = + new DefaultColumnNamingStrategyHelper( + StringHelper.isEmpty( columnSource.getName() ) ? + defaultNameStrategies.get( i ) : + null + ); + Column column = helperContext.tableHelper().locateOrCreateColumn( + table, + columnSource, + defaultColumnNamingStrategyHelper, + reallyForceNonNullable, + valueSourceContainer.areValuesNullableByDefault() + ); + if ( isNaturalId ) { + helperContext.naturalIdUniqueKeyHelper().addUniqueConstraintForNaturalIdColumn( table, column ); + } + final boolean isIncludedInInsert = + TruthValue.toBoolean( + columnSource.isIncludedInInsert(), + valueSourceContainer.areValuesIncludedInInsertByDefault() + ); + final boolean isIncludedInUpdate = + TruthValue.toBoolean( + columnSource.isIncludedInUpdate(), + valueSourceContainer.areValuesIncludedInUpdateByDefault() + ); + valueBindings.add( + new RelationalValueBinding( + table, + column, + isIncludedInInsert, + !isImmutableNaturalId && isIncludedInUpdate + ) + ); + } + else { + final DerivedValue derivedValue = + table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() ); + valueBindings.add( new RelationalValueBinding( table, derivedValue ) ); + } + } + } + return valueBindings; + } + + public List bindInverseRelationalValueBindings( + TableSpecification table, + List values) { + final List relationalValueBindings = + new ArrayList( values.size() ); + for ( Value value : values ) { + final RelationalValueBinding relationalValueBinding = + value.getValueType() == Value.ValueType.COLUMN ? + new RelationalValueBinding( table, (Column) value, false, false ) : + new RelationalValueBinding( table, (DerivedValue) value ); + relationalValueBindings.add( relationalValueBinding ); + } + return relationalValueBindings; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java new file mode 100644 index 0000000000..6bd19dfeaa --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java @@ -0,0 +1,202 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.EmptyInterceptor; +import org.hibernate.EntityMode; +import org.hibernate.EntityNameResolver; +import org.hibernate.Interceptor; +import org.hibernate.ObjectNotFoundException; +import org.hibernate.SessionFactory; +import org.hibernate.SessionFactoryObserver; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Settings; +import org.hibernate.cfg.SettingsFactory; +import org.hibernate.context.spi.CurrentTenantIdentifierResolver; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.internal.DefaultCustomEntityDirtinessStrategy; +import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.tuple.entity.EntityTuplizer; + +/** + * @author Gail Badner + * @author Steve Ebersole + */ +public class SessionFactoryBuilderImpl implements SessionFactoryBuilder { + private final MetadataImplementor metadata; + private final SessionFactoryOptionsImpl options; + + SessionFactoryBuilderImpl(MetadataImplementor metadata) { + this.metadata = metadata; + options = new SessionFactoryOptionsImpl( metadata.getOptions().getServiceRegistry() ); + } + + @Override + public SessionFactoryBuilder with(Interceptor interceptor) { + this.options.interceptor = interceptor; + return this; + } + + @Override + public SessionFactoryBuilder with(CustomEntityDirtinessStrategy dirtinessStrategy) { + this.options.customEntityDirtinessStrategy = dirtinessStrategy; + return this; + } + + @Override + public SessionFactoryBuilder with(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) { + this.options.currentTenantIdentifierResolver = currentTenantIdentifierResolver; + return this; + } + + @Override + public SessionFactoryBuilder add(SessionFactoryObserver... observers) { + this.options.sessionFactoryObserverList.addAll( Arrays.asList( observers ) ); + return this; + } + + @Override + public SessionFactoryBuilder add(EntityNameResolver... entityNameResolvers) { + this.options.entityNameResolvers.addAll( Arrays.asList( entityNameResolvers ) ); + return this; + } + + @Override + public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate) { + this.options.entityNotFoundDelegate = entityNotFoundDelegate; + return this; + } + + @Override + public SessionFactoryBuilder with(EntityMode entityMode, Class tuplizerClass){ + this.options.settings.getEntityTuplizerFactory().registerDefaultTuplizerClass( entityMode, tuplizerClass ); + return this; + } + + @Override + public SessionFactory build() { + return new SessionFactoryImpl( metadata, options ); + } + + private static class SessionFactoryOptionsImpl implements SessionFactory.SessionFactoryOptions { + private final StandardServiceRegistry serviceRegistry; + + private Interceptor interceptor; + private CustomEntityDirtinessStrategy customEntityDirtinessStrategy; + private CurrentTenantIdentifierResolver currentTenantIdentifierResolver; + private List sessionFactoryObserverList = new ArrayList(); + private List entityNameResolvers = new ArrayList(); + private EntityNotFoundDelegate entityNotFoundDelegate; + private Settings settings; + + public SessionFactoryOptionsImpl(StandardServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; + + final Map configurationSettings = serviceRegistry.getService( ConfigurationService.class ).getSettings(); + + final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class ); + + this.interceptor = strategySelector.resolveDefaultableStrategy( + Interceptor.class, + configurationSettings.get( AvailableSettings.INTERCEPTOR ), + EmptyInterceptor.INSTANCE + ); + + // TODO: should there be a DefaultEntityNotFoundDelegate.INSTANCE? + this.entityNotFoundDelegate = new EntityNotFoundDelegate() { + public void handleEntityNotFound(String entityName, Serializable id) { + throw new ObjectNotFoundException( id, entityName ); + } + }; + + this.customEntityDirtinessStrategy = strategySelector.resolveDefaultableStrategy( + CustomEntityDirtinessStrategy.class, + configurationSettings.get( AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY ), + DefaultCustomEntityDirtinessStrategy.INSTANCE + ); + + this.currentTenantIdentifierResolver = strategySelector.resolveStrategy( + CurrentTenantIdentifierResolver.class, + configurationSettings.get( AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER ) + ); + Properties properties = new Properties(); + properties.putAll( configurationSettings ); + this.settings = new SettingsFactory().buildSettings( properties, serviceRegistry ); + } + + @Override + public StandardServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + public Interceptor getInterceptor() { + return interceptor; + } + + @Override + public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { + return customEntityDirtinessStrategy; + } + + @Override + public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { + return currentTenantIdentifierResolver; + } + + @Override + public Settings getSettings() { + return settings; + } + + @Override + public SessionFactoryObserver[] getSessionFactoryObservers() { + return sessionFactoryObserverList.toArray( new SessionFactoryObserver[sessionFactoryObserverList.size()] ); + } + + @Override + public EntityNameResolver[] getEntityNameResolvers() { + return entityNameResolvers.toArray( new EntityNameResolver[entityNameResolvers.size()] ); + } + + @Override + public EntityNotFoundDelegate getEntityNotFoundDelegate() { + return entityNotFoundDelegate; + } + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SourceIndex.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SourceIndex.java new file mode 100644 index 0000000000..5754c0a918 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SourceIndex.java @@ -0,0 +1,474 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.AssertionFailure; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; + +/** + * @author Gail Badner + */ +public class SourceIndex { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + SourceIndex.class.getName() + ); + private static final String EMPTY_STRING = ""; + + private final Map entitySourceIndexByEntityName = new HashMap(); + private final Map attributeSourcesByKey = new HashMap(); + private final Map mappedByAttributeKeysByOwnerAttributeKeys = + new HashMap(); + + public void indexEntitySource(final RootEntitySource rootEntitySource, final EntitySource entitySource) { + String entityName = entitySource.getEntityName(); + EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, rootEntitySource, entitySource ); + entitySourceIndexByEntityName.put( entityName, entitySourceIndex ); + log.debugf( "Mapped entity source \"%s\"", entityName ); + indexAttributes( entitySourceIndex ); + } + + public void resolveAssociationSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) { + entitySourceIndexByEntityName + .get( bindingContextContext.getEntityBinding().getEntityName() ) + .resolveAttributeSources( bindingContextContext ); + } + + public Map getSingularAttributeSources( + String entityName, + boolean isMappedBy, + SingularAttributeSource.Nature nature) { + final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName ); + return entitySourceIndex.getSingularAttributeSources( isMappedBy, nature ); + } + + public Map getPluralAttributeSources( + String entityName, + boolean isInverse) { + final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName ); + return entitySourceIndex.getPluralAttributeSources( isInverse ); + } + + public AttributeSource attributeSource(final String entityName, final String attributePath) { + return attributeSourcesByKey.get( new AttributeSourceKey( entityName, attributePath ) ); + } + + public AttributeSource locateAttributeSourceOwnedBy(final String entityName, final String attributePath) { + AttributeSourceKey ownerKey = new AttributeSourceKey( entityName, attributePath ); + AttributeSourceKey mappedByKey = mappedByAttributeKeysByOwnerAttributeKeys.get( ownerKey ); + return mappedByKey == null ? null : attributeSourcesByKey.get( mappedByKey ); + } + + public EntitySource entitySource(final String entityName) { + return entitySourceIndexByEntityName.get( entityName ).entitySource; + } + + private EntitySourceIndex entitySourceIndex(String entityName) { + return entitySourceIndexByEntityName.get( entityName ); + } + + private void indexAttributes(EntitySourceIndex entitySourceIndex) { + final String emptyString = ""; + if ( entitySourceIndex.entitySource instanceof RootEntitySource ) { + indexIdentifierAttributeSources( entitySourceIndex ); + } + for ( final AttributeSource attributeSource : entitySourceIndex.entitySource.attributeSources() ) { + indexAttributeSources(entitySourceIndex, emptyString, attributeSource, false ); + } + } + + private void indexIdentifierAttributeSources(EntitySourceIndex entitySourceIndex) { + RootEntitySource rootEntitySource = (RootEntitySource) entitySourceIndex.entitySource; + IdentifierSource identifierSource = rootEntitySource.getIdentifierSource(); + switch ( identifierSource.getNature() ) { + case SIMPLE: + final AttributeSource identifierAttributeSource = + ( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + indexAttributeSources( entitySourceIndex, EMPTY_STRING, identifierAttributeSource, true ); + break; + case NON_AGGREGATED_COMPOSITE: + final List nonAggregatedAttributeSources = + ( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier(); + for ( SingularAttributeSource nonAggregatedAttributeSource : nonAggregatedAttributeSources ) { + indexAttributeSources( entitySourceIndex, EMPTY_STRING, nonAggregatedAttributeSource, true ); + } + break; + case AGGREGATED_COMPOSITE: + final ComponentAttributeSource aggregatedAttributeSource = + ( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + indexAttributeSources( entitySourceIndex, EMPTY_STRING, aggregatedAttributeSource, true ); + break; + default: + throw new AssertionFailure( + String.format( "Unknown type of identifier: [%s]", identifierSource.getNature() ) + ); + } + } + + private void indexAttributeSources( + EntitySourceIndex entitySourceIndex, + String pathBase, + AttributeSource attributeSource, + boolean isInIdentifier) { + AttributeSourceKey key = new AttributeSourceKey( entitySourceIndex.entitySource.getEntityName(), pathBase, attributeSource.getName() ); + attributeSourcesByKey.put( key, attributeSource ); + log.debugf( + "Mapped attribute source \"%s\"", key + ); + if ( attributeSource.isSingular() ) { + entitySourceIndex.indexSingularAttributeSource( pathBase, (SingularAttributeSource) attributeSource, isInIdentifier ); + } + else { + entitySourceIndex.indexPluralAttributeSource( pathBase, (PluralAttributeSource) attributeSource ); + } + if ( attributeSource instanceof ComponentAttributeSource ) { + for ( AttributeSource subAttributeSource : ( (ComponentAttributeSource) attributeSource ).attributeSources() ) { + indexAttributeSources( + entitySourceIndex, + key.attributePath(), + subAttributeSource, + isInIdentifier + ); + } + } + } + + void addMappedByAssociationByOwnerAssociation(AttributeSourceKey ownerKey, AttributeSourceKey ownedKey) { + mappedByAttributeKeysByOwnerAttributeKeys.put( + ownerKey, + ownedKey + ); + + } + + public static class AttributeSourceKey { + + private final String entityName; + private final String containerPath; + private final String attributeName; + + private AttributeSourceKey(final String entityName, final String containerPath, final String attributeName) { + this.entityName = entityName; + this.containerPath = containerPath; + this.attributeName = attributeName; + } + + private AttributeSourceKey(final String entityName, final String attributePath) { + this.entityName = entityName; + int indexLastDot = attributePath.lastIndexOf( '.' ); + if ( indexLastDot == -1 ) { + this.containerPath = EMPTY_STRING; + this.attributeName = attributePath; + } + else { + this.containerPath = attributePath.substring( 0, indexLastDot ); + this.attributeName = attributePath.substring( indexLastDot + 1 ); + } + } + + public String entityName() { + return entityName; + } + + public String containerPath() { + return containerPath; + } + + public String attributeName() { + return attributeName; + } + + public String attributePath() { + return StringHelper.isEmpty( containerPath ) ? + attributeName : + containerPath + '.' + attributeName; + } + + public String getAttributePathQualifiedByEntityName() { + return entityName + '.' + attributePath(); + } + + @Override + public String toString() { + return getAttributePathQualifiedByEntityName(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + AttributeSourceKey that = (AttributeSourceKey) o; + + if ( !attributeName.equals( that.attributeName ) ) { + return false; + } + if ( !containerPath.equals( that.containerPath ) ) { + return false; + } + if ( !entityName.equals( that.entityName ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = entityName.hashCode(); + result = 31 * result + containerPath.hashCode(); + result = 31 * result + attributeName.hashCode(); + return result; + } + } + + private static class EntitySourceIndex { + private final SourceIndex sourceIndex; + private final RootEntitySource rootEntitySource; + private final EntitySource entitySource; + private final Map> + identifierAttributeSourcesByNature = new EnumMap>( SingularAttributeSource.Nature.class ); + private final Map> + nonMappedBySingularAttributeSourcesByNature = new EnumMap>( SingularAttributeSource.Nature.class ); + private final Map> + mappedBySingularAttributeSourcesByNature = new EnumMap>( SingularAttributeSource.Nature.class ); + private final Map unresolvedSingularAttributeSourcesByKey = + new HashMap(); + + // TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests + // depend on the ordering + // TODO: rework nonInversePluralAttributeSourcesByKey and inversePluralAttributeSourcesByKey + private final Map nonInversePluralAttributeSourcesByKey = + new LinkedHashMap(); + private final Map inversePluralAttributeSourcesByKey = + new LinkedHashMap(); + + private EntitySourceIndex( + final SourceIndex sourceIndex, + final RootEntitySource rootEntitySource, + final EntitySource entitySource) { + this.sourceIndex = sourceIndex; + this.rootEntitySource = rootEntitySource; + this.entitySource = entitySource; + } + + private void indexSingularAttributeSource( + String pathBase, + SingularAttributeSource attributeSource, + boolean isInIdentifier) { + final AttributeSourceKey attributeSourceKey = + new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() ); + if ( attributeSource.getNature() == null ) { + unresolvedSingularAttributeSourcesByKey.put( attributeSourceKey, attributeSource ); + return; + } + + final Map> map; + if ( isInIdentifier ) { + map = identifierAttributeSourcesByNature; + } + else if ( ToOneAttributeSource.class.isInstance( attributeSource ) && + ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) { + map = mappedBySingularAttributeSourcesByNature; + } + else { + map = nonMappedBySingularAttributeSourcesByNature; + } + indexSingularAttributeSource( + attributeSourceKey, + attributeSource, + map + ); + } + + private static void indexSingularAttributeSource( + AttributeSourceKey attributeSourceKey, + SingularAttributeSource attributeSource, + Map> map) { + final Map singularAttributeSources; + if ( map.containsKey( attributeSource.getNature() ) ) { + singularAttributeSources = map.get( attributeSource.getNature() ); + } + else { + singularAttributeSources = new LinkedHashMap(); + map.put( attributeSource.getNature(), singularAttributeSources ); + } + if ( singularAttributeSources.put( attributeSourceKey, attributeSource ) != null ) { + throw new AssertionFailure( + String.format( "Attempt to reindex attribute source for: [%s]", attributeSourceKey ) + ); + } + } + + private Map getSingularAttributeSources( + boolean isMappedBy, + SingularAttributeSource.Nature nature) { + final Map entries; + if ( isMappedBy && mappedBySingularAttributeSourcesByNature.containsKey( nature ) ) { + entries = Collections.unmodifiableMap( mappedBySingularAttributeSourcesByNature.get( nature ) ); + } + else if ( !isMappedBy && nonMappedBySingularAttributeSourcesByNature.containsKey( nature ) ) { + entries = Collections.unmodifiableMap( nonMappedBySingularAttributeSourcesByNature.get( nature ) ); + } + else { + entries = Collections.emptyMap(); + } + return entries; + } + + private void indexPluralAttributeSource( + String pathBase, + PluralAttributeSource attributeSource) { + AttributeSourceKey key = + new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() ); + final Map map = + attributeSource.isInverse() ? + inversePluralAttributeSourcesByKey : + nonInversePluralAttributeSourcesByKey; + if ( map.put( key, attributeSource ) != null ) { + throw new AssertionFailure( + String.format( + "Attempt to reindex attribute source for: [%s]", + new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() ) + ) + ); + } + } + + private Map getPluralAttributeSources( + boolean isInverse) { + final Map map = + isInverse ? + inversePluralAttributeSourcesByKey : + nonInversePluralAttributeSourcesByKey; + return Collections.unmodifiableMap( map ); + } + + private void resolveAttributeSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) { + final AttributeSourceResolutionContext sourceResolutionContext = + new AttributeSourceResolutionContextImpl( bindingContextContext ); + // Resolve plural attributes. + for ( PluralAttributeSource pluralAttributeSource : inversePluralAttributeSourcesByKey.values() ) { + if ( pluralAttributeSource.getMappedBy() != null ) { + // This plural attribute is mappedBy the opposite side of the association, + // so it needs to be resolved. + pluralAttributeSource.resolvePluralAttributeElementSource( sourceResolutionContext ); + } + if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) { + IndexedPluralAttributeSource indexedPluralAttributeSource = + (IndexedPluralAttributeSource) pluralAttributeSource; + indexedPluralAttributeSource.resolvePluralAttributeIndexSource( sourceResolutionContext ); + } + } + + for ( PluralAttributeSource pluralAttributeSource : nonInversePluralAttributeSourcesByKey.values() ) { + if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) { + IndexedPluralAttributeSource indexedPluralAttributeSource = + (IndexedPluralAttributeSource) pluralAttributeSource; + indexedPluralAttributeSource.resolvePluralAttributeIndexSource( sourceResolutionContext ); + } + } + + // cycle through unresolved SingularAttributeSource. + // TODO: rework so approach is similar to one-to-many/many-to-many resolution. + for ( Iterator> it = unresolvedSingularAttributeSourcesByKey.entrySet().iterator(); it.hasNext(); ) { + final Map.Entry entry = it.next(); + final AttributeSourceKey attributeSourceKey = entry.getKey(); + final SingularAttributeSource attributeSource = entry.getValue(); + if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) { + throw new AssertionFailure( + String.format( "Only a ToOneAttributeSource is expected to have a null nature; attribute: %s ", attributeSourceKey ) + ); + } + ToOneAttributeSource toOneAttributeSource = (ToOneAttributeSource) attributeSource; + toOneAttributeSource.resolveToOneAttributeSource( sourceResolutionContext ); + if ( toOneAttributeSource.getNature() == null ) { + throw new AssertionFailure( + String.format( "Null nature should have been resolved: %s ", attributeSourceKey ) + ); + } + indexSingularAttributeSource( + attributeSourceKey, + attributeSource, + toOneAttributeSource.isMappedBy() ? + mappedBySingularAttributeSourcesByNature : + nonMappedBySingularAttributeSourcesByNature + ); + } + } + + class AttributeSourceResolutionContextImpl implements AttributeSourceResolutionContext { + private final EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext; + + public AttributeSourceResolutionContextImpl( + EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) { + this.bindingContextContext = bindingContextContext; + } + + @Override + public IdentifierSource resolveIdentifierSource(String entityName) { + return bindingContextContext.getRootEntitySource().getIdentifierSource(); + } + + @Override + public AttributeSource resolveAttributeSource(String entityName, String attributeName) { + return sourceIndex.attributeSource( entityName, attributeName ); + } + + @Override + public List resolveIdentifierColumns() { + return bindingContextContext.getEntityBinding().getPrimaryTable().getPrimaryKey().getColumns(); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java new file mode 100644 index 0000000000..f3f64218b3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java @@ -0,0 +1,258 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.TruthValue; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.IndexNamingStrategyHelper; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.UniqueKeyNamingStrategyHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.InLineViewSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MappingDefaults; +import org.hibernate.metamodel.spi.source.SizeSource; +import org.hibernate.metamodel.spi.source.TableSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.jboss.logging.Logger; + +/** + * @author Gail Badner + */ +public class TableHelper { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + TableHelper.class.getName() + ); + + private final HelperContext helperContext; + + public TableHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } + + public TableSpecification createTable( + final TableSpecificationSource tableSpecSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + return createTable( tableSpecSource, namingStrategyHelper, null ); + } + + public TableSpecification createTable( + final TableSpecificationSource tableSpecSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, + final Table includedTable) { + if ( tableSpecSource == null && namingStrategyHelper == null ) { + throw bindingContext().makeMappingException( + "An explicit name must be specified for the table" + ); + } + final boolean isTableSourceNull = tableSpecSource == null; + final Schema schema = resolveSchema( tableSpecSource ); + + TableSpecification tableSpec; + if ( isTableSourceNull || tableSpecSource instanceof TableSource ) { + String explicitName = isTableSourceNull ? null : TableSource.class.cast( tableSpecSource ).getExplicitTableName(); + String tableName = normalizeDatabaseIdentifier( explicitName, namingStrategyHelper ); + String logicTableName = TableNamingStrategyHelper.class.cast( namingStrategyHelper ).getLogicalName( + bindingContext().getNamingStrategy() + ); + tableSpec = createTableSpecification( schema, tableName, logicTableName, includedTable ); + } + else { + final InLineViewSource inLineViewSource = (InLineViewSource) tableSpecSource; + tableSpec = schema.createInLineView( + createIdentifier( inLineViewSource.getLogicalName() ), + inLineViewSource.getSelectStatement() + ); + } + return tableSpec; + } + + public Schema resolveSchema(final TableSpecificationSource tableSpecSource) { + final boolean tableSourceNull = tableSpecSource == null; + final MappingDefaults mappingDefaults = bindingContext().getMappingDefaults(); + final String explicitCatalogName = tableSourceNull ? null : tableSpecSource.getExplicitCatalogName(); + final String explicitSchemaName = tableSourceNull ? null : tableSpecSource.getExplicitSchemaName(); + final Schema.Name schemaName = + new Schema.Name( + createIdentifier( explicitCatalogName, mappingDefaults.getCatalogName() ), + createIdentifier( explicitSchemaName, mappingDefaults.getSchemaName() ) + ); + return bindingContext().getMetadataImplementor().getDatabase().locateSchema( schemaName ); + } + + public TableSpecification createTableSpecification( + final Schema schema, + final String tableName, + final String logicTableName, + final Table includedTable) { + final Identifier logicalTableId = createIdentifier( logicTableName ); + final Identifier physicalTableId = createIdentifier( tableName ); + final Table table = schema.locateTable( logicalTableId ); + if ( table != null ) { + return table; + } + TableSpecification tableSpec; + if ( includedTable == null ) { + tableSpec = schema.createTable( logicalTableId, physicalTableId ); + } + else { + tableSpec = schema.createDenormalizedTable( logicalTableId, physicalTableId, includedTable ); + } + return tableSpec; + } + + public Column locateOrCreateColumn( + final TableSpecification table, + final String columnName, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + if ( columnName == null && namingStrategyHelper == null ) { + throw bindingContext().makeMappingException( + "Cannot resolve name for column because no name was specified and namingStrategyHelper is null." + ); + } + final String resolvedColumnName = normalizeDatabaseIdentifier( + columnName, + namingStrategyHelper + ); + return table.locateOrCreateColumn( resolvedColumnName ); + } + + public Column locateOrCreateColumn( + final TableSpecification table, + final ColumnSource columnSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, + final boolean forceNotNull, + final boolean isNullableByDefault) { + final Column column = locateOrCreateColumn( table, columnSource.getName(), namingStrategyHelper ); + resolveColumnNullable( table, columnSource, forceNotNull, isNullableByDefault, column ); + column.setDefaultValue( columnSource.getDefaultValue() ); + column.setSqlType( columnSource.getSqlType() ); + if ( columnSource.getSizeSource() != null ) { + final SizeSource sizeSource = columnSource.getSizeSource(); + if ( sizeSource.isLengthDefined() ) { + column.getSize().setLength( sizeSource.getLength() ); + } + if ( sizeSource.isPrecisionDefined() ) { + column.getSize().setPrecision( sizeSource.getPrecision() ); + } + if ( sizeSource.isScaleDefined() ) { + column.getSize().setScale( sizeSource.getScale() ); + } + } + column.setJdbcDataType( columnSource.getDatatype() ); + column.setReadFragment( columnSource.getReadFragment() ); + column.setWriteFragment( columnSource.getWriteFragment() ); + column.setCheckCondition( columnSource.getCheckCondition() ); + column.setComment( columnSource.getComment() ); + + if (columnSource.isUnique()) { + createUniqueKey( table, Collections.singletonList( column ), null ); + } + return column; + } + + public void createUniqueKey( + final TableSpecification table, + final List columns, + final String name) { + final UniqueKey uk = new UniqueKey(); + for ( final Column column : columns ) { + uk.addColumn( column ); + } + uk.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new UniqueKeyNamingStrategyHelper( table, columns ) ); + + uk.setName( normalizedName ); + table.addUniqueKey( uk ); + } + + public void createIndex( + final TableSpecification table, + final List columns, + final String name) { + final Index idx = new Index(); + for ( final Column column : columns ) { + idx.addColumn( column ); + } + idx.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new IndexNamingStrategyHelper( table, columns ) ); + + idx.setName( normalizedName ); + table.addIndex( idx ); + } + + private void resolveColumnNullable( + final TableSpecification table, + final ColumnSource columnSource, + final boolean forceNotNull, + final boolean isNullableByDefault, + final Column column) { + if ( forceNotNull ) { + column.setNullable( false ); + if ( columnSource.isNullable() == TruthValue.TRUE ) { + log.warnf( + "Natural Id column[%s] from table[%s] has explicit set to allow nullable, we have to make it force not null ", + columnSource.getName(), + table.getLogicalName().getText() + ); + } + } + else { + // if the column is already non-nullable, leave it alone + if ( column.isNullable() ) { + column.setNullable( TruthValue.toBoolean( columnSource.isNullable(), isNullableByDefault ) ); + } + } + } + + private Identifier createIdentifier(String name) { + return helperContext.relationalIdentifierHelper().createIdentifier( name ); + } + + private Identifier createIdentifier(String name, String defaultName) { + return helperContext.relationalIdentifierHelper().createIdentifier( name, defaultName ); + } + + private String normalizeDatabaseIdentifier(String explicitName, ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + return helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( explicitName, namingStrategyHelper ); + } + + private LocalBindingContext bindingContext() { + return helperContext.bindingContext(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableNamingStrategyHelper.java new file mode 100644 index 0000000000..3e25a6bde5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableNamingStrategyHelper.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +/** + * @author Strong Liu + */ +class TableNamingStrategyHelper implements ObjectNameNormalizer.LogicalNamingStrategyHelper { + protected final EntityBinding entityBinding; + protected final String entityName; + protected String logicalName; + + TableNamingStrategyHelper(EntityBinding entityBinding) { + this.entityBinding = entityBinding; + this.entityName = getImplicitTableName(); + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + String name = getImplicitTableName(); + return strategy.classToTableName( name ); + } + + protected String getImplicitTableName() { + return StringHelper.isNotEmpty( entityBinding.getJpaEntityName() ) ? entityBinding.getJpaEntityName() : entityBinding + .getEntity().getName(); + } + + @Override + public String handleExplicitName(NamingStrategy strategy, String tableName) { + this.logicalName = tableName; + return strategy.tableName( tableName ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return logicalName == null ? entityName : logicalName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java new file mode 100644 index 0000000000..35f07c3b3f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.List; + +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; + +/** + + * @author Gail Badner + + */ +public interface AssociationRelationalBindingResolver { + + SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + final ToOneAttributeSource attributeSource, + final EntityBinding referencedEntityBinding); + + List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeBinding referencedAttributeBinding); + + ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding); + + SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + final EntityBinding referencedEntityBinding); + + // TODO: referencedAttributeBinding and referencedEntityBinding are both included due to a bug that can + // cause entityBinding != entityBinding.hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer() + List resolveManyToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeBinding referencedAttributeBinding, + final EntityBinding referencedEntityBinding); + + ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding); + + List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding); + + ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding); + + TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding); + + List resolvePluralAttributeKeyRelationalValueBindings( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding); + + ForeignKey resolvePluralAttributeKeyForeignKey( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding); + + SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java new file mode 100644 index 0000000000..1e10ccb64a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java @@ -0,0 +1,359 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.ForeignKeyHelper; +import org.hibernate.metamodel.internal.HelperContext; +import org.hibernate.metamodel.internal.RelationalValueBindingHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.ManyToManyPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.source.AssociationSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + + * @author Gail Badner + + */ +public class MappedByAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver { + private final HelperContext helperContext; + + public MappedByAssociationRelationalBindingResolverImpl(HelperContext helperContext) { + this.helperContext = helperContext; + } + + @Override + public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return (SingularAttributeBinding) referencedEntityBinding.locateAttributeBindingByPath( + getMappedByAssociationSource( attributeSource ).getMappedBy(), + true + ); + } + + @Override + public List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding) { + return Collections.emptyList(); + } + + @Override + public ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding) { + // TODO: get rid of this duplication!!! + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) { + throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." ); + } + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + attributeSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + attributeSource.getExplicitForeignKeyName(), + sourceTable, + sourceColumns, + targetTable, + targetColumns + ); + } + + @Override + public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + AttributeBindingContainer attributeBindingContainer, + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + // This is a mappedBy many-to-one. This should only happen when the owning many-to-one uses a join table. + // TODO: confirm the above is true. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return referencedEntityBinding.locateAttributeBinding( + ownerSecondaryTable.getForeignKeyReference().getTargetTable(), + ownerSecondaryTable.getForeignKeyReference().getTargetColumns(), + true + ); + } + + @Override + public List resolveManyToOneRelationalValueBindings( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding, + EntityBinding referencedEntityBinding) { + // A many-to-one can only have mappedBy specified if there is a join table. + // TODO: confirm this is true. + // The relational value bindings for the attribute being processed + // will contain the columns that make up the FK join tables on the + // owner's secondary table. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return relationalValueBindingHelper().bindInverseRelationalValueBindings( + ownerSecondaryTable.getForeignKeyReference().getSourceTable(), + ownerSecondaryTable.getForeignKeyReference().getSourceColumns() + ); + } + + @Override + public ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding) { + // A many-to-one can only have mappedBy specified if there is a join table. + // TODO: confirm this is true. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return ownerSecondaryTable.getForeignKeyReference(); + } + + @Override + public List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( elementSource ) + ); + final List relationalValueBindings; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + // the owner is a many-to-one on a join table; the target will be the FK target + // for the secondary table. + final SecondaryTable ownerSecondaryTable = + referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() ); + relationalValueBindings = relationalValueBindingHelper().bindInverseRelationalValueBindings( + collectionTable, + ownerSecondaryTable.getForeignKeyReference().getSourceColumns() + ); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + relationalValueBindings = relationalValueBindingHelper().bindInverseRelationalValueBindings( + collectionTable, + ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getValues() + ); + } + return relationalValueBindings; + } + } + + @Override + public ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( elementSource ) + ); + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + // the owner is a many-to-one on a join table; the target will be the FK target + // for the secondary table. + final SecondaryTable ownerSecondaryTable = + referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() ); + return ownerSecondaryTable.getForeignKeyReference(); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + return ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey(); + } + } + + @Override + public TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) pluralAttributeSource.getElementSource() ) + ); + return ownerAttributeBinding.getAttribute().isSingular() ? + ( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getTable() : + ( (PluralAttributeBinding) ownerAttributeBinding ).getPluralAttributeKeyBinding().getCollectionTable(); + } + + @Override + public List resolvePluralAttributeKeyRelationalValueBindings( + PluralAttributeSource attributeSource, + EntityBinding entityBinding, + TableSpecification collectionTable, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + return ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getRelationalValueBindings(); + } + else { + final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final ManyToManyPluralAttributeElementBinding ownerElementBinding = + (ManyToManyPluralAttributeElementBinding) pluralOwnerAttributeBinding.getPluralAttributeElementBinding(); + return ownerElementBinding.getRelationalValueBindings(); + } + } + + @Override + public ForeignKey resolvePluralAttributeKeyForeignKey( + PluralAttributeSource attributeSource, + EntityBinding entityBinding, + TableSpecification collectionTable, + List sourceRelationalValueBindings, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + final ForeignKey foreignKey; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + foreignKey = ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getForeignKey(); + } + else { + final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final ManyToManyPluralAttributeElementBinding ownerElementBinding = + (ManyToManyPluralAttributeElementBinding) pluralOwnerAttributeBinding.getPluralAttributeElementBinding(); + foreignKey = ownerElementBinding.getForeignKey(); + } + foreignKey.setDeleteRule( attributeSource.getKeySource().getOnDeleteAction() ); + return foreignKey; + + } + + @Override + public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + AttributeBindingContainer attributeBindingContainer, + PluralAttributeSource attributeSource) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + final SingularAttributeBinding referencedAttributeBinding; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + referencedAttributeBinding = + ( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getReferencedAttributeBinding(); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final ManyToManyPluralAttributeElementBinding ownerElementBinding = + (ManyToManyPluralAttributeElementBinding) ownerPluralAttributeBinding + .getPluralAttributeElementBinding(); + referencedAttributeBinding = attributeBindingContainer.seekEntityBinding().locateAttributeBinding( + ownerElementBinding.getForeignKey().getTargetTable(), + ownerElementBinding.getForeignKey().getTargetColumns(), + true + ); + if ( referencedAttributeBinding == null ) { + throw new NotYetImplementedException( "Referenced columns not used by an attribute binding is not supported yet." ); + } + } + return referencedAttributeBinding; + } + + private LocalBindingContext bindingContext() { + return helperContext.bindingContext(); + } + + private MappedByAssociationSource getMappedByAssociationSource(AssociationSource associationSource) { + if ( !associationSource.isMappedBy() || !MappedByAssociationSource.class.isInstance( associationSource ) ) { + throw new AssertionFailure( "Expected a MappedByAssociationSource." ); + } + return (MappedByAssociationSource) associationSource; + } + + private AttributeBinding getOwnerAttributeBinding(MappedByAssociationSource associationSource) { + final EntityBinding referencedEntityBinding = bindingContext().getMetadataImplementor().getEntityBinding( + associationSource.getReferencedEntityName() + ); + final AttributeBinding ownerAttributeBinding = referencedEntityBinding.locateAttributeBindingByPath( + associationSource.getMappedBy(), + true + ); + if ( ownerAttributeBinding == null ) { + throw bindingContext().makeMappingException( + String.format( + "Attribute not found: [%s.%s]", + referencedEntityBinding.getEntityName(), + associationSource.getMappedBy() + ) + ); + } + return ownerAttributeBinding; + } + + private SecondaryTable getOwnerSecondaryTable( + MappedByAssociationSource attributeSource, + EntityBinding referencedEntityBinding) { + SingularAssociationAttributeBinding ownerAttributeBinding = + (SingularAssociationAttributeBinding) referencedEntityBinding.locateAttributeBinding( + attributeSource.getMappedBy() + ); + TableSpecification table = ownerAttributeBinding.getTable(); + if ( referencedEntityBinding.getPrimaryTable().equals( table ) ) { + throw new AssertionFailure( "many-to-one has mappedby specified but it does not use a join table." ); + } + return referencedEntityBinding.getSecondaryTables().get( table.getLogicalName() ); + } + + private ForeignKeyHelper foreignKeyHelper() { + return helperContext.foreignKeyHelper(); + } + + private RelationalValueBindingHelper relationalValueBindingHelper() { + return helperContext.relationalValueBindingHelper(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java new file mode 100644 index 0000000000..77ddd77fc5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java @@ -0,0 +1,428 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.ForeignKeyHelper; +import org.hibernate.metamodel.internal.HelperContext; +import org.hibernate.metamodel.internal.ManyToManyCollectionTableNamingStrategyHelper; +import org.hibernate.metamodel.internal.RelationalValueBindingHelper; +import org.hibernate.metamodel.internal.TableHelper; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AssociationSource; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + + * @author Gail Badner + + */ +public class StandardAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver { + private final HelperContext helperContext; + + public StandardAssociationRelationalBindingResolverImpl(HelperContext helperContext) { + this.helperContext = helperContext; + } + + @Override + public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + @Override + public List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding) { + if ( ! attributeSource.relationalValueSources().isEmpty() ) { + final TableSpecification defaultTable = + locateDefaultTableSpecificationForAttribute( + attributeBindingContainer, + attributeSource + ); + return resolveRelationalValueBindings( + attributeSource, + attributeBindingContainer.seekEntityBinding(), + defaultTable, + false, + attributeSource.getDefaultNamingStrategies( + attributeBindingContainer.seekEntityBinding().getEntity().getName(), + defaultTable.getLogicalName().getText(), + referencedAttributeBinding + ) + ); + } + else { + return Collections.emptyList(); + } + } + + private TableSpecification locateDefaultTableSpecificationForAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.getContainingTableName() == null ? + attributeBindingContainer.getPrimaryTable() : + attributeBindingContainer.seekEntityBinding().locateTable( attributeSource.getContainingTableName() ); + } + + + @Override + public ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding) { + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) { + throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." ); + } + + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + attributeSource + ); + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + attributeSource.getExplicitForeignKeyName(), + sourceTable, + sourceColumns, + targetTable, + targetColumns + ); + } + + @Override + public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + AttributeBindingContainer attributeBindingContainer, + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + @Override + public List resolveManyToOneRelationalValueBindings( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding, + EntityBinding referencedEntityBinding) { + final TableSpecification defaultTable = + locateDefaultTableSpecificationForAttribute( + attributeBindingContainer, + attributeSource + ); + return resolveRelationalValueBindings( + attributeSource, + attributeBindingContainer.seekEntityBinding(), + defaultTable, + false, + attributeSource.getDefaultNamingStrategies( + attributeBindingContainer.seekEntityBinding().getEntity().getName(), + defaultTable.getLogicalName().getText(), + referencedAttributeBinding + ) + ); + + } + + @Override + public ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding) { + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + return locateOrCreateForeignKey( + attributeSource, + referencedEntityBinding, + relationalValueBindings.get( 0 ).getTable(), + relationalValueBindings, + targetColumns + ); + } + + @Override + public List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + final List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + elementSource + ); + final List namingStrategies = new ArrayList( targetColumns.size() ); + for ( final Column targetColumn : targetColumns ) { + namingStrategies.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + elementSource.getAttributeSource().getName(), + referencedEntityBinding.getEntityName(), + referencedEntityBinding.getPrimaryTableName(), + targetColumn.getColumnName().getText() + ); + } + } + ); + } + return resolveRelationalValueBindings( + elementSource, + entityBinding, + collectionTable, + true, + namingStrategies + ); + } + + @Override + public ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final ManyToManyPluralAttributeElementSource elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding) { + final List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + elementSource + ); + return locateOrCreateForeignKey( + elementSource, + referencedEntityBinding, + collectionTable, + relationalValueBindings, + targetColumns + ); + } + + @Override + public TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding) { + + final TableSpecificationSource collectionTableSource = pluralAttributeSource.getCollectionTableSpecificationSource(); + return tableHelper().createTable( + collectionTableSource, + new ManyToManyCollectionTableNamingStrategyHelper( + attributePath, + pluralAttributeSource.isInverse(), + entityBinding, + referencedEntityBinding + ) + ); + } + + @Override + public List resolvePluralAttributeKeyRelationalValueBindings( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + final PluralAttributeKeySource keySource = attributeSource.getKeySource(); + + final ListtargetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + keySource + ); + final List namingStrategies = new ArrayList( targetColumns.size() ); + + final String ownedAttributeName; + if ( attributeSource.getElementSource().getNature().isAssociation() ) { + final AssociationSource associationSource = (AssociationSource) attributeSource.getElementSource(); + if ( associationSource.getOwnedAssociationSources().size() > 1 ) { + throw new NotYetImplementedException( "Cannot determine default naming strategy when an association owns more than 1 other association." ); + } + if ( associationSource.getOwnedAssociationSources().isEmpty() ) { + ownedAttributeName = null; + } + else { + final AssociationSource ownedAssociationSource = associationSource.getOwnedAssociationSources().iterator().next(); + ownedAttributeName = ownedAssociationSource.getAttributeSource().getName(); + } + } + else { + ownedAttributeName = null; + } + + for ( final Column targetColumn : targetColumns ) { + namingStrategies.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + ownedAttributeName, + entityBinding.getEntityName(), + entityBinding.getPrimaryTableName(), + targetColumn.getColumnName().getText() + ); + } + } + ); + } + return resolveRelationalValueBindings( + keySource, + entityBinding, + collectionTable, + attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.ONE_TO_MANY, + namingStrategies + ); + } + + @Override + public ForeignKey resolvePluralAttributeKeyForeignKey( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final List sourceRelationalValueBindings, + final EntityBinding referencedEntityBinding) { + final PluralAttributeKeySource keySource = attributeSource.getKeySource(); + List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + keySource + ); + ForeignKey foreignKey = locateOrCreateForeignKey( + keySource, + referencedEntityBinding, + collectionTable, + sourceRelationalValueBindings, + targetColumns + ); + foreignKey.setDeleteRule( keySource.getOnDeleteAction() ); + return foreignKey; + } + + @Override + public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + AttributeBindingContainer attributeBindingContainer, + PluralAttributeSource attributeSource) { + return foreignKeyHelper().determineReferencedAttributeBinding( + attributeSource.getKeySource(), + attributeBindingContainer.seekEntityBinding() + ); + } + + + private SingularAttributeBinding resolveReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return foreignKeyHelper().determineReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + public List resolveRelationalValueBindings( + final RelationalValueSourceContainer relationalValueSourceContainer, + EntityBinding entityBinding, + TableSpecification defaultTable, + boolean forceNonNullable, + List defaultNamingStrategies) { + return relationalValueBindingHelper().createRelationalValueBindings( + entityBinding, + relationalValueSourceContainer, + defaultTable, + defaultNamingStrategies, + forceNonNullable + ); + } + + private ForeignKey locateOrCreateForeignKey( + final ForeignKeyContributingSource foreignKeyContributingSource, + final EntityBinding referencedEntityBinding, + final TableSpecification sourceTable, + final List sourceRelationalValueBindings, + final List targetColumns) { + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + foreignKeyContributingSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + foreignKeyContributingSource.getExplicitForeignKeyName(), + sourceTable, + extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), + targetTable, + targetColumns + ); + } + + private TableHelper tableHelper() { + return helperContext.tableHelper(); + } + + private ForeignKeyHelper foreignKeyHelper() { + return helperContext.foreignKeyHelper(); + } + + private RelationalValueBindingHelper relationalValueBindingHelper() { + return helperContext.relationalValueBindingHelper(); + } + + // TODO: try to get rid of this... + private static List extractColumnsFromRelationalValueBindings( + final List valueBindings) { + List columns = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : valueBindings ) { + final Value value = relationalValueBinding.getValue(); + // todo : currently formulas are not supported here... :( + if ( !Column.class.isInstance( value ) ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + columns.add( (Column) value ); + } + return columns; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/OverriddenMappingDefaults.java similarity index 90% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/OverriddenMappingDefaults.java index 170361272c..c671f69a7f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/OverriddenMappingDefaults.java @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.metamodel.source.MappingDefaults; +import org.hibernate.metamodel.spi.source.MappingDefaults; /** * Represents a "nested level" in the mapping defaults stack. @@ -38,6 +38,7 @@ public class OverriddenMappingDefaults implements MappingDefaults { private final String schemaName; private final String catalogName; private final String idColumnName; + private final String tenantIdColumnName; private final String discriminatorColumnName; private final String cascade; private final String propertyAccess; @@ -49,6 +50,7 @@ public class OverriddenMappingDefaults implements MappingDefaults { String schemaName, String catalogName, String idColumnName, + String tenantIdColumnName, String discriminatorColumnName, String cascade, String propertyAccess, @@ -61,6 +63,7 @@ public class OverriddenMappingDefaults implements MappingDefaults { this.schemaName = schemaName; this.catalogName = catalogName; this.idColumnName = idColumnName; + this.tenantIdColumnName = tenantIdColumnName; this.discriminatorColumnName = discriminatorColumnName; this.cascade = cascade; this.propertyAccess = propertyAccess; @@ -87,6 +90,11 @@ public class OverriddenMappingDefaults implements MappingDefaults { return idColumnName == null ? overriddenValues.getIdColumnName() : idColumnName; } + @Override + public String getTenantIdColumnName() { + return tenantIdColumnName == null ? overriddenValues.getTenantIdColumnName() : tenantIdColumnName; + } + @Override public String getDiscriminatorColumnName() { return discriminatorColumnName == null ? overriddenValues.getDiscriminatorColumnName() : discriminatorColumnName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractConstraintSource.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractConstraintSource.java index 3e26ca40b7..6b6e1a27da 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractConstraintSource.java @@ -21,24 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations; import java.util.List; -import org.hibernate.metamodel.source.binder.UniqueConstraintSource; +import org.hibernate.metamodel.spi.source.ConstraintSource; /** * @author Hardy Ferentschik */ -class UniqueConstraintSourceImpl implements UniqueConstraintSource { - private final String name; - private final String tableName; - private final List columnNames; +class AbstractConstraintSource implements ConstraintSource { + protected final String name; + protected final String tableName; + protected final List columnNames; + protected final List orderings; - UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { + protected AbstractConstraintSource(String name, String tableName, List columnNames, List orderings) { this.name = name; this.tableName = tableName; this.columnNames = columnNames; + this.orderings = orderings; } @Override @@ -52,9 +54,13 @@ class UniqueConstraintSourceImpl implements UniqueConstraintSource { } @Override - public Iterable columnNames() { + public List columnNames() { return columnNames; } + + public List orderings() { + return orderings; + } @Override public boolean equals(Object o) { @@ -65,11 +71,14 @@ class UniqueConstraintSourceImpl implements UniqueConstraintSource { return false; } - UniqueConstraintSourceImpl that = (UniqueConstraintSourceImpl) o; + AbstractConstraintSource that = (AbstractConstraintSource) o; if ( columnNames != null ? !columnNames.equals( that.columnNames ) : that.columnNames != null ) { return false; } + if ( orderings != null ? !orderings.equals( that.orderings ) : that.orderings != null ) { + return false; + } if ( name != null ? !name.equals( that.name ) : that.name != null ) { return false; } @@ -85,19 +94,9 @@ class UniqueConstraintSourceImpl implements UniqueConstraintSource { int result = name != null ? name.hashCode() : 0; result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 ); + result = 31 * result + ( orderings != null ? orderings.hashCode() : 0 ); return result; } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "UniqueConstraintSourceImpl" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( ", tableName='" ).append( tableName ).append( '\'' ); - sb.append( ", columnNames=" ).append( columnNames ); - sb.append( '}' ); - return sb.toString(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractManyToManyPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..a2f16aff32 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractManyToManyPluralAttributeElementSourceImpl.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.engine.FetchTiming; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; + +/** + + * @author Gail Badner + + */ +public abstract class AbstractManyToManyPluralAttributeElementSourceImpl + extends AbstractPluralAssociationElementSourceImpl + implements ManyToManyPluralAttributeElementSource { + + + public AbstractManyToManyPluralAttributeElementSourceImpl( + PluralAttributeSourceImpl pluralAttributeSource, + final String relativePath) { + super( pluralAttributeSource, relativePath ); + } + + @Override + public boolean isUnique() { + return pluralAssociationAttribute().getNature() == MappedAttribute.Nature.ONE_TO_MANY; + } + + @Override + public String getReferencedEntityAttributeName() { + // HBM only + return null; + } + + @Override + public FilterSource[] getFilterSources() { + return new FilterSource[0]; //todo + } + + @Override + public String getWhere() { + return pluralAssociationAttribute().getWhereClause(); + } + + @Override + public FetchTiming getFetchTiming() { + return FetchTiming.IMMEDIATE; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_MANY; + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( pluralAssociationAttribute().getOrderBy() ); + } + + @Override + public String getOrder() { + return pluralAssociationAttribute().getOrderBy(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAssociationElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAssociationElementSourceImpl.java new file mode 100644 index 0000000000..c5ac98963f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAssociationElementSourceImpl.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.spi.source.AssociationPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; + +/** + + * @author Gail Badner + + */ +public abstract class AbstractPluralAssociationElementSourceImpl + extends AbstractPluralAttributeElementSourceImpl implements AssociationPluralAttributeElementSource { + private final PluralAttributeSourceImpl pluralAttributeSource; + private final Set ownedAssociationSources = new HashSet( ); + + public AbstractPluralAssociationElementSourceImpl( + final PluralAttributeSourceImpl pluralAttributeSource, + final String relativePath) { + super( pluralAttributeSource.pluralAssociationAttribute(), relativePath ); + this.pluralAttributeSource = pluralAttributeSource; + } + + @Override + public String getReferencedEntityName() { + return pluralAssociationAttribute().getReferencedEntityType(); + } + + @Override + public boolean isNotFoundAnException() { + return !pluralAssociationAttribute().isIgnoreNotFound(); + } + + public AttributeSource getAttributeSource() { + return pluralAttributeSource; + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } + + @Override + public Set getCascadeStyles() { + final Set cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( + pluralAssociationAttribute().getCascadeTypes(), + pluralAssociationAttribute().getHibernateCascadeTypes(), + pluralAssociationAttribute().getContext() + ); + if ( getNature() == Nature.ONE_TO_MANY && pluralAssociationAttribute().isOrphanRemoval() ) { + cascadeStyles.add( CascadeStyles.DELETE_ORPHAN ); + } + return cascadeStyles; + } + + protected PluralAssociationAttribute pluralAssociationAttribute() { + return pluralAttributeSource.pluralAssociationAttribute(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..1e3fd4b556 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeElementSourceImpl.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Map; + +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; + +/** + * @author Strong Liu + */ +public abstract class AbstractPluralAttributeElementSourceImpl implements AnnotationAttributeSource { + private final String path; + protected AttributeOverride attributeOverride; + protected AssociationOverride associationOverride; + + public AbstractPluralAttributeElementSourceImpl( + final PluralAssociationAttribute associationAttribute, + final String relativePath) { + if ( associationAttribute.getPluralAttributeNature() == PluralAttributeSource.Nature.MAP ) { + this.path = relativePath + ".value"; + } + else { + this.path = relativePath + ".element"; + } + } + + @Override + public void applyAttributeOverride(Map attributeOverrideMap) { + this.attributeOverride = attributeOverrideMap.get( path ); + } + + @Override + public void applyAssociationOverride(Map associationOverrideMap) { + this.associationOverride = associationOverrideMap.get( path ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..fc13128f92 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractPluralAttributeIndexSourceImpl.java @@ -0,0 +1,84 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Map; + +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralAttributeIndexSourceImpl implements PluralAttributeIndexSource { + private final PluralAssociationAttribute attribute; + + public AbstractPluralAttributeIndexSourceImpl(PluralAssociationAttribute attribute) { + this.attribute = attribute; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return new HibernateTypeSource() { + @Override + public String getName() { + return attribute.getIndexTypeResolver().getExplicitHibernateTypeName(); + } + + @Override + public Map getParameters() { + return attribute.getIndexTypeResolver().getExplicitHibernateTypeParameters(); + } + @Override + public Class getJavaType() { + return null; + } + }; + } + + @Override + public boolean isReferencedEntityAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + protected PluralAssociationAttribute pluralAssociationAttribute() { + return attribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractToOneAttributeSourceImpl.java new file mode 100644 index 0000000000..b8e9f1637d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AbstractToOneAttributeSourceImpl.java @@ -0,0 +1,138 @@ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.hibernate.type.ForeignKeyDirection; + +public abstract class AbstractToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource{ + private final SingularAssociationAttribute associationAttribute; + private final Set cascadeStyles; + private final Set ownedAssociationSources = new HashSet(); + private SingularAttributeSource.Nature nature; + + public AbstractToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath) { + super( associationAttribute, relativePath ); + this.associationAttribute = associationAttribute; + this.cascadeStyles = determineCascadeStyles( associationAttribute ); + } + + private static Set determineCascadeStyles(SingularAssociationAttribute associationAttribute) { + final Set cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( + associationAttribute.getCascadeTypes(), + associationAttribute.getHibernateCascadeTypes(), + associationAttribute.getContext() + ); + if ( associationAttribute.isOrphanRemoval() ) { + cascadeStyles.add( CascadeStyles.DELETE_ORPHAN ); + } + return cascadeStyles; + } + + @Override + public SingularAttributeSource.Nature getNature() { + return nature; + } + + protected SingularAssociationAttribute associationAttribute() { + return associationAttribute; + } + + protected void setNature(SingularAttributeSource.Nature nature) { + if ( this.nature != null ) { + throw new IllegalStateException( "nature is already initialized." ); + } + this.nature = nature; + } + + @Override + public AttributeSource getAttributeSource() { + return this; + } + + @Override + public String getReferencedEntityName() { + return associationAttribute.getReferencedEntityType(); + } + + @Override + public boolean isUnique() { + return MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() ); + } + + @Override + public boolean isNotFoundAnException() { + return !associationAttribute.isIgnoreNotFound(); + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } + + @Override + public FetchTiming getFetchTiming() { + return associationAttribute.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE; + } + + @Override + public FetchStyle getFetchStyle() { + if ( associationAttribute.getFetchStyle() != null ) { + return associationAttribute.getFetchStyle(); + } + else { + return associationAttribute.isLazy() ? FetchStyle.SELECT : FetchStyle.JOIN; + } + } + + @Override + public boolean isUnWrapProxy() { + return associationAttribute.isUnWrapProxy(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "ToOneAttributeSourceImpl" ); + sb.append( "{associationAttribute=" ).append( associationAttribute ); + sb.append( ", cascadeStyles=" ).append( cascadeStyles ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return nature == Nature.ONE_TO_ONE && !associationAttribute.isOptional() ? + ForeignKeyDirection.FROM_PARENT : + ForeignKeyDirection.TO_PARENT; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationAttributeSource.java new file mode 100644 index 0000000000..e626d9a67b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationAttributeSource.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Map; + +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; + +/** + * @author Strong Liu + */ +public interface AnnotationAttributeSource { + void applyAttributeOverride(Map attributeOverrideMap); + + void applyAssociationOverride(Map associationOverrideMap); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContext.java new file mode 100644 index 0000000000..142c29369b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContext.java @@ -0,0 +1,74 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.source.BindingContext; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.IndexView; + +import com.fasterxml.classmate.MemberResolver; +import com.fasterxml.classmate.TypeResolver; + +/** + * Defines an interface for providing additional annotation related context information. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Strong Liu + */ +public interface AnnotationBindingContext extends BindingContext { + /** + * The annotation repository that this context know about. + * + * @return The {@link IndexView} that this context know about. + */ + IndexView getIndex(); + + /** + * Gets the class (or interface, or annotation) that was scanned during the + * indexing phase. + * + * @param className the name of the class + * @return information about the class or null if it is not known + */ + ClassInfo getClassInfo(String className); + + /** + * Gets the {@literal ClassMate} {@link TypeResolver} used in this context. + * + * @return The {@link TypeResolver} associated within this context. + */ + TypeResolver getTypeResolver(); + + /** + * Gets the {@literal ClassMate} {@link MemberResolver} used in this context. + * + * @return The {@link MemberResolver} associated within this context. + */ + MemberResolver getMemberResolver(); + + + IdentifierGeneratorDefinition findIdGenerator(String name); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContextImpl.java similarity index 61% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContextImpl.java index 20dd10da9b..d1ee74194d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationBindingContextImpl.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations; import java.util.HashMap; import java.util.Map; @@ -29,47 +29,45 @@ import java.util.Map; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.NamingStrategy; import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.source.MappingDefaults; import org.hibernate.service.ServiceRegistry; - import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; -import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import com.fasterxml.classmate.MemberResolver; -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; import com.fasterxml.classmate.TypeResolver; /** + * Default implementation of {@code AnnotationBindingContext} + * + * @author Hardy Ferentschik * @author Steve Ebersole */ public class AnnotationBindingContextImpl implements AnnotationBindingContext { + private static final TypeResolver TYPE_RESOLVER = new TypeResolver(); + private static final MemberResolver MEMBER_RESOLVER = new MemberResolver( TYPE_RESOLVER ); private final MetadataImplementor metadata; - private final ValueHolder classLoaderService; - private final Index index; - private final TypeResolver typeResolver = new TypeResolver(); - private final Map, ResolvedType> resolvedTypeCache = new HashMap, ResolvedType>(); + private final ClassLoaderService classLoaderService; + private final IndexView index; - public AnnotationBindingContextImpl(MetadataImplementor metadata, Index index) { + /** + * Constructor + * + * @param metadata {@code Metadata} instance + * @param index the Jandex index view + */ + public AnnotationBindingContextImpl(MetadataImplementor metadata, IndexView index) { this.metadata = metadata; - this.classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return AnnotationBindingContextImpl.this.metadata - .getServiceRegistry() - .getService( ClassLoaderService.class ); - } - } - ); + this.classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class ); this.index = index; } @Override - public Index getIndex() { + public IndexView getIndex() { return index; } @@ -80,31 +78,18 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext { } @Override - public void resolveAllTypes(String className) { - // the resolved type for the top level class in the hierarchy - Class clazz = classLoaderService.getValue().classForName( className ); - ResolvedType resolvedType = typeResolver.resolve( clazz ); - while ( resolvedType != null ) { - // todo - check whether there is already something in the map - resolvedTypeCache.put( clazz, resolvedType ); - resolvedType = resolvedType.getParentClass(); - if ( resolvedType != null ) { - clazz = resolvedType.getErasedType(); - } - } + public MemberResolver getMemberResolver() { + return MEMBER_RESOLVER; } @Override - public ResolvedType getResolvedType(Class clazz) { - // todo - error handling - return resolvedTypeCache.get( clazz ); + public TypeResolver getTypeResolver() { + return TYPE_RESOLVER; } @Override - public ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type) { - // todo : is there a reason we create this resolver every time? - MemberResolver memberResolver = new MemberResolver( typeResolver ); - return memberResolver.resolve( type, null, null ); + public IdentifierGeneratorDefinition findIdGenerator(String name) { + return getMetadataImplementor().getIdGenerator( name ); } @Override @@ -129,7 +114,7 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext { @Override public Class locateClassByName(String name) { - return classLoaderService.getValue().classForName( name ); + return classLoaderService.classForName( name ); } private Map nameToJavaTypeMap = new HashMap(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationMetadataSourceProcessorImpl.java new file mode 100644 index 0000000000..6aabbf358d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/AnnotationMetadataSourceProcessorImpl.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.source.annotations.global.FetchProfileProcessor; +import org.hibernate.metamodel.internal.source.annotations.global.IdGeneratorProcessor; +import org.hibernate.metamodel.internal.source.annotations.global.QueryProcessor; +import org.hibernate.metamodel.internal.source.annotations.global.SqlResultSetProcessor; +import org.hibernate.metamodel.internal.source.annotations.global.TableProcessor; +import org.hibernate.metamodel.internal.source.annotations.util.EntityHierarchyBuilder; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.IndexView; + +/** + * Main class responsible to creating and binding the Hibernate meta-model from annotations. + * This binder only has to deal with the (jandex) annotation index/repository. XML configuration is already processed + * and pseudo annotations are created. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProcessor { + + private final AnnotationBindingContext bindingContext; + + public AnnotationMetadataSourceProcessorImpl( + MetadataImpl metadata, + IndexView jandexView) { + + if ( !jandexView.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ).isEmpty() ) { + // todo : this needs to move to AnnotationBindingContext + // what happens right now is that specifying this in an orm.xml causes it to effect all orm.xmls + metadata.setGloballyQuotedIdentifiers( true ); + } + + this.bindingContext = new AnnotationBindingContextImpl( metadata, jandexView ); + } + + @Override + public Iterable extractTypeDefinitionSources() { + List typeDescriptorSources = new ArrayList(); + Collection annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + HibernateDotNames.TYPE_DEF, + HibernateDotNames.TYPE_DEFS, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance typeDef : annotations ) { + typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDef, bindingContext ) ); + } + return typeDescriptorSources; + } + + @Override + public Iterable extractFilterDefinitionSources() { + List filterDefinitionSources = new ArrayList(); + Collection annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + HibernateDotNames.FILTER_DEF, + HibernateDotNames.FILTER_DEFS, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance filterDef : annotations ) { + filterDefinitionSources.add( new FilterDefinitionSourceImpl( filterDef, bindingContext ) ); + } + return filterDefinitionSources; + } + + @Override + public Iterable extractGlobalIdentifierGeneratorSources() { + return IdGeneratorProcessor.extractGlobalIdentifierGeneratorSources( bindingContext ); + } + + @Override + public Iterable extractEntityHierarchies() { + // need to order our annotated entities into an order we can process + return EntityHierarchyBuilder.createEntityHierarchies( bindingContext ); + } + + @Override + public void processMappingDependentMetadata() { + TableProcessor.bind( bindingContext ); + FetchProfileProcessor.bind( bindingContext ); + SqlResultSetProcessor.bind( bindingContext ); + QueryProcessor.bind( bindingContext ); + + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..69cf1d5f0a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeElementSourceImpl.java @@ -0,0 +1,89 @@ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Hardy Ferentschik + */ +public class BasicPluralAttributeElementSourceImpl + extends AbstractPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource { + private final PluralAssociationAttribute associationAttribute; + private final ConfiguredClass entityClass; + private final Nature nature; + + + + public BasicPluralAttributeElementSourceImpl( + final PluralAssociationAttribute associationAttribute, + final ConfiguredClass entityClass, + final String relativePath) { + super(associationAttribute, relativePath); + this.associationAttribute = associationAttribute; + this.entityClass = entityClass; + this.nature = resolveNature( associationAttribute ); + } + + @Override + public HibernateTypeSource getExplicitHibernateTypeSource() { + return new HibernateTypeSourceImpl( associationAttribute ); + } + + @Override + public Nature getNature() { + return nature; + } + + private static Nature resolveNature(PluralAssociationAttribute attribute){ + switch ( attribute.getNature() ){ + case ELEMENT_COLLECTION_BASIC: + return Nature.BASIC; + case ELEMENT_COLLECTION_EMBEDDABLE: + return Nature.AGGREGATE; + default: + throw new AssertionError( + "Wrong attribute nature for a element collection attribute: " + attribute.getNature() + ); + + } + } + + @Override + public List relationalValueSources() { + List valueSources = new ArrayList(); + if(attributeOverride!=null){ + attributeOverride.apply( associationAttribute ); + } + if ( !associationAttribute.getColumnValues().isEmpty() ) { + for ( Column columnValues : associationAttribute.getColumnValues() ) { + valueSources.add( new ColumnSourceImpl( columnValues ) ); + } + } + return valueSources; + } + + // TODO - these values are also hard coded in the hbm version of this source implementation. Do we really need them? (HF) + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..0883944ec5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/BasicPluralAttributeIndexSourceImpl.java @@ -0,0 +1,101 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Collections; +import java.util.List; + +import org.jboss.jandex.AnnotationInstance; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Strong Liu + */ +public class BasicPluralAttributeIndexSourceImpl extends AbstractPluralAttributeIndexSourceImpl implements BasicPluralAttributeIndexSource { + private final IndexedPluralAttributeSourceImpl indexedPluralAttributeSource; + private final List relationalValueSources; + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + public BasicPluralAttributeIndexSourceImpl( + IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, + PluralAssociationAttribute attribute, + Binder.DefaultNamingStrategy defaultNamingStrategy) { + this( indexedPluralAttributeSource, attribute, defaultNamingStrategy, createRelationalValueSources( attribute ) ); + } + + public BasicPluralAttributeIndexSourceImpl( + IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, + PluralAssociationAttribute attribute, + Binder.DefaultNamingStrategy defaultNamingStrategy, + List relationalValueSources) { + super( attribute ); + this.indexedPluralAttributeSource = indexedPluralAttributeSource; + this.relationalValueSources = relationalValueSources; + this.defaultNamingStrategy = defaultNamingStrategy; + } + + private static List createRelationalValueSources(PluralAssociationAttribute attribute) { + AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + HibernateDotNames.INDEX_COLUMN + ); + if ( columnAnnotation == null ) { + columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + JPADotNames.ORDER_COLUMN + ); + } + if ( columnAnnotation == null ) { + columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + JPADotNames.MAP_KEY_COLUMN + ); + } + Column indexColumn = new Column( columnAnnotation ); + return Collections.singletonList( (RelationalValueSource) new ColumnSourceImpl( indexColumn ) ); + } + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return PluralAttributeIndexBinding.Nature.BASIC; + } + + @Override + public List getDefaultNamingStrategies() { + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ColumnSourceImpl.java new file mode 100644 index 0000000000..54a9b3df6f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ColumnSourceImpl.java @@ -0,0 +1,164 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * @author Hardy Ferentschik + */ +public class ColumnSourceImpl implements ColumnSource { + private final Column columnValues; + private final String defaultTableName; + private final String readFragement; + private final String writeFragement; + private final String checkCondition; + + public ColumnSourceImpl(Column columnValues) { + this( null, columnValues, null ); + } + + public ColumnSourceImpl(MappedAttribute attribute, Column columnValues) { + this( attribute, columnValues, null ); + } + + public ColumnSourceImpl(MappedAttribute attribute, Column columnValues, String defaultTableName) { + boolean isBasicAttribute = attribute != null && attribute.getNature() == MappedAttribute.Nature.BASIC; + this.readFragement = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomReadFragment() : null; + this.writeFragement = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomWriteFragment() : null; + this.checkCondition = attribute != null ? attribute.getCheckCondition() : null; + this.columnValues = columnValues; + this.defaultTableName = defaultTableName; + } + + @Override + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public String getName() { + return columnValues == null ? null : columnValues.getName(); + } + + @Override + public TruthValue isNullable() { + if ( columnValues == null || columnValues.isNullable() == null ) { + return null; + } + return columnValues.isNullable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public String getDefaultValue() { + return null; + } + + @Override + public String getSqlType() { + if ( columnValues == null ) { + return null; + } + return columnValues.getColumnDefinition(); + } + + @Override + public JdbcDataType getDatatype() { + return null; + } + + @Override + public SizeSource getSizeSource() { + if ( columnValues == null ) { + return null; + } + return new SizeSourceImpl( + columnValues.getPrecision(), columnValues.getScale(), columnValues.getLength() + ); + } + + @Override + public boolean isUnique() { + return columnValues != null && columnValues.isUnique() != null && columnValues.isUnique(); + } + + @Override + public String getComment() { + return null; + } + + @Override + public TruthValue isIncludedInInsert() { + if ( columnValues == null || columnValues.isInsertable() == null) { + return null; + } + return columnValues.isInsertable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public TruthValue isIncludedInUpdate() { + if ( columnValues == null || columnValues.isUpdatable() == null) { + return null; + } + return columnValues.isUpdatable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public String getContainingTableName() { + if ( columnValues == null ) { + return defaultTableName; + } + else if ( columnValues.getTable() == null ) { + return defaultTableName; + } + else { + return columnValues.getTable(); + } + } + + // these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public String getReadFragment() { + return readFragement; + } + + @Override + public String getWriteFragment() { + return writeFragement; + } + + @Override + public String getCheckCondition() { + return checkCondition; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ComponentAttributeSourceImpl.java new file mode 100644 index 0000000000..3e3c43e910 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ComponentAttributeSourceImpl.java @@ -0,0 +1,237 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.persistence.AccessType; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * Annotation backed implementation of {@code ComponentAttributeSource}. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class ComponentAttributeSourceImpl implements ComponentAttributeSource, AnnotationAttributeSource { + private final EmbeddableClass embeddableClass; + private final ValueHolder> classReference; + private final String path; + private final AccessType classAccessType; + private Map attributeOverrideMap; + private Map associationOverrideMap; + public ComponentAttributeSourceImpl( + final EmbeddableClass embeddableClass, + final String parentPath, + final AccessType classAccessType) { + this.embeddableClass = embeddableClass; + this.classReference = new ValueHolder>( embeddableClass.getConfiguredClass() ); + this.path = StringHelper.isEmpty( parentPath ) ? embeddableClass.getEmbeddedAttributeName() : parentPath + "." + embeddableClass.getEmbeddedAttributeName(); + this.classAccessType = classAccessType; + } + + @Override + public void applyAssociationOverride(Map associationOverrideMap) { + this.associationOverrideMap = associationOverrideMap; + } + + @Override + public void applyAttributeOverride(Map attributeOverrideMap) { + this.attributeOverrideMap = attributeOverrideMap; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public Nature getNature() { + return Nature.COMPOSITE; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public String getClassName() { + return embeddableClass.getConfiguredClass().getName(); + } + + @Override + public ValueHolder> getClassReference() { + return classReference; + } + + @Override + public String getName() { + return embeddableClass.getEmbeddedAttributeName(); + } + + @Override + public String getExplicitTuplizerClassName() { + return StringHelper.isEmpty( embeddableClass.getCustomTuplizerClass() ) ? embeddableClass.getCustomTuplizer() : embeddableClass + .getCustomTuplizerClass(); + } + + @Override + public String getPropertyAccessorName() { + return classAccessType.toString().toLowerCase(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return embeddableClass.getLocalBindingContext(); + } + +// private final ValueHolder> attributeSourcesValue = new ValueHolder>( +// new ValueHolder.DeferredInitializer>() { +// @Override +// public List initialize() { +// List attributeList = new ArrayList(); +// for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes().values() ) { +// attribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// attributeList.add( new SingularAttributeSourceImpl( attribute ) ); +// } +// for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) { +// embeddable.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// attributeList.add( +// new ComponentAttributeSourceImpl( +// embeddable, +// getPath(), +// classAccessType +// ) +// ); +// } +// for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes().values() ) { +// associationAttribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// } +// SourceHelper.resolveAssociationAttributes( embeddableClass, attributeList ); +// return Collections.unmodifiableList( attributeList ); +// } +// } +// ); + + @Override + public List attributeSources() { +// return attributeSourcesValue.getValue(); + return SourceHelper.resolveAttributes( embeddableClass, getPath(), attributeOverrideMap, associationOverrideMap ).getValue(); + } + + @Override + public String getPath() { + return path; + } + + @Override + public String getParentReferenceAttributeName() { + return embeddableClass.getParentReferencingAttributeName(); + } + + @Override + public Iterable getMetaAttributeSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public String getContainingTableName() { + // none, it is defined on the sub-attributes + return null; + } + + @Override + public List relationalValueSources() { + // none, they are defined on the sub-attributes + return null; + } + + @Override + public HibernateTypeSource getTypeInformation() { + // probably need to check for @Target in EmbeddableClass (HF) + return null; + } + + @Override + public PropertyGeneration getGeneration() { + return null; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return embeddableClass.getNaturalIdMutability(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return true; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "ComponentAttributeSourceImpl" ); + sb.append( "{embeddableClass=" ).append( embeddableClass.getConfiguredClass().getSimpleName() ); + sb.append( '}' ); + return sb.toString(); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..5bc48101f1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeElementSourceImpl.java @@ -0,0 +1,173 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass; +import org.hibernate.metamodel.spi.binding.CascadeType; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; + +/** + * @author Brett Meyer + */ +public class CompositePluralAttributeElementSourceImpl implements CompositePluralAttributeElementSource,AnnotationAttributeSource { + private final AssociationAttribute associationAttribute; + private final ConfiguredClass entityClass; + +// private final List attributeSources +// = new ArrayList(); +// + private final String parentReferenceAttributeName; + private final EmbeddableClass embeddableClass; + + private final String overridePath; + + private Map attributeOverrideMap; + private Map associationOverrideMap; + + public CompositePluralAttributeElementSourceImpl( + final PluralAssociationAttribute associationAttribute, + final ConfiguredClass rootEntityClass, + final String parentPath) { + this.associationAttribute = associationAttribute; + this.entityClass = rootEntityClass; + this.embeddableClass = entityClass + .getCollectionEmbeddedClasses() + .get( associationAttribute.getName() ); + + this.parentReferenceAttributeName = embeddableClass.getParentReferencingAttributeName(); + if ( associationAttribute.getPluralAttributeNature() == PluralAttributeSource.Nature.MAP ) { + this.overridePath = parentPath + ".value"; + } + else { + this.overridePath = parentPath + ".element"; + + } + } + + @Override + public void applyAssociationOverride(Map associationOverrideMap) { + this.associationOverrideMap = associationOverrideMap; + } + + @Override + public void applyAttributeOverride(Map attributeOverrideMap) { + this.attributeOverrideMap = attributeOverrideMap; + } + + @Override + public Nature getNature() { + return Nature.AGGREGATE; + } + + @Override + public String getPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List attributeSources() { + return SourceHelper.resolveAttributes( embeddableClass, overridePath, attributeOverrideMap, associationOverrideMap ).getValue(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return associationAttribute.getContext(); + } + + @Override + public Set getCascadeStyles() { + Set cascadeStyles = new HashSet(); + for ( javax.persistence.CascadeType cascadeType : associationAttribute + .getCascadeTypes() ) { + cascadeStyles.add( CascadeType.getCascadeType( cascadeType ) + .toCascadeStyle() ); + } + return cascadeStyles; + } + + @Override + public Iterable getMetaAttributeSources() { + // HBM only + return Collections.emptyList(); + } + + @Override + public String getClassName() { + return associationAttribute.getReferencedEntityType(); + } + + @Override + public ValueHolder> getClassReference() { + return getLocalBindingContext().makeClassReference( getClassName() ); + } + + @Override + public String getParentReferenceAttributeName() { + return parentReferenceAttributeName; + } + + @Override + public String getExplicitTuplizerClassName() { + // TODO ? + return null; + } + +// private void buildAttributeSources() { +// // TODO: Duplicates code in ComponentAttributeSourceImpl. +// for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes().values() ) { +// attribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// attributeSources.add( new SingularAttributeSourceImpl( attribute ) ); +// } +// for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) { +// embeddable.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// attributeSources.add( +// new ComponentAttributeSourceImpl( +// embeddable, +// getPath(), +// embeddableClass.getClassAccessType() +// ) +// ); +// } +// for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes().values() ) { +// associationAttribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() ); +// } +// SourceHelper.resolveAssociationAttributes( embeddableClass, attributeSources ); +// } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..dc1f2f531f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/CompositePluralAttributeIndexSourceImpl.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Gail Badner + */ +public class CompositePluralAttributeIndexSourceImpl extends AbstractPluralAttributeIndexSourceImpl implements CompositePluralAttributeIndexSource { + private final List relationalValueSources = new ArrayList( 1 ); + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + private final List attributeSources; + public CompositePluralAttributeIndexSourceImpl( + PluralAssociationAttribute attribute, + List attributeSources, + Binder.DefaultNamingStrategy defaultNamingStrategy) { + super( attribute ); + this.attributeSources = attributeSources; + this.defaultNamingStrategy = defaultNamingStrategy; + } + + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return PluralAttributeIndexBinding.Nature.AGGREGATE; + } + + @Override + public List getDefaultNamingStrategies() { + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public boolean isReferencedEntityAttribute() { + return false; + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getClassName() { + return pluralAssociationAttribute().getIndexType().getName(); + } + + public ValueHolder> getClassReference() { + return getLocalBindingContext().makeClassReference( getClassName() ); + } + + @Override + public String getPath() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List attributeSources() { + return attributeSources; + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return pluralAssociationAttribute().getContext(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DerivedValueSourceImpl.java similarity index 84% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DerivedValueSourceImpl.java index c53002db96..eb59ae7899 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DerivedValueSourceImpl.java @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ +package org.hibernate.metamodel.internal.source.annotations; -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.source.binder.DerivedValueSource; +import org.hibernate.metamodel.internal.source.annotations.attribute.FormulaValue; +import org.hibernate.metamodel.spi.source.DerivedValueSource; /** * @author Strong Liu @@ -36,7 +36,12 @@ public class DerivedValueSourceImpl implements DerivedValueSource { this.formulaValue = formulaValue; } - @Override + @Override + public Nature getNature() { + return Nature.DERIVED; + } + + @Override public String getExpression() { return formulaValue.getExpression(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DiscriminatorSourceImpl.java similarity index 68% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DiscriminatorSourceImpl.java index a2a3e50fe9..02dbdd7fab 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/DiscriminatorSourceImpl.java @@ -21,19 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; +package org.hibernate.metamodel.internal.source.annotations; -import org.hibernate.metamodel.source.annotations.entity.EntityClass; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; +import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass; +import org.hibernate.metamodel.spi.source.DiscriminatorSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Hardy Ferentschik */ public class DiscriminatorSourceImpl implements DiscriminatorSource { - private final EntityClass entityClass; + private final RootEntityClass entityClass; - public DiscriminatorSourceImpl(EntityClass entityClass) { + public DiscriminatorSourceImpl(RootEntityClass entityClass) { this.entityClass = entityClass; } @@ -47,12 +47,12 @@ public class DiscriminatorSourceImpl implements DiscriminatorSource { return entityClass.isDiscriminatorIncludedInSql(); } - @Override - public RelationalValueSource getDiscriminatorRelationalValueSource() { - return entityClass.getDiscriminatorFormula() != null ? - new DerivedValueSourceImpl( entityClass.getDiscriminatorFormula() ) - : new ColumnValuesSourceImpl( entityClass.getDiscriminatorColumnValues() ); - } + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + return entityClass.getDiscriminatorFormula() != null ? + new DerivedValueSourceImpl( entityClass.getDiscriminatorFormula() ) + : new ColumnSourceImpl( entityClass.getDiscriminatorColumnValues() ); + } @Override public String getExplicitHibernateTypeName() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntityHierarchyImpl.java similarity index 74% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntityHierarchyImpl.java index 2d970afbb6..adeef81c7f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntityHierarchyImpl.java @@ -21,11 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.RootEntitySource; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.RootEntitySource; /** * @author Hardy Ferentschik @@ -48,6 +48,16 @@ public class EntityHierarchyImpl implements EntityHierarchy { public RootEntitySource getRootEntitySource() { return rootEntitySource; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "EntityHierarchyImpl" ); + sb.append( "{rootEntitySource=" ).append( rootEntitySource.getEntityName() ); + sb.append( ", inheritanceType=" ).append( inheritanceType ); + sb.append( '}' ); + return sb.toString(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntitySourceImpl.java new file mode 100644 index 0000000000..3be5780818 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/EntitySourceImpl.java @@ -0,0 +1,579 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +import org.hibernate.AnnotationException; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.ConstraintSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.SecondaryTableSource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class EntitySourceImpl implements EntitySource { + private final EntityClass entityClass; + private final Set subclassEntitySources; + private final String jpaEntityName; + private final FilterSource[] filterSources; + private final TableSpecificationSource primaryTable; + private final EntityBindingContext bindingContext; + private final ClassLoaderService classLoaderService; + + public EntitySourceImpl(EntityClass entityClass) { + this.entityClass = entityClass; + this.subclassEntitySources = new HashSet(); + + if ( StringHelper.isNotEmpty( entityClass.getExplicitEntityName() ) ) { + this.jpaEntityName = entityClass.getExplicitEntityName(); + } + else { + this.jpaEntityName = StringHelper.unqualify( entityClass.getName() ); + } + + this.bindingContext = entityClass.getLocalBindingContext(); + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + + addImports(); + this.filterSources = buildFilterSources(); + this.primaryTable = resolvePrimaryTable(); + } + + private TableSpecificationSource resolvePrimaryTable() { + if ( !entityClass.definesItsOwnTable() ) { + return null; + } + + if ( entityClass.hostsAnnotation( HibernateDotNames.SUB_SELECT ) ) { + return new InLineViewSourceImpl( entityClass ); + } + else { + AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.TABLE + ); + return new TableSourceImpl( tableAnnotation, bindingContext ); + } + } + + private FilterSource[] buildFilterSources() { + AnnotationInstance filtersAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.FILTERS , + ClassInfo.class + ); + List filterSourceList = new ArrayList(); + if ( filtersAnnotation != null ) { + AnnotationInstance[] annotationInstances = filtersAnnotation.value().asNestedArray(); + for ( AnnotationInstance filterAnnotation : annotationInstances ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation, bindingContext ); + filterSourceList.add( filterSource ); + } + + } + AnnotationInstance filterAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.FILTER , + ClassInfo.class + ); + if ( filterAnnotation != null ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation, bindingContext ); + filterSourceList.add( filterSource ); + } + if ( filterSourceList.isEmpty() ) { + return null; + } + else { + return filterSourceList.toArray( new FilterSource[filterSourceList.size()] ); + } + } + + public EntityClass getEntityClass() { + return entityClass; + } + + @Override + public Origin getOrigin() { + return entityClass.getLocalBindingContext().getOrigin(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return entityClass.getLocalBindingContext(); + } + + @Override + public String getEntityName() { + return getClassName(); + } + + @Override + public String getClassName() { + return entityClass.getName(); + } + + @Override + public String getJpaEntityName() { + return jpaEntityName; + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public boolean isAbstract() { + return entityClass.isAbstract(); + } + + @Override + public boolean isLazy() { + return entityClass.isLazy(); + } + + @Override + public String getProxy() { + return entityClass.getProxy(); + } + + @Override + public int getBatchSize() { + return entityClass.getBatchSize(); + } + + @Override + public boolean isDynamicInsert() { + return entityClass.isDynamicInsert(); + } + + @Override + public boolean isDynamicUpdate() { + return entityClass.isDynamicUpdate(); + } + + @Override + public boolean isSelectBeforeUpdate() { + return entityClass.isSelectBeforeUpdate(); + } + + @Override + public String getCustomTuplizerClassName() { + return entityClass.getCustomTuplizer(); + } + + @Override + public String getCustomPersisterClassName() { + return entityClass.getCustomPersister(); + } + + @Override + public String getCustomLoaderName() { + return entityClass.getCustomLoaderQueryName(); + } + + @Override + public CustomSQL getCustomSqlInsert() { + return entityClass.getCustomInsert(); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return entityClass.getCustomUpdate(); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return entityClass.getCustomDelete(); + } + + @Override + public String[] getSynchronizedTableNames() { + return entityClass.getSynchronizedTableNames(); + } + + @Override + public Iterable getMetaAttributeSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public String getPath() { + return entityClass.getName(); + } + +// private final ValueHolder> attributeSource = new ValueHolder>( +// new ValueHolder.DeferredInitializer>() { +// @Override +// public List initialize() { +// List attributeList = new ArrayList(); +// for ( BasicAttribute attribute : getEntityClass().getSimpleAttributes().values() ) { +// AttributeSource source = new SingularAttributeSourceImpl( attribute ); +// attributeList.add( source ); +// } +// +// for ( Map.Entry entry : getEntityClass().getEmbeddedClasses().entrySet() ) { +// final String attributeName = entry.getKey(); +// if ( !getEntityClass().isIdAttribute( attributeName ) ) { +// final EmbeddableClass component = entry.getValue(); +// attributeList.add( +// new ComponentAttributeSourceImpl( +// component, +// "", +// getEntityClass().getClassAccessType() +// ) +// ); +// } +// } +// SourceHelper.resolveAssociationAttributes( getEntityClass(), attributeList ); +// return attributeList; +// } +// } +// ); + + @Override + public List attributeSources() { +// return attributeSource.getValue(); + return SourceHelper.resolveAttributes( getEntityClass(), "" ).getValue(); + } + + @Override + public void add(SubclassEntitySource subclassEntitySource) { + subclassEntitySources.add( subclassEntitySource ); + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public Iterable subclassEntitySources() { + return subclassEntitySources; + } + + @Override + public String getDiscriminatorMatchValue() { + return entityClass.getDiscriminatorMatchValue(); + } + + @Override + public Iterable getConstraints() { + Set constraintSources = new HashSet(); + + // primary table + if ( entityClass.hostsAnnotation( JPADotNames.TABLE ) ) { + AnnotationInstance table = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.TABLE + ); + addUniqueConstraints( constraintSources, table, null ); + addIndexConstraints( constraintSources, table, null ); + } + + // secondary table(s) + if ( entityClass.hostsAnnotation( JPADotNames.SECONDARY_TABLE ) ) { + AnnotationInstance secondaryTable = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.SECONDARY_TABLE + ); + String tableName = JandexHelper.getValue( secondaryTable, "name", String.class, classLoaderService ); + addUniqueConstraints( constraintSources, secondaryTable, tableName ); + addIndexConstraints( constraintSources, secondaryTable, tableName ); + + } + + if ( entityClass.hostsAnnotation( JPADotNames.SECONDARY_TABLES ) ) { + AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.SECONDARY_TABLES + ); + if ( secondaryTables != null ) { + for ( AnnotationInstance secondaryTable : JandexHelper.getValue( + secondaryTables, + "value", + AnnotationInstance[].class, + classLoaderService + ) ) { + String tableName = JandexHelper.getValue( secondaryTable, "name", String.class, classLoaderService ); + addUniqueConstraints( constraintSources, secondaryTable, tableName ); + addIndexConstraints( constraintSources, secondaryTable, tableName ); + } + } + } + + if ( entityClass.hostsAnnotation( JPADotNames.COLLECTION_TABLE ) ) { + List collectionTables = JandexHelper.getAnnotations( + entityClass.getClassInfo(), JPADotNames.COLLECTION_TABLE ); + for (AnnotationInstance collectionTable : collectionTables) { + String tableName = JandexHelper.getValue( collectionTable, "name", String.class, classLoaderService ); + addUniqueConstraints( constraintSources, collectionTable, tableName ); + addIndexConstraints( constraintSources, collectionTable, tableName ); + } + + } + + if ( entityClass.hostsAnnotation( JPADotNames.JOIN_TABLE ) ) { + List joinTables = JandexHelper.getAnnotations( + entityClass.getClassInfo(), JPADotNames.JOIN_TABLE ); + for (AnnotationInstance joinTable : joinTables) { + String tableName = JandexHelper.getValue( joinTable, "name", String.class, classLoaderService ); + addUniqueConstraints( constraintSources, joinTable, tableName ); + addIndexConstraints( constraintSources, joinTable, tableName ); + } + + } + + if ( entityClass.hostsAnnotation( JPADotNames.TABLE_GENERATOR ) ) { + List tableGenerators = JandexHelper.getAnnotations( + entityClass.getClassInfo(), JPADotNames.TABLE_GENERATOR ); + for (AnnotationInstance tableGenerator : tableGenerators) { + String tableName = JandexHelper.getValue( tableGenerator, "table", String.class, classLoaderService ); + addUniqueConstraints( constraintSources, tableGenerator, tableName ); + addIndexConstraints( constraintSources, tableGenerator, tableName ); + } + + } + + return constraintSources; + } + + @Override + public List getJpaCallbackClasses() { + return entityClass.getJpaCallbacks(); + } + + @Override + public Set getSecondaryTables() { + Set secondaryTableSources = new HashSet(); + + // process a singular @SecondaryTable annotation + if ( entityClass.hostsAnnotation( JPADotNames.SECONDARY_TABLE ) ) { + AnnotationInstance secondaryTable = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.SECONDARY_TABLE + ); + if ( secondaryTable != null ) { + secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) ); + } + } + + // process any @SecondaryTables grouping + if ( entityClass.hostsAnnotation( JPADotNames.SECONDARY_TABLES ) ) { + AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + JPADotNames.SECONDARY_TABLES + ); + if ( secondaryTables != null ) { + AnnotationInstance[] tableAnnotations = JandexHelper.getValue( + secondaryTables, + "value", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance secondaryTable : tableAnnotations ) { + secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) ); + } + } + } + + for(AssociationAttribute associationAttribute: entityClass.getAssociationAttributes().values()){ + if( ( associationAttribute.getNature() == MappedAttribute.Nature.MANY_TO_ONE || + associationAttribute.getNature() == MappedAttribute.Nature.ONE_TO_ONE ) ) { + AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation( + associationAttribute.annotations(), + JPADotNames.JOIN_TABLE + ); + if ( joinTableAnnotation != null ) { + secondaryTableSources.add( createSecondaryTableSource( joinTableAnnotation, false ) ); + } + } + } + + return secondaryTableSources; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "EntitySourceImpl" ); + sb.append( "{entityClass=" ).append( entityClass.getName() ); + + sb.append( ", subclassEntitySources={" ); + for ( SubclassEntitySource subClass : subclassEntitySources ) { + sb.append( subClass.getClassName() ).append( "," ); + } + sb.append( "}}" ); + return sb.toString(); + } + + private void addImports() { + try { + final MetadataImplementor metadataImplementor = entityClass.getLocalBindingContext() + .getMetadataImplementor(); + metadataImplementor.addImport( getJpaEntityName(), getEntityName() ); + if ( !getEntityName().equals( getJpaEntityName() ) ) { + metadataImplementor.addImport( getEntityName(), getEntityName() ); + } + } + catch ( MappingException e ) { + throw new AnnotationException( "Use of the same entity name twice: " + getJpaEntityName(), e ); + } + } + + private void addUniqueConstraints(Set constraintSources, AnnotationInstance tableAnnotation, String tableName) { + final AnnotationValue value = tableAnnotation.value( "uniqueConstraints" ); + if ( value == null ) { + return; + } + + final AnnotationInstance[] uniqueConstraints = value.asNestedArray(); + for ( final AnnotationInstance unique : uniqueConstraints ) { + final String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString(); + final String[] columnNames = unique.value( "columnNames" ).asStringArray(); + final UniqueConstraintSourceImpl uniqueConstraintSource = + new UniqueConstraintSourceImpl( + name, tableName, Arrays.asList( columnNames ) + ); + constraintSources.add( uniqueConstraintSource ); + } + } + + private void addIndexConstraints(Set constraintSources, AnnotationInstance tableAnnotation, String tableName) { + final AnnotationValue value = tableAnnotation.value( "indexes" ); + if ( value == null ) { + return; + } + + final AnnotationInstance[] indexConstraints = value.asNestedArray(); + for ( final AnnotationInstance index : indexConstraints ) { + final String name = index.value( "name" ) == null ? null : index.value( "name" ).asString(); + final String columnList = index.value( "columnList" ).asString(); + final boolean isUnique = index.value( "unique" ) == null ? false : index.value( "unique" ).asBoolean(); + + // Taken from JPAIndexHolder. + // TODO: Move elsewhere? + final StringTokenizer tokenizer = new StringTokenizer( columnList, "," ); + final List tmp = new ArrayList(); + while ( tokenizer.hasMoreElements() ) { + tmp.add( tokenizer.nextToken().trim() ); + } + final List columnNames = new ArrayList(); + final List orderings = new ArrayList(); + for ( String indexColumn : tmp ) { + indexColumn = indexColumn.toLowerCase(); + if ( indexColumn.endsWith( " desc" ) ) { + columnNames.add( indexColumn.substring( 0, indexColumn.length() - 5 ) ); + orderings.add( "desc" ); + } + else if ( indexColumn.endsWith( " asc" ) ) { + columnNames.add( indexColumn.substring( 0, indexColumn.length() - 4 ) ); + orderings.add( "asc" ); + } + else { + columnNames.add( indexColumn ); + orderings.add( null ); + } + } + + ConstraintSource constraintSource = null; + if ( isUnique ) { + constraintSource = new UniqueConstraintSourceImpl( name, tableName, columnNames, orderings ); + } else { + constraintSource = new IndexConstraintSourceImpl( name, tableName, columnNames, orderings ); + } + constraintSources.add( constraintSource ); + } + } + + private SecondaryTableSource createSecondaryTableSource( + AnnotationInstance tableAnnotation, + boolean isPrimaryKeyJoinColumn) { + final List keys = collectSecondaryTableKeys( tableAnnotation, isPrimaryKeyJoinColumn ); + return new SecondaryTableSourceImpl( new TableSourceImpl( tableAnnotation, bindingContext ), keys ); + } + + private List collectSecondaryTableKeys( + final AnnotationInstance tableAnnotation, + final boolean isPrimaryKeyJoinColumn) { + final AnnotationInstance[] joinColumnAnnotations = JandexHelper.getValue( + tableAnnotation, + isPrimaryKeyJoinColumn ? "pkJoinColumns" : "joinColumns", + AnnotationInstance[].class, + classLoaderService + ); + + if ( joinColumnAnnotations == null ) { + return Collections.emptyList(); + } + final List keys = new ArrayList(); + for ( final AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) { + final Column joinColumn; + if ( isPrimaryKeyJoinColumn ) { + joinColumn = new PrimaryKeyJoinColumn( joinColumnAnnotation ); + } + else { + joinColumn = new Column( joinColumnAnnotation ); + } + keys.add( joinColumn ); + } + return keys; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FetchProfileSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FetchProfileSourceImpl.java new file mode 100644 index 0000000000..8575ddd6a2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FetchProfileSourceImpl.java @@ -0,0 +1,104 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.FetchProfileSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class FetchProfileSourceImpl implements FetchProfileSource { + private final String name; + private final List associationOverrideSources; + private final ClassLoaderService classLoaderService; + + public FetchProfileSourceImpl(AnnotationInstance fetchProfileAnnotation, AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + this.name = JandexHelper.getValue( fetchProfileAnnotation, "name", String.class, classLoaderService ); + this.associationOverrideSources = buildAssociationOverrideSources( fetchProfileAnnotation ); + } + + @Override + public String getName() { + return name; + } + + @Override + public Iterable getAssociationOverrides() { + return associationOverrideSources; + } + + private List buildAssociationOverrideSources(AnnotationInstance fetchProfileAnnotation) { + final List associationOverrideSources = new ArrayList(); + AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( + fetchProfileAnnotation, + "fetchOverrides", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance overrideAnnotation : overrideAnnotations ) { + associationOverrideSources.add( new AssociationOverrideSourceImpl( overrideAnnotation ) ); + } + return associationOverrideSources; + } + + private class AssociationOverrideSourceImpl implements AssociationOverrideSource { + private final String entityName; + private final String attributeName; + private final String fetchMode; + + private AssociationOverrideSourceImpl(AnnotationInstance overrideAnnotation) { + this.entityName = JandexHelper.getValue( overrideAnnotation, "entity", String.class, classLoaderService ); + this.attributeName = JandexHelper.getValue( overrideAnnotation, "association", String.class, classLoaderService ); + FetchMode fetchMode = JandexHelper.getEnumValue( overrideAnnotation, "mode", FetchMode.class, classLoaderService ); + if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { + throw new MappingException( "Only FetchMode.JOIN is currently supported" ); + } + this.fetchMode = "join"; + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getAttributeName() { + return attributeName; + } + + @Override + public String getFetchModeName() { + return fetchMode; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterDefinitionSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterDefinitionSourceImpl.java new file mode 100644 index 0000000000..a3c0b1d357 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterDefinitionSourceImpl.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.FilterParameterSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class FilterDefinitionSourceImpl implements FilterDefinitionSource { + private final String name; + private final String condition; + private final ClassLoaderService classLoaderService; + private List parameterSources; + + public FilterDefinitionSourceImpl(AnnotationInstance filterDefAnnotation, AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + this.name = JandexHelper.getValue( filterDefAnnotation, "name", String.class, classLoaderService ); + this.condition = JandexHelper.getValue( filterDefAnnotation, "defaultCondition", String.class, classLoaderService ); + this.parameterSources = buildParameterSources( filterDefAnnotation ); + } + + private List buildParameterSources(AnnotationInstance filterDefAnnotation) { + final List parameterSources = new ArrayList(); + for ( AnnotationInstance paramAnnotation : JandexHelper.getValue( filterDefAnnotation, "parameters", + AnnotationInstance[].class, classLoaderService ) ) { + parameterSources.add( new FilterParameterSourceImpl( paramAnnotation ) ); + } + return parameterSources; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public Iterable getParameterSources() { + return parameterSources; + } + + private class FilterParameterSourceImpl implements FilterParameterSource { + private final String name; + private final String type; + + public FilterParameterSourceImpl(AnnotationInstance paramAnnotation) { + this.name = JandexHelper.getValue( paramAnnotation, "name", String.class, classLoaderService ); + this.type = JandexHelper.getValue( paramAnnotation, "type", String.class, classLoaderService ); + } + + @Override + public String getParameterName() { + return name; + } + + @Override + public String getParameterValueTypeName() { + return type; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterSourceImpl.java new file mode 100644 index 0000000000..ff6469e3f5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/FilterSourceImpl.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class FilterSourceImpl implements FilterSource { + private final String name; + private final String condition; + private final boolean autoAliasInjection; + private final Map aliasTableMap = new HashMap(); + private final Map aliasEntityMap = new HashMap(); + + public FilterSourceImpl(AnnotationInstance filterAnnotation, AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + + this.name = JandexHelper.getValue( filterAnnotation, "name", String.class, classLoaderService ); + this.condition = JandexHelper.getValue( filterAnnotation, "condition", String.class, classLoaderService ); + this.autoAliasInjection = JandexHelper.getValue( filterAnnotation, "deduceAliasInjectionPoints", Boolean.class, + classLoaderService ); + + for ( AnnotationInstance aliasAnnotation : JandexHelper.getValue( filterAnnotation, "aliases", + AnnotationInstance[].class, classLoaderService ) ) { + final String alias = JandexHelper.getValue( aliasAnnotation, "alias", String.class, classLoaderService ); + final String table = JandexHelper.getValue( aliasAnnotation, "table", String.class, classLoaderService ); + final String entity = JandexHelper.getValue( aliasAnnotation, "entity", String.class, classLoaderService ); + if ( StringHelper.isNotEmpty( table ) ) { + aliasTableMap.put( alias, table ); + } + else if ( StringHelper.isNotEmpty( entity ) ) { + aliasEntityMap.put( alias, entity ); + } + else { + // todo : throw a mapping exception + } + } + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public boolean shouldAutoInjectAliases() { + return autoAliasInjection; + } + + @Override + public Map getAliasToTableMap() { + return aliasTableMap; + } + + @Override + public Map getAliasToEntityMap() { + return aliasEntityMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/HibernateTypeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/HibernateTypeSourceImpl.java new file mode 100644 index 0000000000..c8a1264b4f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/HibernateTypeSourceImpl.java @@ -0,0 +1,77 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Map; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; + +/** + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class HibernateTypeSourceImpl implements HibernateTypeSource { + private final ValueHolder nameHolder; + private final ValueHolder> parameterHolder; + private final Class javaType; + + public HibernateTypeSourceImpl(final MappedAttribute attribute) { + this.nameHolder = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public String initialize() { + return attribute.getHibernateTypeResolver().getExplicitHibernateTypeName(); + } + } + ); + this.parameterHolder = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + return attribute.getHibernateTypeResolver().getExplicitHibernateTypeParameters(); + } + } + ); + this.javaType = attribute.getAttributeType(); + } + + @Override + public String getName() { + return nameHolder.getValue(); + } + + @Override + public Map getParameters() { + return parameterHolder.getValue(); + } + + @Override + public Class getJavaType() { + return javaType; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainer.java similarity index 63% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainer.java index 9c766e0735..99856133de 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainer.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,32 +21,22 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.internal.source.annotations; import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import org.jboss.jandex.AnnotationInstance; /** - * Describes the nature of the collection itself as declared by the metadata. + * Basically defines a source of identifier generator sources. Used to abstract where the identifier generator + * specifications come from so that we can share the process code. * * @author Steve Ebersole */ -public enum PluralAttributeNature { - BAG( Collection.class ), - ID_BAG( Collection.class ), - SET( Set.class ), - LIST( List.class ), - MAP( Map.class ); +public interface IdentifierGeneratorSourceContainer { + public Collection getSequenceGeneratorSources(); - private final Class reportedJavaType; + public Collection getTableGeneratorSources(); - PluralAttributeNature(Class reportedJavaType) { - this.reportedJavaType = reportedJavaType; - } - - public Class reportedJavaType() { - return reportedJavaType; - } + public Collection getGenericGeneratorSources(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainerImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainerImpl.java new file mode 100644 index 0000000000..e1d5687ab7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IdentifierGeneratorSourceContainerImpl.java @@ -0,0 +1,107 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class IdentifierGeneratorSourceContainerImpl implements IdentifierGeneratorSourceContainer { + + private final ClassLoaderService classLoaderService; + + public IdentifierGeneratorSourceContainerImpl(AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + } + + private Collection resolveOrEmpty(DotName name) { + Collection generatorSources = getAnnotations( name ); + return generatorSources == null ? Collections.emptyList() : generatorSources; + } + + private final ValueHolder> sequenceGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + return resolveOrEmpty( JPADotNames.SEQUENCE_GENERATOR ); + } + } + ); + + @Override + public Collection getSequenceGeneratorSources() { + return sequenceGeneratorSources.getValue(); + } + + private final ValueHolder> tableGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + return resolveOrEmpty( JPADotNames.TABLE_GENERATOR ); + } + } + ); + + @Override + public Collection getTableGeneratorSources() { + return tableGeneratorSources.getValue(); + } + + private final ValueHolder> genericGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + List annotations = new ArrayList(); + annotations.addAll( resolveOrEmpty( HibernateDotNames.GENERIC_GENERATOR ) ); + for ( AnnotationInstance generatorsAnnotation : resolveOrEmpty( HibernateDotNames.GENERIC_GENERATORS ) ) { + Collections.addAll( + annotations, + JandexHelper.getValue( generatorsAnnotation, "value", AnnotationInstance[].class, classLoaderService ) + ); + } + return annotations; + } + } + ); + + + @Override + public Collection getGenericGeneratorSources() { + return genericGeneratorSources.getValue(); + } + + protected abstract Collection getAnnotations(DotName name); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/InLineViewSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/InLineViewSourceImpl.java new file mode 100644 index 0000000000..7040837757 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/InLineViewSourceImpl.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.InLineViewSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class InLineViewSourceImpl implements InLineViewSource { + private final InlineViewInfo inlineViewInfo; + + public InLineViewSourceImpl(EntityClass entityClass) { + this.inlineViewInfo = createInlineViewInfo( entityClass ); + } + + @Override + public String getSelectStatement() { + return inlineViewInfo.getSelectStatement(); + } + + @Override + public String getExplicitSchemaName() { + return null; + } + + @Override + public String getExplicitCatalogName() { + return null; + } + + @Override + public String getLogicalName() { + return inlineViewInfo.getLogicalName(); + } + + private InlineViewInfo createInlineViewInfo(EntityClass entityClass) { + AnnotationInstance subselectAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.SUB_SELECT + ); + + return new InlineViewInfo( + JandexHelper.getValue( subselectAnnotation, "value", String.class, + entityClass.getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ), + entityClass.getEntityName() + ); + } + + private static class InlineViewInfo { + private final String selectStatement; + private final String logicalName; + + private InlineViewInfo(String selectStatement, String logicalName) { + this.selectStatement = selectStatement; + this.logicalName = logicalName; + } + + public String getSelectStatement() { + return selectStatement; + } + + public String getLogicalName() { + return logicalName; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + InlineViewInfo that = ( InlineViewInfo ) o; + + if ( logicalName != null ? !logicalName.equals( that.logicalName ) : that.logicalName != null ) { + return false; + } + if ( selectStatement != null ? !selectStatement.equals( that.selectStatement ) : that.selectStatement != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = selectStatement != null ? selectStatement.hashCode() : 0; + result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexConstraintSourceImpl.java new file mode 100644 index 0000000000..7c14fe2928 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexConstraintSourceImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.List; + +import org.hibernate.metamodel.spi.source.IndexConstraintSource; + +/** + * @author Brett Meyer + */ +class IndexConstraintSourceImpl extends AbstractConstraintSource implements IndexConstraintSource { + + public IndexConstraintSourceImpl(String name, String tableName, List columnNames, List orderings) { + super( name, tableName, columnNames, orderings ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "IndexConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexedPluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexedPluralAttributeSourceImpl.java new file mode 100644 index 0000000000..f6f8de2bde --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/IndexedPluralAttributeSourceImpl.java @@ -0,0 +1,226 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.EnumSet; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Strong Liu + */ +public class IndexedPluralAttributeSourceImpl extends PluralAttributeSourceImpl + implements IndexedPluralAttributeSource { + private PluralAttributeIndexSource indexSource; + private final static EnumSet VALID_NATURES = EnumSet.of( + MappedAttribute.Nature.MANY_TO_MANY, + MappedAttribute.Nature.ONE_TO_MANY, + MappedAttribute.Nature.ELEMENT_COLLECTION_BASIC, + MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE); + + public IndexedPluralAttributeSourceImpl( + final PluralAssociationAttribute attribute, + final ConfiguredClass entityClass, + final String relativePath) { + super( attribute, entityClass, relativePath ); + if ( !VALID_NATURES.contains( attribute.getNature() ) ) { + throw new MappingException( + "Indexed column could be only mapped on the MANY side", + attribute.getContext().getOrigin() + ); + } + + if ( attribute.getPluralAttributeNature() == PluralAttributeSource.Nature.ARRAY + && !attribute.annotations().containsKey( JPADotNames.ORDER_COLUMN ) + && !attribute.annotations().containsKey( HibernateDotNames.INDEX_COLUMN ) ) { + throw new AnnotationException( "The array attribute '" + attribute.getRole() + + "' must be annotated with @OrderColumn or @IndexColumn!" ); + } + + if ( attribute.isSequentiallyIndexed() ) { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( attribute.getName() ) + "_ORDER"; + } + }; + indexSource = new SequentialPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy ); + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY ) ) { + // need to wait until the ID or attribute source can be resolved. + indexSource = null; + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_CLASS ) ) { + // can be anything + throw new NotYetImplementedException( "@MapKeyClass is not supported yet." ); + } + //TODO the map attribute may contains both {@code MAP_KEY_COLUMN} and {@code MAP_KEY_CLASS} + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_COLUMN ) ) { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( attribute.getName() ) + "_KEY"; + } + }; + indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy ); + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_ENUMERATED ) ) { + // basic + throw new NotYetImplementedException( "@MapKeyEnumerated is not supported yet." ); + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_TEMPORAL ) ) { + // basic + throw new NotYetImplementedException( "@MapKeyTemporal is not supported yet." ); + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMN ) ) { + // association + throw new NotYetImplementedException( "@MapKeyJoinColumn is not supported yet." ); + } + else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMNS ) ) { + // association + throw new NotYetImplementedException( "@MapKeyJoinColumns is not supported yet." ); + } + else if ( String.class.equals( attribute.getIndexType() ) || attribute.getIndexType().isPrimitive() ) { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( attribute.getName() ) + "_KEY"; + } + }; + indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy ); + } + else { + // either @Embeddable or entity type. + + // composite: + // index is @Embeddable + // @MapKeyClass is not basic, not entity type + + // association: + // MapKeyJoinColumn, MapKeyJoinColumns are present + // If the primary key of the referenced entity is not a simple primary key, must have MapKeyJoinColumns. + //indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute ); + throw new NotYetImplementedException( "Embeddable and entity keys are not supported yet." ); + } + } + + @Override + public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext attributeSourceResolutionContext) { + if ( indexSource == null ) { + if ( pluralAssociationAttribute().annotations().containsKey( JPADotNames.MAP_KEY ) ) { + indexSource = resolveMapKeyPluralAttributeIndexSource( attributeSourceResolutionContext ); + } + else { + throw new NotYetImplementedException( "caonnot resolve index source." ); + } + } + return indexSource; + } + + private PluralAttributeIndexSource resolveMapKeyPluralAttributeIndexSource(AttributeSourceResolutionContext attributeSourceResolutionContext) { + final AnnotationInstance mapKeyAnnotation = + JandexHelper.getSingleAnnotation( pluralAssociationAttribute().annotations(), JPADotNames.MAP_KEY ); + final String attributeName = JandexHelper.getValue( mapKeyAnnotation, "name", String.class, + entityClass.getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + final PluralAttributeIndexSource innerIndexSource; + if ( attributeName == null ) { + IdentifierSource identifierSource = attributeSourceResolutionContext.resolveIdentifierSource( + pluralAssociationAttribute().getReferencedEntityType() + ); + switch ( identifierSource.getNature() ) { + case SIMPLE: + innerIndexSource = new BasicPluralAttributeIndexSourceImpl( + this, + pluralAssociationAttribute(), + null, + ( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource().relationalValueSources() ); + break; + default: + throw new NotYetImplementedException( "Only simple IDs are supported for @MapKey" ); + } + } + else { + AttributeSource attributeSource = attributeSourceResolutionContext.resolveAttributeSource( + pluralAssociationAttribute().getReferencedEntityType(), + attributeName + ); + if ( ! attributeSource.isSingular() ) { + throw new MappingException( + String.format( + "Plural attribute index [%s.%s] is not a singular attribute.", + pluralAssociationAttribute().getReferencedEntityType(), + attributeName + ), + pluralAssociationAttribute().getContext().getOrigin() + ); + } + final SingularAttributeSource mapKeyAttributeSource = (SingularAttributeSource) attributeSource; + switch ( mapKeyAttributeSource.getNature() ) { + case BASIC: + innerIndexSource = new BasicPluralAttributeIndexSourceImpl( + this, + pluralAssociationAttribute(), + null, + mapKeyAttributeSource.relationalValueSources() ); + break; + case COMPOSITE: + innerIndexSource = new CompositePluralAttributeIndexSourceImpl( + pluralAssociationAttribute(), + ( ( ComponentAttributeSource) attributeSource ).attributeSources(), + null + ); + break; + default: + throw new NotYetImplementedException( "Only basic plural attribute index sources are supported for @MapKey" ); + } + } + return new MapKeyPluralAttributeIndexSourceImpl( pluralAssociationAttribute(), innerIndexSource, attributeName ); + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java new file mode 100644 index 0000000000..032da436b1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.JoinedSubclassEntitySource; + +/** + * @author Strong Liu + */ +public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl implements JoinedSubclassEntitySource { + private final List columnSources; + private final JoinColumnResolutionDelegate fkColumnResolutionDelegate; + + public JoinedSubclassEntitySourceImpl(EntityClass entityClass, EntitySource container) { + super( entityClass, container ); + // todo : following normal annotation idiom for source, we probably want to move this stuff up to EntityClass... + columnSources = new ArrayList(); + final List targetColumnNames = new ArrayList(); + boolean hadNamedTargetColumnReferences = false; + if ( CollectionHelper.isNotEmpty( entityClass.getJoinedSubclassPrimaryKeyJoinColumnSources() ) ) { + for ( PrimaryKeyJoinColumn primaryKeyJoinColumnSource : entityClass.getJoinedSubclassPrimaryKeyJoinColumnSources() ) { + columnSources.add( + new ColumnSourceImpl( primaryKeyJoinColumnSource ) + ); + targetColumnNames.add( primaryKeyJoinColumnSource.getReferencedColumnName() ); + if ( primaryKeyJoinColumnSource.getReferencedColumnName() != null ) { + hadNamedTargetColumnReferences = true; + } + } + } + + this.fkColumnResolutionDelegate = !hadNamedTargetColumnReferences + ? null + : new JoinColumnResolutionDelegateImpl( targetColumnNames ); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return getEntityClass().getOnDeleteAction() != null && getEntityClass().getOnDeleteAction() == OnDeleteAction.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return getEntityClass().getExplicitForeignKeyName(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkColumnResolutionDelegate; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final List targetColumnNames; + + private JoinColumnResolutionDelegateImpl(List targetColumnNames) { + this.targetColumnNames = targetColumnNames; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List columns = new ArrayList(); + for ( String name : targetColumnNames ) { + // the nulls represent table, schema and catalog name which are ignored anyway... + columns.add( context.resolveColumn( name, null, null, null ) ); + } + return columns; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + } + + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JpaCallbackSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JpaCallbackSourceImpl.java new file mode 100644 index 0000000000..8cb0971e1d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JpaCallbackSourceImpl.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Map; + +import org.hibernate.metamodel.spi.source.JpaCallbackSource; + +/** + * @author Hardy Ferentschik + */ +public class JpaCallbackSourceImpl implements JpaCallbackSource { + + private final Map, String> callbacksByType; + private final String name; + private final boolean isListener; + + public JpaCallbackSourceImpl(String name, + Map, String> callbacksByType, + boolean isListener) { + this.name = name; + this.callbacksByType = callbacksByType; + this.isListener = isListener; + } + + @Override + public String getCallbackMethod(Class callbackType) { + return callbacksByType.get( callbackType ); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isListener() { + return isListener; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "JpaCallbackSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", isListener=" ).append( isListener ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToAnyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToAnyPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..9931d075c0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToAnyPluralAttributeElementSourceImpl.java @@ -0,0 +1,20 @@ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.metamodel.spi.source.ManyToAnyPluralAttributeElementSource; + +/** + * @author Hardy Ferentschik + */ +public class ManyToAnyPluralAttributeElementSourceImpl + extends AbstractPluralAssociationElementSourceImpl implements ManyToAnyPluralAttributeElementSource { + + public ManyToAnyPluralAttributeElementSourceImpl(PluralAttributeSourceImpl pluralAttributeSource, String relativePath) { + super( pluralAttributeSource, relativePath ); + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_ANY; + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyMappedByPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyMappedByPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..d3be718e2e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyMappedByPluralAttributeElementSourceImpl.java @@ -0,0 +1,57 @@ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Gail Badner + */ +public class ManyToManyMappedByPluralAttributeElementSourceImpl + extends AbstractManyToManyPluralAttributeElementSourceImpl implements MappedByAssociationSource { + + public ManyToManyMappedByPluralAttributeElementSourceImpl( + PluralAttributeSourceImpl pluralAttributeSource, + final String relativePath) { + super( pluralAttributeSource, relativePath ); + if ( pluralAssociationAttribute().getMappedBy() == null ) { + throw new AssertionFailure( "pluralAssociationAttribute().getMappedBy() must be non-null." ); + } + } + + @Override + public String getExplicitForeignKeyName() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesNullableByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return pluralAssociationAttribute().getMappedBy(); + } + + @Override + public List relationalValueSources() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..f4f34e2a0d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java @@ -0,0 +1,161 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + * @author Brett Meyer + * @author Gail Badner + */ +public class ManyToManyPluralAttributeElementSourceImpl + extends AbstractManyToManyPluralAttributeElementSourceImpl + implements ManyToManyPluralAttributeElementSource { + + private final List relationalValueSources + = new ArrayList(); + + private final EntityBindingContext bindingContext; + + public ManyToManyPluralAttributeElementSourceImpl( + PluralAttributeSourceImpl pluralAttributeSource, + String relativePath, + EntityBindingContext bindingContext) { + super( pluralAttributeSource, relativePath ); + if ( pluralAttributeSource.getMappedBy() != null ) { + throw new AssertionFailure( "pluralAttributeSource.getMappedBy() must be null." ); + } + for ( Column column : pluralAttributeSource.pluralAssociationAttribute().getInverseJoinColumnValues() ) { + relationalValueSources.add( new ColumnSourceImpl( column ) ); + } + this.bindingContext = bindingContext; + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + @Override + public String getExplicitForeignKeyName() { + return pluralAssociationAttribute().getInverseForeignKeyName(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + boolean hasReferencedColumn = false; + for ( Column joinColumn : pluralAssociationAttribute().getInverseJoinColumnValues() ) { + if ( joinColumn.getReferencedColumnName() != null ) { + hasReferencedColumn = true; + break; + } + } + return hasReferencedColumn ? + new AnnotationJoinColumnResolutionDelegate() : + null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + // TODO: This needs reworked. + public class AnnotationJoinColumnResolutionDelegate + implements ForeignKeyContributingSource.JoinColumnResolutionDelegate { + private final String logicalJoinTableName; + + public AnnotationJoinColumnResolutionDelegate() { + logicalJoinTableName = resolveLogicalJoinTableName(); + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + final List values = new ArrayList(); + for ( Column column : pluralAssociationAttribute().getInverseJoinColumnValues() ) { + org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn( + column.getReferencedColumnName(), + null, + null, + null + ); + values.add( resolvedColumn ); + } + return values; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + // HBM only + return null; + } + + private String resolveLogicalJoinTableName() { + final AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation( + pluralAssociationAttribute().annotations(), + JPADotNames.JOIN_TABLE + ); + + if ( joinTableAnnotation != null ) { + return JandexHelper.getValue( joinTableAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + // todo : this ties into the discussion about naming strategies. This would be part of a logical naming strategy... + return null; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MapKeyPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MapKeyPluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..5e69ef7a04 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MapKeyPluralAttributeIndexSourceImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.List; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.source.EntityAttributePluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Gail Badner + */ +public class MapKeyPluralAttributeIndexSourceImpl extends AbstractPluralAttributeIndexSourceImpl implements EntityAttributePluralAttributeIndexSource { + private final PluralAttributeIndexSource pluralAttributeIndexSource; + private final String attributeName; + + public MapKeyPluralAttributeIndexSourceImpl( + PluralAssociationAttribute attribute, + PluralAttributeIndexSource pluralAttributeIndexSource, + String attributeName) { + super( attribute ); + this.pluralAttributeIndexSource = pluralAttributeIndexSource; + this.attributeName = attributeName; + } + + @Override + public String getAttributeName() { + return attributeName; + } + + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return pluralAttributeIndexSource.getNature(); + } + + @Override + public List getDefaultNamingStrategies() { + return pluralAttributeIndexSource.getDefaultNamingStrategies(); + } + + @Override + public boolean isReferencedEntityAttribute() { + return true; + } + + @Override + public List relationalValueSources() { + return pluralAttributeIndexSource.relationalValueSources(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MutliTenancySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MutliTenancySourceImpl.java new file mode 100644 index 0000000000..8c06952cd8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/MutliTenancySourceImpl.java @@ -0,0 +1,107 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.FormulaValue; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.MultiTenancySource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class MutliTenancySourceImpl implements MultiTenancySource { + private final RelationalValueSource relationalValueSource; + private final boolean shared; + private final boolean bindAsParameter; + + public MutliTenancySourceImpl(EntityClass entityClass) { + final ClassLoaderService classLoaderService = entityClass.getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ); + + final AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.TENANT_COLUMN + ); + if ( columnAnnotation != null ) { + final Column column = new Column( null ); + column.setName( JandexHelper.getValue( columnAnnotation, "column", String.class, classLoaderService ) ); + column.setTable( null ); // primary table + column.setLength( JandexHelper.getValue( columnAnnotation, "length", int.class, classLoaderService ) ); + column.setPrecision( JandexHelper.getValue( columnAnnotation, "precision", int.class, classLoaderService ) ); + column.setScale( JandexHelper.getValue( columnAnnotation, "scale", int.class, classLoaderService ) ); + // todo : type + relationalValueSource = new ColumnSourceImpl( column ); + } + else { + final AnnotationInstance formulaAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.TENANT_FORMULA + ); + if ( formulaAnnotation != null ) { + relationalValueSource = new DerivedValueSourceImpl( + new FormulaValue( + null, // primary table + JandexHelper.getValue( formulaAnnotation, "value", String.class, classLoaderService ) + ) + ); + } + else { + relationalValueSource = null; + } + } + + final AnnotationInstance multiTenantAnnotation = JandexHelper.getSingleAnnotation( + entityClass.getClassInfo(), + HibernateDotNames.MULTI_TENANT + ); + if ( multiTenantAnnotation == null ) { + shared = true; + bindAsParameter = true; + } + else { + shared = JandexHelper.getValue( multiTenantAnnotation, "shared", Boolean.class, classLoaderService ); + bindAsParameter = JandexHelper.getValue( multiTenantAnnotation, "useParameterBinding", Boolean.class, classLoaderService ); + } + } + + @Override + public RelationalValueSource getRelationalValueSource() { + return relationalValueSource; + } + + @Override + public boolean isShared() { + return shared; + } + + @Override + public boolean bindAsParameter() { + return bindAsParameter; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyMappedByPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyMappedByPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..5171ea20ef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyMappedByPluralAttributeElementSourceImpl.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; + +/** + * @author Gail Badner + */ +public class OneToManyMappedByPluralAttributeElementSourceImpl + extends OneToManyPluralAttributeElementSourceImpl implements MappedByAssociationSource { + + public OneToManyMappedByPluralAttributeElementSourceImpl( + PluralAttributeSourceImpl pluralAttributeSource, + String relativePath) { + super( pluralAttributeSource, relativePath ); + if ( pluralAttributeSource.pluralAssociationAttribute().getMappedBy() == null ) { + throw new AssertionFailure( "pluralAssociationAttribute().getMappedBy() must be non-null." ); + } + } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return pluralAssociationAttribute().getMappedBy(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..e6c5d0097d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/OneToManyPluralAttributeElementSourceImpl.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource; + +/** + * @author Hardy Ferentschik + */ +public class OneToManyPluralAttributeElementSourceImpl + extends AbstractPluralAssociationElementSourceImpl implements OneToManyPluralAttributeElementSource { + + public OneToManyPluralAttributeElementSourceImpl( + PluralAttributeSourceImpl pluralAttributeSource, + String relativePath) { + super( pluralAttributeSource, relativePath ); + } + + @Override + public Nature getNature() { + return Nature.ONE_TO_MANY; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java new file mode 100644 index 0000000000..ac48b30f1a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java @@ -0,0 +1,134 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { + private final PluralAssociationAttribute attribute; + private final ForeignKey.ReferentialAction deleteAction; + + public PluralAttributeKeySourceImpl(PluralAssociationAttribute attribute) { + this.attribute = attribute; + this.deleteAction = attribute.getOnDeleteAction() == OnDeleteAction.CASCADE + ? ForeignKey.ReferentialAction.CASCADE : ForeignKey.ReferentialAction.NO_ACTION; + } + @Override + public ForeignKey.ReferentialAction getOnDeleteAction() { + return deleteAction; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String getExplicitForeignKeyName() { + return attribute.getExplicitForeignKeyName(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + if ( attribute.getMappedBy() != null ) { + throw new IllegalStateException( "Cannot determine foreign key information because association is not the owner." ); + } + for ( Column joinColumn : attribute.getJoinColumnValues() ) { + if ( StringHelper.isNotEmpty( joinColumn.getReferencedColumnName() ) ) { + return new JoinColumnResolutionDelegateImpl( attribute ); + } + } + return null; + } + + @Override + public List relationalValueSources() { + List joinClumnValues = attribute.getJoinColumnValues(); + if ( joinClumnValues.isEmpty() ) { + return Collections.emptyList(); + } + List result = new ArrayList( joinClumnValues.size() ); + for ( Column joinColumn : joinClumnValues ) { + result.add( new ColumnSourceImpl( joinColumn ) ); + } + return result; + } + + public static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final PluralAssociationAttribute attribute; + + public JoinColumnResolutionDelegateImpl(PluralAssociationAttribute attribute) { + this.attribute = attribute; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List joinColumnValues = attribute.getJoinColumnValues(); + if ( joinColumnValues.isEmpty() ) { + return null; + } + List result = new ArrayList( joinColumnValues.size() ); + for ( Column column : attribute.getJoinColumnValues() ) { + result.add( context.resolveColumn( column.getReferencedColumnName(), null, null, null ) ); + } + return result; + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( null ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeSourceImpl.java new file mode 100644 index 0000000000..c8f42b3a4a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeSourceImpl.java @@ -0,0 +1,421 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.source.AssociationSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.Orderable; +import org.hibernate.metamodel.spi.source.PluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.Sortable; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + */ +public class PluralAttributeSourceImpl implements AnnotationAttributeSource, PluralAttributeSource, Orderable, Sortable { + + private final PluralAssociationAttribute associationAttribute; + protected final ConfiguredClass entityClass; + private final Nature nature; + private final HibernateTypeSource typeSource; + private final PluralAttributeKeySource keySource; + private final FilterSource[] filterSources; + private final String attributePath; + + // If it is not the owner side (i.e., mappedBy != null), then the AttributeSource + // for the owner is required to determine elementSource. + private PluralAttributeElementSource elementSource; + private AttributeSource ownerAttributeSource; + public PluralAttributeSourceImpl( + final PluralAssociationAttribute associationAttribute, + final ConfiguredClass entityClass, + final String relativePath) { + this.associationAttribute = associationAttribute; + this.entityClass = entityClass; + this.keySource = new PluralAttributeKeySourceImpl( associationAttribute ); + this.typeSource = new HibernateTypeSourceImpl( associationAttribute ); + this.nature = associationAttribute.getPluralAttributeNature(); + this.attributePath = StringHelper.isEmpty( relativePath ) ? associationAttribute.getName() : relativePath + "." + associationAttribute.getName(); + + if ( associationAttribute.getMappedBy() == null ) { + this.ownerAttributeSource = this; + this.elementSource = determineElementSource( this, this, entityClass, attributePath ); + } + this.filterSources = determineFilterSources(associationAttribute); + } + + private FilterSource[] determineFilterSources(PluralAssociationAttribute associationAttribute) { + AnnotationInstance filtersAnnotation = JandexHelper.getSingleAnnotation( + associationAttribute.annotations(), + HibernateDotNames.FILTERS + ); + List filterSourceList = new ArrayList(); + if ( filtersAnnotation != null ) { + AnnotationInstance[] annotationInstances = filtersAnnotation.value().asNestedArray(); + for ( AnnotationInstance filterAnnotation : annotationInstances ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation, entityClass.getLocalBindingContext() ); + filterSourceList.add( filterSource ); + } + + } + AnnotationInstance filterAnnotation = JandexHelper.getSingleAnnotation( + associationAttribute.annotations(), + HibernateDotNames.FILTER + ); + if ( filterAnnotation != null ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation, entityClass.getLocalBindingContext() ); + filterSourceList.add( filterSource ); + } + if ( filterSourceList.isEmpty() ) { + return null; + } + else { + return filterSourceList.toArray( new FilterSource[filterSourceList.size()] ); + } + } + + @Override + public Nature getNature() { + return nature; + } + + @Override + public PluralAttributeElementSource getElementSource() { + if ( elementSource == null ) { + throw new IllegalStateException( "elementSource has not been initialized yet." ); + } + return elementSource; + } + + @Override + public void applyAssociationOverride(Map associationOverrideMap) { + if(elementSource != null && elementSource instanceof AnnotationAttributeSource){ + ((AnnotationAttributeSource)elementSource).applyAssociationOverride( associationOverrideMap ); + }else{ + //TODO what to do here, store this and apply later ( to the owner side )? + } + } + + @Override + public void applyAttributeOverride(Map attributeOverrideMap) { + if(elementSource != null && elementSource instanceof AnnotationAttributeSource){ + ((AnnotationAttributeSource)elementSource).applyAttributeOverride( attributeOverrideMap ); + } + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public int getBatchSize() { + return associationAttribute.getBatchSize(); + } + + @Override + public boolean usesJoinTable() { + if ( associationAttribute.getMappedBy() != null ) { + throw new IllegalStateException( "Cannot determine if a join table is used because plural attribute is not the owner." ); + } + // By default, a unidirectional one-to-many (i.e., with mappedBy == null) uses a join table, + // unless it has join columns defined. + return associationAttribute.getJoinTableAnnotation() != null || + ( associationAttribute.getJoinTableAnnotation() == null && + associationAttribute.getJoinColumnValues().size() == 0 ); + } + + @Override + public ValueHolder> getElementClassReference() { + // needed for arrays + Class attributeType = associationAttribute.getAttributeType(); + if ( attributeType.isArray() ) { + return new ValueHolder>( attributeType.getComponentType() ); + } + else { + return null; + } + } + + private static PluralAttributeElementSource determineElementSource( + AttributeSource ownerAttributeSource, + PluralAttributeSourceImpl pluralAttributeSource, + ConfiguredClass entityClass, + String relativePath) { + if ( ownerAttributeSource == null ) { + throw new AssertionFailure( "ownerAssociationSource must be non-null." ); + } + final PluralAssociationAttribute associationAttribute = pluralAttributeSource.pluralAssociationAttribute(); + switch ( pluralAttributeSource.pluralAssociationAttribute().getNature() ) { + case MANY_TO_MANY: + return associationAttribute.getMappedBy() == null ? + new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath, + entityClass.getLocalBindingContext() ) : + new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ); + case MANY_TO_ANY: + return new ManyToAnyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ); + case ONE_TO_MANY: + boolean usesJoinTable = ownerAttributeSource.isSingular() ? + ( (ToOneAttributeSource) ownerAttributeSource ).getContainingTableName() != null : + ( (PluralAttributeSource) ownerAttributeSource ).usesJoinTable(); + if ( usesJoinTable ) { + return associationAttribute.getMappedBy() == null ? + new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath, + entityClass.getLocalBindingContext() ) : + new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ); + } + else { + return associationAttribute.getMappedBy() == null ? + new OneToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ) : + new OneToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ); + } + case ELEMENT_COLLECTION_BASIC: + return new BasicPluralAttributeElementSourceImpl( associationAttribute, entityClass, relativePath ); + case ELEMENT_COLLECTION_EMBEDDABLE: { + // TODO: cascadeStyles? + return new CompositePluralAttributeElementSourceImpl( + associationAttribute, entityClass, relativePath + ); + } + } + throw new AssertionError( "Unexpected attribute nature for a association:" + associationAttribute.getNature() ); + } + + @Override + public PluralAttributeKeySource getKeySource() { + return keySource; + } + + @Override + public TableSpecificationSource getCollectionTableSpecificationSource() { + // todo - see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey + // todo - needs to cater for @CollectionTable and @JoinTable + if ( associationAttribute.getMappedBy() != null ) { + throw new IllegalStateException( "Cannot get collection table because this association is not the owner." ); + } + final AnnotationInstance joinTableAnnotation = associationAttribute.getJoinTableAnnotation(); + return joinTableAnnotation == null ? null : new TableSourceImpl( joinTableAnnotation, entityClass.getLocalBindingContext() ); + } + + @Override + public String getCollectionTableComment() { + return null; + } + + @Override + public String getCollectionTableCheck() { + return associationAttribute.getCheckCondition(); + } + + @Override + public Caching getCaching() { + return associationAttribute.getCaching(); + } + + @Override + public String getCustomPersisterClassName() { + return associationAttribute.getCustomPersister(); + } + + @Override + public String getWhere() { + return associationAttribute.getWhereClause(); + } + + @Override + public String getMappedBy() { + return associationAttribute.getMappedBy(); + } + + @Override + public boolean isInverse() { + return getMappedBy() != null; + } + + @Override + public String getCustomLoaderName() { + return associationAttribute.getCustomLoaderName(); + } + + @Override + public CustomSQL getCustomSqlInsert() { + return associationAttribute.getCustomInsert(); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return associationAttribute.getCustomUpdate(); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return associationAttribute.getCustomDelete(); + } + + @Override + public CustomSQL getCustomSqlDeleteAll() { + return associationAttribute.getCustomDeleteAll(); + } + + @Override + public String getName() { + return associationAttribute.getName(); + } + + @Override + public boolean isSingular() { + return false; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return associationAttribute.getAccessType(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return associationAttribute.isOptimisticLockable(); + } + + @Override + public Iterable getMetaAttributeSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public String getOrder() { + return elementSource.getNature() == PluralAttributeElementSource.Nature.MANY_TO_MANY ? + null : + associationAttribute.getOrderBy(); + } + + @Override + public boolean isMutable() { + return associationAttribute.isMutable(); + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getComparatorName() { + return associationAttribute.getComparatorName(); + } + + @Override + public boolean isSorted() { + return associationAttribute.isSorted(); + } + + @Override + public FetchTiming getFetchTiming() { + if ( associationAttribute.isExtraLazy() ) { + return FetchTiming.EXTRA_LAZY; + } + else if ( associationAttribute.isLazy() ) { + return FetchTiming.DELAYED; + } + else { + return FetchTiming.IMMEDIATE; + } + } + + @Override + public FetchStyle getFetchStyle() { + return associationAttribute.getFetchStyle(); + } + + @Override + public PluralAttributeElementSource resolvePluralAttributeElementSource( + AttributeSourceResolutionContext context) { + if ( elementSource == null ) { + // elementSource has not been initialized, so we need to resolve it using the + // association owner. + // Get the owner attribute source that maps the opposite side of the association. + ownerAttributeSource = context.resolveAttributeSource( + associationAttribute.getReferencedEntityType(), + associationAttribute.getMappedBy() + ); + // Initialize resolved entitySource. + elementSource = determineElementSource( ownerAttributeSource, this, entityClass, "" ); //TODO not sure what relativePath should be here + if ( !MappedByAssociationSource.class.isInstance( elementSource ) ) { + throw new AssertionFailure( "expected a mappedBy association." ); + } + final AssociationSource ownerAssociationSource; + if ( ownerAttributeSource.isSingular() ) { + ownerAssociationSource = (ToOneAttributeSource) ownerAttributeSource; + } + else { + final PluralAttributeSource pluralAttributeSource = (PluralAttributeSource) ownerAttributeSource; + if ( !AssociationSource.class.isInstance( pluralAttributeSource.getElementSource() ) ) { + throw new AssertionFailure( "Owner is not an association." ); + } + ownerAssociationSource = (AssociationSource) pluralAttributeSource.getElementSource(); + } + ownerAssociationSource.addMappedByAssociationSource( (MappedByAssociationSource) elementSource ); + } + return elementSource; + } + + protected PluralAssociationAttribute pluralAssociationAttribute() { + return associationAttribute; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/RootEntitySourceImpl.java new file mode 100644 index 0000000000..303e98e4c0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/RootEntitySourceImpl.java @@ -0,0 +1,313 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.entity.IdType; +import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.DiscriminatorSource; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.MultiTenancySource; +import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntitySource { + private final RootEntityClass rootEntityClass; + + public RootEntitySourceImpl(RootEntityClass entityClass) { + super( entityClass ); + this.rootEntityClass = entityClass; + } + + @Override + public IdentifierSource getIdentifierSource() { + IdType idType = rootEntityClass.getIdType(); + switch ( idType ) { + case SIMPLE: { + MappedAttribute attribute = getEntityClass().getIdAttributes().values().iterator().next(); + return new SimpleIdentifierSourceImpl(rootEntityClass, (BasicAttribute) attribute); + } + case COMPOSED: { + return new NonAggregatedCompositeIdentifierSourceImpl( this ); + } + case EMBEDDED: { + return new AggregatedCompositeIdentifierSourceImpl( this ); + } + default: { + throw new AssertionFailure( + String.format( "Entity [%s] did not define an identifier", getEntityName() ) + ); + } + } + } + + @Override + public VersionAttributeSource getVersioningAttributeSource() { + final EntityClass entityClass = getEntityClass(); + if ( entityClass.getVersionAttribute() == null ) { + return null; + } + return new VersionAttributeSourceImpl( entityClass.getVersionAttribute() ); + } + + @Override + public DiscriminatorSource getDiscriminatorSource() { + DiscriminatorSource discriminatorSource = null; + if ( rootEntityClass.needsDiscriminatorColumn() ) { + discriminatorSource = new DiscriminatorSourceImpl( rootEntityClass ); + } + return discriminatorSource; + } + + @Override + public MultiTenancySource getMultiTenancySource() { + return getEntityClass().hasMultiTenancySourceInformation() + ? new MutliTenancySourceImpl( getEntityClass() ) + : null; + } + + @Override + public EntityMode getEntityMode() { + return EntityMode.POJO; + } + + @Override + public boolean isMutable() { + return getEntityClass().isMutable(); + } + + @Override + public boolean isExplicitPolymorphism() { + return getEntityClass().isExplicitPolymorphism(); + } + + @Override + public String getWhere() { + return getEntityClass().getWhereClause(); + } + + @Override + public String getRowId() { + return getEntityClass().getRowId(); + } + + @Override + public OptimisticLockStyle getOptimisticLockStyle() { + return getEntityClass().getOptimisticLockStyle(); + } + + @Override + public Caching getCaching() { + return getEntityClass().getCaching(); + } + + @Override + public Caching getNaturalIdCaching() { + return getEntityClass().getNaturalIdCaching(); + } + + private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource { + private final ComponentAttributeSourceImpl componentAttributeSource; + + public AggregatedCompositeIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource) { + // the entity class reference should contain one single id attribute... + Iterator idAttributes = rootEntitySource.getEntityClass().getIdAttributes().values().iterator(); + noIdentifierCheck( rootEntitySource, idAttributes ); + final MappedAttribute idAttribute = idAttributes.next(); + if ( idAttributes.hasNext() ) { + throw rootEntitySource.getLocalBindingContext().makeMappingException( + String.format( + "Encountered multiple identifier attributes on entity %s", + rootEntitySource.getEntityName() + ) + ); + } + + final EmbeddableClass embeddableClass = rootEntitySource.getEntityClass().getEmbeddedClasses().get( + idAttribute.getName() + ); + if ( embeddableClass == null ) { + throw rootEntitySource.getLocalBindingContext().makeMappingException( + "Could not locate embedded identifier class metadata" + ); + } + + componentAttributeSource = new ComponentAttributeSourceImpl( embeddableClass, "", embeddableClass.getClassAccessType() ); + } + + private void noIdentifierCheck(RootEntitySourceImpl rootEntitySource, Iterator idAttributes) { + if ( !idAttributes.hasNext() ) { + throw rootEntitySource.getLocalBindingContext().makeMappingException( + String.format( + "Could not locate identifier attributes on entity %s", + rootEntitySource.getEntityName() + ) + ); + } + } + + @Override + public ComponentAttributeSource getIdentifierAttributeSource() { + return componentAttributeSource; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + // annotations do not currently allow generators to be attached to composite identifiers as a whole + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public Iterable getMetaAttributeSources() { + // not relevant for annotations + return Collections.emptySet(); + } + } + + private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource { + private final RootEntitySourceImpl rootEntitySource; + + public NonAggregatedCompositeIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource) { + this.rootEntitySource = rootEntitySource; + } + + @Override + public Class getLookupIdClass() { + final AnnotationInstance idClassAnnotation = ( + ( RootEntityClass ) rootEntitySource.getEntityClass() ) + .getIdClassAnnotation(); + + if ( idClassAnnotation == null ) { + return null; + } + + return rootEntitySource.getLocalBindingContext().locateClassByName( + JandexHelper.getValue( idClassAnnotation, "value", String.class, + rootEntityClass.getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + + @Override + public String getIdClassPropertyAccessorName() { + // TODO: Should we retrieve property accessor name for the ID Class? + return rootEntitySource.getEntityClass().getClassAccessType().name() + .toLowerCase(); + } + + @Override + public List getAttributeSourcesMakingUpIdentifier() { + List attributeSources = new ArrayList(); + for ( MappedAttribute attr : rootEntitySource.getEntityClass().getIdAttributes().values() ) { + switch ( attr.getNature() ) { + case BASIC: + attributeSources.add( new SingularAttributeSourceImpl( attr ) ); + break; + case MANY_TO_ONE: + case ONE_TO_ONE: + final SingularAssociationAttribute associationAttribute = (SingularAssociationAttribute) attr; + final SingularAttributeSource attributeSource = + associationAttribute.getMappedBy() == null ? + new ToOneAttributeSourceImpl( associationAttribute, "", + rootEntityClass.getLocalBindingContext() ) : + new ToOneMappedByAttributeSourceImpl( associationAttribute, "" ); + attributeSources.add( attributeSource ); + } + } + return attributeSources; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + // annotations do not currently allow generators to be attached to composite identifiers as a whole + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public Iterable getMetaAttributeSources() { + // not relevant for annotations + return Collections.emptySet(); + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java new file mode 100644 index 0000000000..f7e7da84d2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java @@ -0,0 +1,161 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.SecondaryTableSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; + +/** + * @author Steve Ebersole + */ +public class SecondaryTableSourceImpl implements SecondaryTableSource { + private final TableSpecificationSource joinTable; + private final List columnSources; + private final JoinColumnResolutionDelegate fkColumnResolutionDelegate; + + public SecondaryTableSourceImpl( + TableSpecificationSource joinTable, + List joinColumns) { + this.joinTable = joinTable; + + // todo : following normal annotation idiom for source, we probably want to move this stuff up to EntityClass... + columnSources = new ArrayList(); + final List targetColumnNames = new ArrayList(); + boolean hadNamedTargetColumnReferences = false; + for ( Column joinColumn : joinColumns ) { + columnSources.add( + new ColumnSourceImpl( + joinColumn + ) + ); + targetColumnNames.add( joinColumn.getReferencedColumnName() ); + if ( joinColumn.getReferencedColumnName() != null ) { + hadNamedTargetColumnReferences = true; + } + } + + this.fkColumnResolutionDelegate = ! hadNamedTargetColumnReferences + ? null + : new JoinColumnResolutionDelegateImpl( targetColumnNames ); + } + + @Override + public TableSpecificationSource getTableSource() { + return joinTable; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + @Override + public String getComment() { + return null; + } + + @Override + public FetchStyle getFetchStyle() { + return null; + } + + @Override + public boolean isInverse() { + return false; + } + + @Override + public boolean isOptional() { + return true; + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public CustomSQL getCustomSqlDelete() { + return null; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return null; + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return null; + } + + @Override + public String getExplicitForeignKeyName() { + // not supported from annotations, unless docs for @ForeignKey are wrong... + return null; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkColumnResolutionDelegate; + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final List targetColumnNames; + + private JoinColumnResolutionDelegateImpl(List targetColumnNames) { + this.targetColumnNames = targetColumnNames; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List columns = new ArrayList(); + for ( String name : targetColumnNames ) { + // the nulls represent table, schema and catalog name which are ignored anyway... + columns.add( context.resolveColumn( name, null, null, null ) ); + } + return columns; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SequentialPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SequentialPluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..66c51f27fe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SequentialPluralAttributeIndexSourceImpl.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.Collections; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.SequentialPluralAttributeIndexSource; + +/** + * @author Gail Badner + */ +public class SequentialPluralAttributeIndexSourceImpl + extends BasicPluralAttributeIndexSourceImpl + implements SequentialPluralAttributeIndexSource { + private final int base; + + private final static HibernateTypeSource INTERGER_TYPE = new HibernateTypeSource() { + @Override + public String getName() { + return "integer"; + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + @Override + public Class getJavaType() { + return null; + } + }; + + public SequentialPluralAttributeIndexSourceImpl( + IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, + PluralAssociationAttribute attribute, + Binder.DefaultNamingStrategy defaultNamingStrategy) { + super( indexedPluralAttributeSource, attribute, defaultNamingStrategy ); + AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + HibernateDotNames.INDEX_COLUMN + ); + if ( columnAnnotation == null ) { + columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + JPADotNames.ORDER_COLUMN + ); + } + this.base = columnAnnotation.value( "base" ) != null ? columnAnnotation.value( "base" ) + .asInt() : 0; + } + + @Override + public int base() { + return base; + } + @Override + public HibernateTypeSource getTypeInformation() { + return INTERGER_TYPE; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SimpleIdentifierSourceImpl.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SimpleIdentifierSourceImpl.java index e6ae635ea9..60ad0db4f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SimpleIdentifierSourceImpl.java @@ -21,23 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; +package org.hibernate.metamodel.internal.source.annotations; -import java.util.Map; +import java.util.Collections; import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; /** * @author Hardy Ferentschik */ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { private final BasicAttribute attribute; - private final Map attributeOverrideMap; - - public SimpleIdentifierSourceImpl(BasicAttribute attribute, Map attributeOverrideMap) { + private final RootEntityClass rootEntityClass; + private final SingularAttributeSourceImpl source ; + public SimpleIdentifierSourceImpl(RootEntityClass rootEntityClass, BasicAttribute attribute) { if ( !attribute.isId() ) { throw new AssertionFailure( String.format( @@ -46,23 +50,36 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { ) ); } + this.rootEntityClass = rootEntityClass; this.attribute = attribute; - this.attributeOverrideMap = attributeOverrideMap; + this.source= new SingularAttributeSourceImpl( attribute ); + source.applyAttributeOverride( rootEntityClass.getAttributeOverrideMap() ); } @Override - public Nature getNature() { - return Nature.SIMPLE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; } @Override public SingularAttributeSource getIdentifierAttributeSource() { - return new SingularAttributeSourceImpl( attribute ); + + return source; } @Override - public IdGenerator getIdentifierGeneratorDescriptor() { - return attribute.getIdGenerator(); + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + return attribute.getIdentifierGeneratorDefinition(); + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public Iterable getMetaAttributeSources() { + return Collections.emptySet(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SingularAttributeSourceImpl.java new file mode 100644 index 0000000000..85e1bd4e66 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SingularAttributeSourceImpl.java @@ -0,0 +1,190 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; + +/** + * @author Hardy Ferentschik + */ +public class SingularAttributeSourceImpl implements SingularAttributeSource, AnnotationAttributeSource { + private final MappedAttribute attribute; + private final HibernateTypeSource type; + private final String attributePath; + + protected AttributeOverride attributeOverride; + + public SingularAttributeSourceImpl(MappedAttribute attribute) { + this(attribute, ""); + } + + public SingularAttributeSourceImpl(MappedAttribute attribute, String parentPath) { + this.attribute = attribute; + this.type = new HibernateTypeSourceImpl( attribute ); + this.attributePath = StringHelper.isEmpty( parentPath ) ? attribute.getName() : parentPath + "." + attribute.getName(); + } + + @Override + public void applyAssociationOverride(Map associationOverrideMap) { + //doing nothing here + } + + @Override + public void applyAttributeOverride(Map attributeOverrideMap) { + this.attributeOverride = attributeOverrideMap.get( attributePath ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return type; + } + + @Override + public String getPropertyAccessorName() { + return attribute.getAccessType(); + } + + @Override + public PropertyGeneration getGeneration() { + return attribute.getPropertyGeneration(); + } + + @Override + public boolean isLazy() { + return attribute.isLazy(); + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return attribute.getNaturalIdMutability(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return attribute.isOptimisticLockable(); + } + + @Override + public String getName() { + return attribute.getName(); + } + + @Override + public String getContainingTableName() { + return null; + } + + private final ValueHolder> relationalValueSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public List initialize() { + List valueSources = new ArrayList(); + if ( attributeOverride != null ) { + attributeOverride.apply( attribute ); + } + boolean hasDefinedColumnSource = !attribute.getColumnValues().isEmpty(); + if ( hasDefinedColumnSource ) { + for ( Column columnValues : attribute.getColumnValues() ) { + + valueSources.add( new ColumnSourceImpl( attribute, columnValues ) ); + } + } + else if ( attribute.getFormulaValue() != null ) { + valueSources.add( new DerivedValueSourceImpl( attribute.getFormulaValue() ) ); + } + else if ( attribute instanceof BasicAttribute ) { + //for column transformer + BasicAttribute basicAttribute = BasicAttribute.class.cast( attribute ); + if ( basicAttribute.getCustomReadFragment() != null && basicAttribute.getCustomWriteFragment() != null ) { + + valueSources.add( new ColumnSourceImpl( attribute, null ) ); + } + } + return valueSources; + } + } + ); + + /** + * very ugly, can we just return the columnSourceImpl anyway? + */ + @Override + public List relationalValueSources() { + return relationalValueSources.getValue(); + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Nature getNature() { + return Nature.BASIC; + } + + @Override + public Iterable getMetaAttributeSources() { + return Collections.emptySet(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return attribute.isInsertable(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return !attribute.isId() && attribute.isUpdatable(); + } + + @Override + public boolean areValuesNullableByDefault() { + return !attribute.isId() && attribute.isOptional(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SizeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SizeSourceImpl.java new file mode 100644 index 0000000000..8e5c67494f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SizeSourceImpl.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * @author Gail Badner + */ +public class SizeSourceImpl implements SizeSource { + + private final int length; + private final int precision; + private final int scale; + + public SizeSourceImpl(int precision, int scale, int length) { + this.precision = precision; + this.scale = scale; + this.length = length; + } + + public boolean isLengthDefined() { + return true; + } + + public int getLength() { + return length; + } + + public boolean isPrecisionDefined() { + return true; + } + + public int getPrecision() { + return precision; + } + + public boolean isScaleDefined() { + return true; + } + + public int getScale() { + return scale; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SourceHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SourceHelper.java new file mode 100644 index 0000000000..5f2f0ee4ac --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SourceHelper.java @@ -0,0 +1,177 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; + +/** + * @author Strong Liu + */ +public class SourceHelper { + + public static ValueHolder> resolveAttributes( + final ConfiguredClass configuredClass, + final String relativePath, + final Map attributeOverrideMap, + final Map associationAttributeMap){ + return new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public List initialize() { + List attributeList = new ArrayList(); + for ( BasicAttribute attribute : configuredClass.getSimpleAttributes().values() ) { + SingularAttributeSourceImpl source = new SingularAttributeSourceImpl( attribute, relativePath ); + attributeList.add( source ); + } + + for ( Map.Entry entry : configuredClass.getEmbeddedClasses() + .entrySet() ) { + final String attributeName = entry.getKey(); + if ( !configuredClass.isIdAttribute( attributeName ) ) { + final EmbeddableClass component = entry.getValue(); + ComponentAttributeSourceImpl source = new ComponentAttributeSourceImpl( + component, + relativePath, + configuredClass.getClassAccessType() + ); + attributeList.add( source ); + } + } + resolveAssociationAttributes( configuredClass, attributeList, relativePath ); + for ( AttributeSource attributeSource : attributeList ) { + if ( attributeSource instanceof AnnotationAttributeSource ) { + AnnotationAttributeSource source = (AnnotationAttributeSource) attributeSource; + source.applyAssociationOverride( + associationAttributeMap != null ? associationAttributeMap : Collections + .emptyMap() + ); + source.applyAttributeOverride( + attributeOverrideMap != null ? attributeOverrideMap : Collections.emptyMap() + ); + } + } + return attributeList; + } + } + ); + } + + public static ValueHolder> resolveAttributes(final ConfiguredClass configuredClass, final String relativePath){ + return resolveAttributes( configuredClass, relativePath, configuredClass.getAttributeOverrideMap(), configuredClass.getAssociationOverrideMap() ); + + } + + /** + * Bind association attributes within {@param configuredClass} to the proper source impl based on its nature. + * + * @param configuredClass The holder of association attributes. + * @param attributeList Attribute source container, can't be null. + */ + private static void resolveAssociationAttributes(ConfiguredClass configuredClass, List attributeList, final String relativePath) { + for ( AssociationAttribute associationAttribute : configuredClass.getAssociationAttributes().values() ) { + switch ( associationAttribute.getNature() ) { + case ONE_TO_ONE: + case MANY_TO_ONE: { + final SingularAssociationAttribute singularAssociationAttribute = + (SingularAssociationAttribute) associationAttribute; + final SingularAttributeSource source = + associationAttribute.getMappedBy() == null ? + new ToOneAttributeSourceImpl( singularAssociationAttribute, relativePath, + configuredClass.getLocalBindingContext() ) : + new ToOneMappedByAttributeSourceImpl( singularAssociationAttribute, relativePath ); + attributeList.add( source ); + break; + } + case MANY_TO_MANY: + case ONE_TO_MANY: + case ELEMENT_COLLECTION_BASIC: + case ELEMENT_COLLECTION_EMBEDDABLE: { + attributeList.add( + createPluralAttributeSource( + configuredClass, + (PluralAssociationAttribute) associationAttribute, + relativePath + ) + ); + break; + } + default: { + throw new NotYetImplementedException(); + } + } + } + } + + private static PluralAttributeSource createPluralAttributeSource( + ConfiguredClass configuredClass, + PluralAssociationAttribute pluralAssociationAttribute, + String relativePath) { + switch ( pluralAssociationAttribute.getPluralAttributeNature() ) { + case BAG: // fall through intentionally + case SET: { + return new PluralAttributeSourceImpl( pluralAssociationAttribute, configuredClass, relativePath ); + } + case ARRAY: // fall through intentionally + case MAP: // fall through intentionally + case LIST: { + return new IndexedPluralAttributeSourceImpl( pluralAssociationAttribute, configuredClass, relativePath ); + } + case ID_BAG: { + throw new NotYetImplementedException( + String.format( + "%s attributes are not supported yet", + pluralAssociationAttribute.getPluralAttributeNature() + ) + ); + } + default: { + throw new AssertionFailure( + String.format( + "Unknown plural attribute nature: %s", + pluralAssociationAttribute.getPluralAttributeNature() + ) + ); + } + } + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SubclassEntitySourceImpl.java similarity index 61% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SubclassEntitySourceImpl.java index dc8dbe7843..06b8751ed6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SubclassEntitySourceImpl.java @@ -21,30 +21,31 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations; -import org.hibernate.metamodel.source.BindingContext; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.Index; - -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; /** - * Defines an interface for providing additional annotation related context information. - * - * @author Steve Ebersole * @author Hardy Ferentschik + * @author Strong Liu */ -public interface AnnotationBindingContext extends BindingContext { - Index getIndex(); +public class SubclassEntitySourceImpl extends EntitySourceImpl implements SubclassEntitySource { - ClassInfo getClassInfo(String name); + private final EntitySource container; - void resolveAllTypes(String className); + public SubclassEntitySourceImpl( + final EntityClass entityClass, + final EntitySource container) { + super( entityClass ); + this.container = container; + } - ResolvedType getResolvedType(Class clazz); - - ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type); + @Override + public EntitySource superclassEntitySource() { + return container; + } } + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TableSourceImpl.java new file mode 100644 index 0000000000..8c9080a756 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TableSourceImpl.java @@ -0,0 +1,186 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.TableSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +class TableSourceImpl implements TableSource { + private final TableInfo tableInfo; + private final EntityBindingContext bindingContext; + + TableSourceImpl(AnnotationInstance tableAnnotation, EntityBindingContext bindingContext) { + this.bindingContext = bindingContext; + this.tableInfo = createTableInfo( tableAnnotation ); + } + + @Override + public String getExplicitSchemaName() { + return tableInfo.getSchema(); + } + + @Override + public String getExplicitCatalogName() { + return tableInfo.getCatalog(); + } + + @Override + public String getExplicitTableName() { + return tableInfo.getTableName(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + TableSourceImpl that = ( TableSourceImpl ) o; + + if ( tableInfo != null ? !tableInfo.equals( that.tableInfo ) : that.tableInfo != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return tableInfo != null ? tableInfo.hashCode() : 0; + } + + private TableInfo createTableInfo(AnnotationInstance tableAnnotation) { + if ( tableAnnotation != null ) { + return createPrimaryTableInfo( tableAnnotation ); + } + else { + return new TableInfo( null, null, null ); + } + } + + private TableInfo createPrimaryTableInfo(AnnotationInstance tableAnnotation) { + final String schemaName = determineSchemaName( tableAnnotation ); + final String catalogName = determineCatalogName( tableAnnotation ); + + final String explicitTableName = tableAnnotation == null + ? null + : JandexHelper.getValue( tableAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + + return new TableInfo( schemaName, catalogName, explicitTableName ); + } + + private String determineSchemaName(AnnotationInstance tableAnnotation) { + return tableAnnotation == null + ? null + : JandexHelper.getValue( tableAnnotation, "schema", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + private String determineCatalogName(AnnotationInstance tableAnnotation) { + return tableAnnotation == null + ? null + : JandexHelper.getValue( tableAnnotation, "catalog", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + private static class TableInfo { + private final String schema; + private final String catalog; + private final String tableName; + + private TableInfo(String schema, String catalog, String tableName) { + this.schema = schema; + this.catalog = catalog; + this.tableName = tableName; + } + + public String getSchema() { + return schema; + } + + public String getCatalog() { + return catalog; + } + + public String getTableName() { + return tableName; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + TableInfo tableInfo = ( TableInfo ) o; + + if ( catalog != null ? !catalog.equals( tableInfo.catalog ) : tableInfo.catalog != null ) { + return false; + } + if ( schema != null ? !schema.equals( tableInfo.schema ) : tableInfo.schema != null ) { + return false; + } + if ( tableName != null ? !tableName.equals( tableInfo.tableName ) : tableInfo.tableName != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = schema != null ? schema.hashCode() : 0; + result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); + result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "TableInfo" ); + sb.append( "{schema='" ).append( schema ).append( '\'' ); + sb.append( ", catalog='" ).append( catalog ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java new file mode 100644 index 0000000000..fb609cc8af --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java @@ -0,0 +1,314 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource { + private final List relationalValueSources; + private final String containingTableName; + private final EntityBindingContext bindingContext; + + public ToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath, + EntityBindingContext bindingContext) { + super( associationAttribute, relativePath ); + if ( associationAttribute.getMappedBy() != null ) { + throw new IllegalArgumentException( "associationAttribute.getMappedBy() must be null" ); + } + this.bindingContext = bindingContext; + // Need to initialize relationalValueSources before determining logicalJoinTableName. + this.relationalValueSources = resolveRelationalValueSources( associationAttribute ); + // Need to initialize logicalJoinTableName before determining nature. + this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources ); + setNature( determineNatureIfPossible( associationAttribute ) ); + } + + private Nature determineNatureIfPossible( + SingularAssociationAttribute associationAttribute) { + if ( MappedAttribute.Nature.MANY_TO_ONE.equals( associationAttribute.getNature() ) ) { + return Nature.MANY_TO_ONE; + } + else if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() ) ) { + if ( getContainingTableName() != null ) { + return Nature.MANY_TO_ONE; + } + else if ( associationAttribute.hasPrimaryKeyJoinColumn() ) { + return Nature.ONE_TO_ONE; + } + else if ( associationAttribute.isId() ) { + // if this association is part of the ID then this can't be a one-to-one + return Nature.MANY_TO_ONE; + } + else if ( associationAttribute.getJoinColumnValues() == null || + associationAttribute.getJoinColumnValues().isEmpty() ) { + return Nature.MANY_TO_ONE; + } + else { + return null; + } + } + else { + throw new AssertionError(String.format( "Wrong attribute nature[%s] for toOne attribute: %s", + associationAttribute.getNature(), associationAttribute.getRole() )); + } + } + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + if ( getNature() != null ) { + return; + } + // It would be nice to have the following block in determineNatureIfPossible(), + // but it requires context.resolveIdentifierColumns(), it's here instead. + if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) { + final List idColumns = context.resolveIdentifierColumns(); + if ( associationAttribute().getJoinColumnValues().size() != idColumns.size() ) { + setNature( Nature.MANY_TO_ONE ); + } + else { + Set joinColumnNames = new HashSet( associationAttribute().getJoinColumnValues().size() ); + for ( Column joinColumn : associationAttribute().getJoinColumnValues() ) { + joinColumnNames.add( joinColumn.getName() ); + } + // if join columns are the entity's ID, then it is a one-to-one (mapToPk == true) + boolean areJoinColumnsSameAsIdColumns = true; + for ( org.hibernate.metamodel.spi.relational.Column idColumn : idColumns ) { + if ( ! joinColumnNames.contains( idColumn.getColumnName().getText() ) ) { + areJoinColumnsSameAsIdColumns = false; + break; + } + } + setNature( areJoinColumnsSameAsIdColumns ? Nature.ONE_TO_ONE : Nature.MANY_TO_ONE ); + } + } + if ( getNature() == null ) { + throw new NotYetImplementedException( "unknown type of to-one attribute." ); + } + } + + @Override + public List getDefaultNamingStrategies( + final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding) { + if ( CompositeAttributeBinding.class.isInstance( referencedAttributeBinding ) ) { + CompositeAttributeBinding compositeAttributeBinding = CompositeAttributeBinding.class.cast( + referencedAttributeBinding + ); + List result = new ArrayList( ); + for ( final AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) { + result.addAll( getDefaultNamingStrategies( entityName, tableName, attributeBinding ) ); + } + return result; + } + else { + List result = new ArrayList( 1 ); + result.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + associationAttribute().getName(), + entityName, + tableName, + referencedAttributeBinding.getAttribute().getName() + ); + } + } + ); + return result; + } + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + private List resolveRelationalValueSources(AssociationAttribute associationAttribute) { + final List valueSources; + final List joinColumns; + if ( associationAttribute.getJoinTableAnnotation() == null ) { + joinColumns = associationAttribute.getJoinColumnValues(); + } + else { + joinColumns = associationAttribute.getInverseJoinColumnValues(); + } + if ( joinColumns.isEmpty() ) { + valueSources = Collections.emptyList(); + } + else { + valueSources = new ArrayList( joinColumns.size() ); + for ( Column joinColumn : joinColumns ) { + valueSources.add( + new ColumnSourceImpl( + associationAttribute, + joinColumn, + getDefaultLogicalJoinTableName( associationAttribute ) + ) + ); + } + } + return valueSources; + } + + private String getDefaultLogicalJoinTableName(AssociationAttribute associationAttribute) { + if ( associationAttribute.getJoinTableAnnotation() == null ) { + return null; + } + return JandexHelper.getValue( associationAttribute.getJoinTableAnnotation(), "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class )); + } + + + private String resolveContainingTableName( + AssociationAttribute associationAttribute, + List relationalValueSources) { + if ( relationalValueSources.isEmpty() ) { + return getDefaultLogicalJoinTableName( associationAttribute ); + } + String logicalTableName = relationalValueSources.get( 0 ).getContainingTableName(); + for ( int i = 1; i< relationalValueSources.size(); i++ ) { + if ( logicalTableName == null ) { + if ( relationalValueSources.get( i ).getContainingTableName() != null ) { + throw new IllegalStateException( "Relational value sources refer to null and non-null containing tables." ); + } + } + else if ( !logicalTableName.equals( relationalValueSources.get( i ).getContainingTableName() ) ) { + throw new IllegalStateException( "Relational value sources do not refer to the same containing table." ); + } + } + return logicalTableName; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + List joinColumns = + associationAttribute().getJoinTableAnnotation() == null ? + associationAttribute().getJoinColumnValues() : + associationAttribute().getInverseJoinColumnValues(); + boolean hasReferencedColumn = false; + for ( Column joinColumn : joinColumns ) { + if ( joinColumn.getReferencedColumnName() != null ) { + hasReferencedColumn = true; + break; + } + } + return hasReferencedColumn ? new AnnotationJoinColumnResolutionDelegate() : null; + } + + @Override + public String getExplicitForeignKeyName() { + return null; + } + + public class AnnotationJoinColumnResolutionDelegate + implements ForeignKeyContributingSource.JoinColumnResolutionDelegate { + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + final List values = new ArrayList(); + final List joinColumns = + associationAttribute().getJoinTableAnnotation() == null ? + associationAttribute().getJoinColumnValues() : + associationAttribute().getInverseJoinColumnValues(); + for ( Column joinColumn : joinColumns ) { + if ( joinColumn.getReferencedColumnName() == null ) { + return context.resolveRelationalValuesForAttribute( null ); + } + org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn( + joinColumn.getReferencedColumnName(), + null, + null, + null + ); + values.add( resolvedColumn ); + } + return values; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( + null, + null, + null + ); + } + + @Override + public String getReferencedAttributeName() { + // in annotations we are not referencing attribute but column names via @JoinColumn(s) + return null; + } + + private String resolveLogicalJoinTableName() { + final AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation( + associationAttribute().annotations(), + JPADotNames.JOIN_TABLE + ); + + if ( joinTableAnnotation != null ) { + return JandexHelper.getValue( joinTableAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + // todo : this ties into the discussion about naming strategies. This would be part of a logical naming strategy... + return null; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneMappedByAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneMappedByAttributeSourceImpl.java new file mode 100644 index 0000000000..39dbef9ea1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneMappedByAttributeSourceImpl.java @@ -0,0 +1,119 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.List; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; + +/** + * @author Gail Badner + */ +public class ToOneMappedByAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements MappedByAssociationSource { + private ToOneAttributeSource owner; + + public ToOneMappedByAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath) { + super( associationAttribute, relativePath); + if ( associationAttribute.getMappedBy() == null ) { + throw new IllegalArgumentException( "associationAttribute.getMappedBy() must be non-null" ); + } + } + + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + if ( getNature() != null && owner != null) { + return; + } + if ( owner == null ) { + owner = (ToOneAttributeSource) context.resolveAttributeSource( + associationAttribute().getReferencedEntityType(), + associationAttribute().getMappedBy() + ); + owner.addMappedByAssociationSource( this ); + } + if ( getNature() == null ) { + final Nature nature; + if ( MappedAttribute.Nature.MANY_TO_ONE.equals( associationAttribute().getNature() ) ) { + nature = Nature.MANY_TO_ONE; + } + else if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) { + if ( owner.getContainingTableName() != null ) { + nature = Nature.MANY_TO_ONE; + } + else { + nature = Nature.ONE_TO_ONE; + } + } + else { + throw new AssertionError(String.format( + "Wrong attribute nature[%s] for toOne attribute: %s", + associationAttribute().getNature(), associationAttribute().getRole() + )); + } + setNature( nature ); + } + } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return associationAttribute().getMappedBy(); + } + + @Override + public List relationalValueSources() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public String getContainingTableName() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public String getExplicitForeignKeyName() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public List getDefaultNamingStrategies(String entityName, String tableName, AttributeBinding referencedAttributeBinding) { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TypeDescriptorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TypeDescriptorSourceImpl.java new file mode 100644 index 0000000000..efc7cc0e8c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/TypeDescriptorSourceImpl.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class TypeDescriptorSourceImpl implements TypeDescriptorSource { + private final String name; + private final String implementationClassName; + private final String[] registrationKeys; + private final AnnotationBindingContext bindingContext; + + private Map parameterValueMap; + + public TypeDescriptorSourceImpl(AnnotationInstance typeDefAnnotation, AnnotationBindingContext bindingContext) { + this.bindingContext = bindingContext; + this.name = JandexHelper.getValue( typeDefAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + this.implementationClassName = JandexHelper.getValue( typeDefAnnotation, "typeClass", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + + String defaultForType = JandexHelper.getValue( typeDefAnnotation, "defaultForType", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + if ( defaultForType != null ) { + if ( void.class.getName().equals( defaultForType ) ) { + defaultForType = null; + } + } + String registrationKey = defaultForType; + + if ( StringHelper.isEmpty( name ) && registrationKey == null ) { + throw new AnnotationException( + String.format( + "Either name or defaultForType (or both) must be set on TypeDefinition [%s]", + implementationClassName + ) + ); + } + + this.registrationKeys = registrationKey == null ? new String[0] : new String[] { registrationKey }; + this.parameterValueMap = extractParameterValues( typeDefAnnotation ); + } + + private Map extractParameterValues(AnnotationInstance typeDefAnnotation) { + Map parameterMaps = new HashMap(); + AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + typeDefAnnotation, + "parameters", + AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMaps.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ), + JandexHelper.getValue( parameterAnnotation, "value", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + return parameterMaps; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getTypeImplementationClassName() { + return implementationClassName; + } + + @Override + public String[] getRegistrationKeys() { + return registrationKeys; + } + + @Override + public Map getParameters() { + return parameterValueMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UniqueConstraintSourceImpl.java similarity index 52% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UniqueConstraintSourceImpl.java index 47916da9ed..752015b5d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UniqueConstraintSourceImpl.java @@ -21,40 +21,37 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - -package org.hibernate.metamodel.source.annotations.attribute.type; +package org.hibernate.metamodel.internal.source.annotations; import java.util.Collections; -import java.util.Map; +import java.util.List; -import org.hibernate.internal.util.StringHelper; - -import org.jboss.jandex.AnnotationInstance; +import org.hibernate.metamodel.spi.source.UniqueConstraintSource; /** - * @author Strong Liu + * @author Hardy Ferentschik */ -public abstract class AbstractAttributeTypeResolver implements AttributeTypeResolver { - protected abstract AnnotationInstance getTypeDeterminingAnnotationInstance(); - - protected abstract String resolveHibernateTypeName(AnnotationInstance annotationInstance); - - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - return Collections.emptyMap(); +class UniqueConstraintSourceImpl extends AbstractConstraintSource implements UniqueConstraintSource { + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames, List orderings) { + super( name, tableName, columnNames, orderings ); + } + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { + super( name, tableName, columnNames, Collections.EMPTY_LIST ); } @Override - final public String getExplicitHibernateTypeName() { - return resolveHibernateTypeName( getTypeDeterminingAnnotationInstance() ); - } - - @Override - final public Map getExplicitHibernateTypeParameters() { - if ( StringHelper.isNotEmpty( getExplicitHibernateTypeName() ) ) { - return resolveHibernateTypeParameters( getTypeDeterminingAnnotationInstance() ); - } - else { - return Collections.emptyMap(); - } + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "UniqueConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); } } + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UnknownInheritanceTypeException.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UnknownInheritanceTypeException.java index 1f492d5d6c..8f4916d33e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/UnknownInheritanceTypeException.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/VersionAttributeSourceImpl.java new file mode 100644 index 0000000000..ccb9e0f020 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/VersionAttributeSourceImpl.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations; + +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; + +/** + * @author Steve Ebersole + */ +public class VersionAttributeSourceImpl + extends SingularAttributeSourceImpl + implements VersionAttributeSource { + + public VersionAttributeSourceImpl(MappedAttribute attribute) { + super( attribute ); + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AbstractOverrideDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AbstractOverrideDefinition.java new file mode 100644 index 0000000000..b458ec9a45 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AbstractOverrideDefinition.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import org.hibernate.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class AbstractOverrideDefinition { + + protected static final String PROPERTY_PATH_SEPARATOR = "."; + protected final String attributePath; + protected final EntityBindingContext bindingContext; + + private boolean isApplied; + + public AbstractOverrideDefinition(String prefix, AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + if ( attributeOverrideAnnotation == null ) { + throw new IllegalArgumentException( "An AnnotationInstance needs to be passed" ); + } + + if ( !getTargetAnnotation().equals( attributeOverrideAnnotation.name() ) ) { + throw new AssertionFailure( "A @AttributeOverride annotation needs to be passed to the constructor" ); + } + this.attributePath = createAttributePath( + prefix, + JandexHelper.getValue( attributeOverrideAnnotation, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class )) + ); + this.bindingContext = bindingContext; + } + + protected static String createAttributePath(String prefix, String name) { + if ( StringHelper.isEmpty( name ) ) { + throw new AssertionFailure( "name attribute in @AttributeOverride can't be empty" ); + } + String path = ""; + if ( StringHelper.isNotEmpty( prefix ) ) { + path += prefix; + } + if ( StringHelper.isNotEmpty( path ) && !path.endsWith( PROPERTY_PATH_SEPARATOR ) ) { + path += PROPERTY_PATH_SEPARATOR; + } + path += name; + return path; + } + + public String getAttributePath(){ + return attributePath; + } + + public abstract void apply(MappedAttribute mappedAttribute); + + protected abstract DotName getTargetAnnotation(); + + public boolean isApplied() { + return isApplied; + } + + public void setApplied(boolean applied) { + isApplied = applied; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof AbstractOverrideDefinition ) ) { + return false; + } + + AbstractOverrideDefinition that = (AbstractOverrideDefinition) o; + + if ( attributePath != null ? !attributePath.equals( that.attributePath ) : that.attributePath != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return attributePath != null ? attributePath.hashCode() : 0; + } + + @Override + public String toString() { + return "AbstractOverrideDefinition{" + + "attributePath='" + attributePath + '\'' + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java new file mode 100644 index 0000000000..60a185cb63 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java @@ -0,0 +1,577 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.FetchType; + +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.LazyToOneOption; +import org.hibernate.annotations.NotFoundAction; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.FetchStyle; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.MockHelper; +import org.hibernate.metamodel.spi.source.MappingException; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; + +/** + * Represents an association attribute. + * + * @author Hardy Ferentschik + * @author Brett Meyer + * @author Gail Badner + */ +public class AssociationAttribute extends MappedAttribute { + private static final CoreMessageLogger coreLogger = Logger.getMessageLogger( + CoreMessageLogger.class, + AssociationAttribute.class.getName() + ); + + private final boolean ignoreNotFound; + private final String referencedEntityType; + private final Class referencedAttributeType; + private final String mappedBy; + private final Set cascadeTypes; + private final Set hibernateCascadeTypes; + private final boolean isOptional; + private final boolean isLazy; + private final boolean isUnWrapProxy; + private final boolean isOrphanRemoval; + private final FetchStyle fetchStyle; + private final boolean mapsId; + private final String referencedIdAttributeName; + private ArrayList joinColumnValues = new ArrayList(); + private ArrayList inverseJoinColumnValues = new ArrayList(); + private final AnnotationInstance joinTableAnnotation; + private AttributeTypeResolver resolver; + + AssociationAttribute( + ClassInfo classInfo, + String name, + Class attributeType, + Class referencedAttributeType, + Nature attributeNature, + String accessType, + Map> annotations, + EntityBindingContext context) { + super( name, attributeType, attributeNature, accessType, annotations, context ); + this.ignoreNotFound = determineNotFoundBehavior(); + + AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation( + annotations, + attributeNature.getAnnotationDotName() + ); + if ( associationAnnotation == null && + ( attributeNature == Nature.ELEMENT_COLLECTION_BASIC || attributeNature == Nature.ELEMENT_COLLECTION_EMBEDDABLE ) ) { + + AnnotationTarget target = MockHelper.getTarget( + context.getServiceRegistry(), + classInfo, + name, + MockHelper.TargetType.valueOf( accessType.toUpperCase() ) + ); + + + associationAnnotation = AnnotationInstance.create( + attributeNature.getAnnotationDotName(), + target, + MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY + ); + } + + // using jandex we don't really care which exact type of annotation we are dealing with + this.referencedEntityType = determineReferencedEntityType( associationAnnotation, referencedAttributeType ); + this.referencedAttributeType = referencedAttributeType; + this.mappedBy = determineMappedByAttributeName( associationAnnotation ); + this.isOptional = determineOptionality( associationAnnotation ); + this.isLazy = determineIsLazy( associationAnnotation ); + this.isUnWrapProxy = determinIsUnwrapProxy(); + this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation ); + this.cascadeTypes = determineCascadeTypes( associationAnnotation ); + this.hibernateCascadeTypes = determineHibernateCascadeTypes( annotations ); + + if ( this.mappedBy == null ) { + determineJoinColumnAnnotations( annotations ); + determineJoinTableAnnotations( annotations, referencedAttributeType ); + joinColumnValues.trimToSize(); + inverseJoinColumnValues.trimToSize(); + this.joinTableAnnotation = determineExplicitJoinTable( annotations ); + } + else { + this.joinTableAnnotation = null; + } + + this.fetchStyle = determineFetchStyle(); + this.referencedIdAttributeName = determineMapsId(); + this.mapsId = referencedIdAttributeName != null; + } + + public boolean isIgnoreNotFound() { + return ignoreNotFound; + } + + public String getReferencedEntityType() { + return referencedEntityType; + } + + public Class getReferencedAttributeType() { + return referencedAttributeType; + } + + public String getMappedBy() { + return mappedBy; + } + + public Set getCascadeTypes() { + return cascadeTypes; + } + + public Set getHibernateCascadeTypes() { + return hibernateCascadeTypes; + } + + public boolean isOrphanRemoval() { + return isOrphanRemoval; + } + + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + public String getReferencedIdAttributeName() { + return referencedIdAttributeName; + } + + public boolean mapsId() { + return mapsId; + } + + public List getJoinColumnValues() { + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine join column information because assocation is not owner." ); + } + return joinColumnValues; + } + + public List getInverseJoinColumnValues() { + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine inverse join column information because assocation is not owner." ); + } + return inverseJoinColumnValues; + } + + public AnnotationInstance getJoinTableAnnotation() { + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine join table information because assocation is not owner." ); + } + return joinTableAnnotation; + } + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + if ( resolver == null ) { + resolver = getDefaultHibernateTypeResolver(); + } + return resolver; + } + + @Override + public boolean isLazy() { + return isLazy; + } + + public boolean isUnWrapProxy() { + return isUnWrapProxy; + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public boolean isInsertable() { + return true; + } + + @Override + public boolean isUpdatable() { + return true; + } + protected boolean hasOptimisticLockAnnotation(){ + AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.OPTIMISTIC_LOCK + ); + return optimisticLockAnnotation != null; + } + @Override + public boolean isOptimisticLockable() { + if(hasOptimisticLockAnnotation()){ + return super.isOptimisticLockable(); + } else { + Nature nature = getNature(); + return (nature != Nature.ONE_TO_ONE && nature != Nature.MANY_TO_ONE ) || isInsertable(); + } + + } + + @Override + public PropertyGeneration getPropertyGeneration() { + return PropertyGeneration.NEVER; + } + + protected AttributeTypeResolver getDefaultHibernateTypeResolver() { + return new CompositeAttributeTypeResolver( + this, + HibernateTypeResolver.createAttributeTypeResolver( this ) + ); + } + + private boolean determineNotFoundBehavior() { + NotFoundAction action = NotFoundAction.EXCEPTION; + AnnotationInstance notFoundAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.NOT_FOUND + ); + if ( notFoundAnnotation != null ) { + AnnotationValue actionValue = notFoundAnnotation.value( "action" ); + if ( actionValue != null ) { + action = Enum.valueOf( NotFoundAction.class, actionValue.asEnum() ); + } + } + + return NotFoundAction.IGNORE.equals( action ); + } + + private boolean determinIsUnwrapProxy() { + AnnotationInstance lazyToOne = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.LAZY_TO_ONE ); + if ( lazyToOne != null ) { + return JandexHelper.getEnumValue( lazyToOne, "value", LazyToOneOption.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) == LazyToOneOption.NO_PROXY; + } + return false; + } + + private boolean determineOptionality(AnnotationInstance associationAnnotation) { + boolean optional = true; + + AnnotationValue optionalValue = associationAnnotation.value( "optional" ); + if ( optionalValue != null ) { + optional = optionalValue.asBoolean(); + } + + return optional; + } + + private boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) { + boolean orphanRemoval = false; + AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" ); + if ( orphanRemovalValue != null ) { + orphanRemoval = orphanRemovalValue.asBoolean(); + } + return orphanRemoval; + } + + protected boolean determineIsLazy(AnnotationInstance associationAnnotation) { + FetchType fetchType = JandexHelper.getEnumValue( associationAnnotation, "fetch", FetchType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + boolean lazy = fetchType == FetchType.LAZY; + final AnnotationInstance lazyToOneAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.LAZY_TO_ONE + ); + if ( lazyToOneAnnotation != null ) { + LazyToOneOption option = JandexHelper.getEnumValue( lazyToOneAnnotation, "value", LazyToOneOption.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + lazy = option != LazyToOneOption.FALSE; + } + + if ( associationAnnotation.value( "fetch" ) != null ) { + lazy = FetchType.LAZY == fetchType; + } + final AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.FETCH + ); + if ( fetchAnnotation != null ) { + lazy = JandexHelper.getEnumValue( fetchAnnotation, "value", FetchMode.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) != FetchMode.JOIN; + } + if ( getFetchStyle() != null ) { + lazy = getFetchStyle() != FetchStyle.JOIN; + } + return lazy; + } + + private String determineReferencedEntityType(AnnotationInstance associationAnnotation, Class referencedAttributeType) { + // use the annotated attribute type as default target type + String targetTypeName = null; + + // unless we have an explicit @Target + AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.TARGET + ); + if ( targetAnnotation != null ) { + targetTypeName = targetAnnotation.value().asClass().name().toString(); + } + + AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" ); + if ( targetEntityValue != null ) { + targetTypeName = targetEntityValue.asClass().name().toString(); + } + + if( StringHelper.isEmpty( targetTypeName ) ) { + if ( referencedAttributeType != null ) { + targetTypeName = referencedAttributeType.getName(); + } + else { + throw getContext().makeMappingException( "Can't find the target type for this collection attribute: "+ getRole() ); + } + } + + return targetTypeName; + } + + private String determineMappedByAttributeName(AnnotationInstance associationAnnotation) { + String mappedBy = null; + AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" ); + if ( mappedByAnnotationValue != null ) { + mappedBy = mappedByAnnotationValue.asString(); + } + + return mappedBy; + } + + private Set determineCascadeTypes(AnnotationInstance associationAnnotation) { + Set cascadeTypes = new HashSet(); + AnnotationValue cascadeValue = associationAnnotation.value( "cascade" ); + if ( cascadeValue != null ) { + String[] cascades = cascadeValue.asEnumArray(); + for ( String s : cascades ) { + cascadeTypes.add( Enum.valueOf( CascadeType.class, s ) ); + } + } + return cascadeTypes; + } + + private Set determineHibernateCascadeTypes( + Map> annotations) { + AnnotationInstance cascadeAnnotation = JandexHelper + .getSingleAnnotation( + annotations, HibernateDotNames.CASCADE ); + Set cascadeTypes + = new HashSet(); + if ( cascadeAnnotation != null ) { + AnnotationValue cascadeValue = cascadeAnnotation.value(); + if ( cascadeValue != null ) { + String[] cascades = cascadeValue.asEnumArray(); + for ( String s : cascades ) { + cascadeTypes.add( Enum.valueOf( + org.hibernate.annotations.CascadeType.class, s ) ); + } + } + } + return cascadeTypes; + } + + private FetchStyle determineFetchStyle() { + AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.FETCH ); + if ( fetchAnnotation != null ) { + org.hibernate.annotations.FetchMode annotationFetchMode = JandexHelper.getEnumValue( + fetchAnnotation, + "value", + org.hibernate.annotations.FetchMode.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + return EnumConversionHelper.annotationFetchModeToFetchStyle( annotationFetchMode ); + } + + return null; + } + + private String determineMapsId() { + AnnotationInstance mapsIdAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.MAPS_ID ); + if ( mapsIdAnnotation == null ) { + return null; + } + if ( !( Nature.MANY_TO_ONE.equals( getNature() ) || Nature.MANY_TO_ONE + .equals( getNature() ) ) ) { + throw new MappingException( + "@MapsId can only be specified on a many-to-one or one-to-one associations, property: "+ getRole(), + getContext().getOrigin() + ); + } + return JandexHelper.getValue( mapsIdAnnotation, "value", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class )); + } + + private void determineJoinColumnAnnotations(Map> annotations) { + // If mappedBy is defined, then annotations for this association are on the + // owning side of the association. + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine join column information because association is not the owner." ); + } + + Collection joinColumnAnnotations = JandexHelper.getAnnotations( + annotations, + JPADotNames.JOIN_COLUMN, + JPADotNames.JOIN_COLUMNS, + true, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) { + joinColumnValues.add( new Column( joinColumnAnnotation ) ); + } + + // @JoinColumn as part of @CollectionTable + AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.COLLECTION_TABLE + ); + if ( collectionTableAnnotation != null ) { + List columnsList = Arrays.asList( + JandexHelper.getValue( collectionTableAnnotation, "joinColumns", AnnotationInstance[].class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + for ( AnnotationInstance annotation : columnsList ) { + joinColumnValues.add( new Column( annotation ) ); + } + } + } + + private void determineJoinTableAnnotations( + Map> annotations, + Class referencedAttributeType ) { + + // If mappedBy is defined, then annotations for this association are on the + // owning side of the association. + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine join table information because association is not the owner." ); + } + + // @JoinColumn as part of @JoinTable + AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.JOIN_TABLE + ); + if (joinTableAnnotation != null) { + List columnsList = Arrays.asList( + JandexHelper.getValue( joinTableAnnotation, "joinColumns", AnnotationInstance[].class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + List inverseColumnsList = Arrays.asList( + JandexHelper.getValue( joinTableAnnotation, "inverseJoinColumns", AnnotationInstance[].class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + + for ( AnnotationInstance annotation : columnsList ) { + joinColumnValues.add( new Column( annotation ) ); + } + for ( AnnotationInstance annotation : inverseColumnsList ) { + inverseJoinColumnValues.add( new Column( annotation ) ); + } + } + } + + private AnnotationInstance determineExplicitJoinTable(Map> annotations) { + // If mappedBy is defined, then annotations for this association are on the + // owning side of the association. + if ( mappedBy != null ) { + throw new IllegalStateException( "Cannot determine join table information because association is not the owner." ); + } + + AnnotationInstance annotationInstance = null; + AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.COLLECTION_TABLE + ); + + AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.JOIN_TABLE + ); + + // sanity checks + if ( collectionTableAnnotation != null && joinTableAnnotation != null ) { + String msg = coreLogger.collectionTableAndJoinTableUsedTogether( + getContext().getOrigin().getName(), + getName() + ); + throw new MappingException( msg, getContext().getOrigin() ); + } + + if ( collectionTableAnnotation != null ) { + if ( JandexHelper.getSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION ) == null ) { + String msg = coreLogger.collectionTableWithoutElementCollection( + getContext().getOrigin().getName(), + getName() + ); + throw new MappingException( msg, getContext().getOrigin() ); + } + annotationInstance = collectionTableAnnotation; + } + + if ( joinTableAnnotation != null ) { + if ( JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ) == null + && JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ) == null + && JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) == null + && JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ) == null) { + String msg = coreLogger.joinTableForNonAssociationAttribute( + getContext().getOrigin().getName(), + getName() + ); + throw new MappingException( msg, getContext().getOrigin() ); + } + annotationInstance = joinTableAnnotation; + } + + return annotationInstance; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationOverride.java similarity index 55% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationOverride.java index 8cf9228198..54a0ad87c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationOverride.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,34 +21,33 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.source.annotations.JPADotNames; +package org.hibernate.metamodel.internal.source.annotations.attribute; +import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; + /** - * An enum defining the type of a mapped attribute. - * - * @author Hardy Ferentschik + * @author Strong Liu */ -public enum AttributeNature { - BASIC( JPADotNames.BASIC ), - ONE_TO_ONE( JPADotNames.ONE_TO_ONE ), - ONE_TO_MANY( JPADotNames.ONE_TO_MANY ), - MANY_TO_ONE( JPADotNames.MANY_TO_ONE ), - MANY_TO_MANY( JPADotNames.MANY_TO_MANY ), - ELEMENT_COLLECTION( JPADotNames.ELEMENT_COLLECTION ), - EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), - EMBEDDED( JPADotNames.EMBEDDED ); +public class AssociationOverride extends AbstractOverrideDefinition { - private final DotName annotationDotName; - - AttributeNature(DotName annotationDotName) { - this.annotationDotName = annotationDotName; + public AssociationOverride(String prefix, AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + super( prefix, attributeOverrideAnnotation, bindingContext ); } - public DotName getAnnotationDotName() { - return annotationDotName; + @Override + protected DotName getTargetAnnotation() { + return JPADotNames.ASSOCIATION_OVERRIDE; } + + + @Override + public void apply(MappedAttribute mappedAttribute) { + } + + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AttributeOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AttributeOverride.java new file mode 100644 index 0000000000..b1964fc2c9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AttributeOverride.java @@ -0,0 +1,107 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * Contains the information about a single {@link javax.persistence.AttributeOverride}. Instances of this class + * are creating during annotation processing and then applied onto the persistence attributes. + * + * @author Hardy Ferentschik + * @todo Take care of prefixes of the form 'element', 'key' and 'value'. Add another type enum to handle this. (HF) + */ +public class AttributeOverride extends AbstractOverrideDefinition{ + private final Column column; + private final AnnotationInstance columnAnnotation; + + public AttributeOverride(String prefix, AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + super(prefix, attributeOverrideAnnotation, bindingContext); + + this.columnAnnotation= JandexHelper.getValue( attributeOverrideAnnotation, "column", AnnotationInstance.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class )); + this.column = new Column( columnAnnotation ); + } + + @Override + protected DotName getTargetAnnotation() { + return JPADotNames.ATTRIBUTE_OVERRIDE; + } + + + @Override + public void apply(MappedAttribute mappedAttribute) { + int columnSize = mappedAttribute.getColumnValues().size(); + switch ( columnSize ){ + case 0: + mappedAttribute.getColumnValues().add( column ); + break; + case 1: + mappedAttribute.getColumnValues().get( 0 ).applyColumnValues( columnAnnotation ); + break; + default: + //TODO throw exception?? + } + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof AttributeOverride ) ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + + AttributeOverride that = (AttributeOverride) o; + + if ( column != null ? !column.equals( that.column ) : that.column != null ) { + return false; + } + if ( columnAnnotation != null ? !columnAnnotation.equals( that.columnAnnotation ) : that.columnAnnotation != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + ( column != null ? column.hashCode() : 0 ); + result = 31 * result + ( columnAnnotation != null ? columnAnnotation.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java index 280edcf9bf..ecd93278a9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java @@ -21,33 +21,35 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; +package org.hibernate.metamodel.internal.source.annotations.attribute; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; + import javax.persistence.FetchType; import javax.persistence.GenerationType; import org.hibernate.AnnotationException; import org.hibernate.annotations.GenerationTime; +import org.hibernate.annotations.SourceType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl; -import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.EnumeratedTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.LobTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.TemporalTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - +import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.EnumeratedTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.LobTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.TemporalTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.source.MappingException; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; @@ -63,13 +65,16 @@ public class BasicAttribute extends MappedAttribute { * The id generator in case this basic attribute represents an simple id. Will be {@code null} in case there * is no explicit id generator or the containing entity does not have a simple id */ - private final IdGenerator idGenerator; + private final IdentifierGeneratorDefinition identifierGeneratorDefinition; /** - * Is this a versioned property (annotated w/ {@code @Version}. + * Is this a versioned property (annotated w/ {@code @Version}). */ private final boolean isVersioned; + + private final SourceType versionSourceType; + /** * Is this property lazy loaded (see {@link javax.persistence.Basic}). */ @@ -89,45 +94,60 @@ public class BasicAttribute extends MappedAttribute { private final String customWriteFragment; private final String customReadFragment; - private final String checkCondition; private AttributeTypeResolver resolver; - public static BasicAttribute createSimpleAttribute(String name, - Class attributeType, - Map> annotations, - String accessType, - EntityBindingContext context) { - return new BasicAttribute( name, attributeType, accessType, annotations, context ); + public static BasicAttribute createSimpleAttribute( + String name, + Class attributeType, + Nature attributeNature, + Map> annotations, + String accessType, + EntityBindingContext context) { + return new BasicAttribute( name, attributeType, attributeNature, accessType, annotations, context ); } BasicAttribute(String name, Class attributeType, + Nature attributeNature, String accessType, Map> annotations, EntityBindingContext context) { - super( name, attributeType, accessType, annotations, context ); + super( name, attributeType, attributeNature, accessType, annotations, context ); AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION ); isVersioned = versionAnnotation != null; - if ( isId() ) { - // an id must be unique and cannot be nullable - getColumnValues().setUnique( true ); - getColumnValues().setNullable( false ); - idGenerator = checkGeneratedValueAnnotation(); + if ( isVersioned ) { + AnnotationInstance sourceAnnotation = JandexHelper.getSingleAnnotation( + annotations, + HibernateDotNames.SOURCE + ); + this.versionSourceType = sourceAnnotation !=null ? + JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) : null; } else { - idGenerator = null; + versionSourceType = null; + } + + if ( isId() ) { + // an id must be unique and cannot be nullable + for ( Column columnValue : getColumnValues() ) { + columnValue.setNullable( false ); + } + identifierGeneratorDefinition = checkGeneratedValueAnnotation(); + } + else { + identifierGeneratorDefinition = null; } checkBasicAnnotation(); checkGeneratedAnnotation(); - List columnTransformerAnnotations = getAllColumnTransformerAnnotations(); String[] readWrite = createCustomReadWrite( columnTransformerAnnotations ); this.customReadFragment = readWrite[0]; this.customWriteFragment = readWrite[1]; - this.checkCondition = parseCheckAnnotation(); + } public boolean isVersioned() { @@ -162,19 +182,33 @@ public class BasicAttribute extends MappedAttribute { return customReadFragment; } - public String getCheckCondition() { - return checkCondition; + public IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() { + return identifierGeneratorDefinition; } - public IdGenerator getIdGenerator() { - return idGenerator; + public SourceType getVersionSourceType() { + return versionSourceType; + } + + @Override + public boolean isOptimisticLockable() { + boolean isOptimisticLockable = super.isOptimisticLockable(); + if ( !isOptimisticLockable ) { + if ( isId() || isVersioned() ) { + throw new AnnotationException( + "@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: " + + getRole() + ); + } + } + return isOptimisticLockable; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "SimpleAttribute" ); - sb.append( "{name=" ).append( getName() ); + sb.append( "{name=" ).append( getRole() ); return sb.toString(); } @@ -213,6 +247,13 @@ public class BasicAttribute extends MappedAttribute { } } } + else { + if ( isId() ) { + this.isInsertable = true; + this.isUpdatable = false; + this.propertyGeneration = PropertyGeneration.INSERT; + } + } } private List getAllColumnTransformerAnnotations() { @@ -245,13 +286,12 @@ public class BasicAttribute extends MappedAttribute { for ( AnnotationInstance annotationInstance : columnTransformerAnnotations ) { String forColumn = annotationInstance.value( "forColumn" ) == null ? null : annotationInstance.value( "forColumn" ).asString(); - - if ( forColumn != null && !forColumn.equals( getName() ) ) { + if ( forColumn != null && !isColumnPresentForTransformer( forColumn ) ) { continue; } if ( alreadyProcessedForColumn ) { - throw new AnnotationException( "Multiple definition of read/write conditions for column " + getName() ); + throw new AnnotationException( "Multiple definition of read/write conditions for column " + getRole() ); } readWrite[0] = annotationInstance.value( "read" ) == null ? @@ -264,42 +304,44 @@ public class BasicAttribute extends MappedAttribute { return readWrite; } - private String parseCheckAnnotation() { - String checkCondition = null; - AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK ); - if ( checkAnnotation != null ) { - checkCondition = checkAnnotation.value( "constraints" ).toString(); + private boolean isColumnPresentForTransformer(final String forColumn) { + assert forColumn != null; + List columns = getColumnValues(); + for ( final Column column : columns ) { + if ( forColumn.equals( column.getName() ) ) { + return true; + } } - return checkCondition; + return forColumn.equals( getName() ); } - private IdGenerator checkGeneratedValueAnnotation() { - IdGenerator generator = null; + private IdentifierGeneratorDefinition checkGeneratedValueAnnotation() { AnnotationInstance generatedValueAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.GENERATED_VALUE ); - if ( generatedValueAnnotation != null ) { - String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class ); - if ( StringHelper.isNotEmpty( name ) ) { - generator = getContext().getMetadataImplementor().getIdGenerator( name ); - if ( generator == null ) { - throw new MappingException( String.format( "Unable to find named generator %s", name ), null ); - } - } - else { - GenerationType genType = JandexHelper.getEnumValue( - generatedValueAnnotation, - "strategy", - GenerationType.class - ); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - genType, - getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators() - ); - generator = new IdGenerator( null, strategy, null ); + if ( generatedValueAnnotation == null ) { + return null; + } + + IdentifierGeneratorDefinition generator = null; + String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + if ( StringHelper.isNotEmpty( name ) ) { + generator = getContext().findIdGenerator( name ); + if ( generator == null ) { + throw new MappingException( String.format( "Unable to find named generator %s", getRole() ), getContext().getOrigin() ); } } + else { + GenerationType genType = JandexHelper.getEnumValue( generatedValueAnnotation, "strategy", GenerationType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + genType, + getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators() + ); + generator = new IdentifierGeneratorDefinition( null, strategy, null ); + } return generator; } @@ -312,14 +354,11 @@ public class BasicAttribute extends MappedAttribute { } private AttributeTypeResolver getDefaultHibernateTypeResolver() { - CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( - new AttributeTypeResolverImpl( - this - ) - ); - resolver.addHibernateTypeResolver( new TemporalTypeResolver( this ) ); - resolver.addHibernateTypeResolver( new LobTypeResolver( this ) ); - resolver.addHibernateTypeResolver( new EnumeratedTypeResolver( this ) ); + CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this ); + resolver.addHibernateTypeResolver( HibernateTypeResolver.createAttributeTypeResolver( this ) ); + resolver.addHibernateTypeResolver( TemporalTypeResolver.createAttributeTypeResolver( this ) ); + resolver.addHibernateTypeResolver( LobTypeResolver.createAttributeTypeResolve( this ) ); + resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createAttributeTypeResolver( this ) ); return resolver; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java index 03b751aa90..33f65d3148 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java @@ -21,43 +21,60 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; +package org.hibernate.metamodel.internal.source.annotations.attribute; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; /** - * Container for the properties defined by {@link javax.persistence.Column}. + * Container for the properties defined by {@link javax.persistence.Column} or {@link javax.persistence.JoinColumn}. * * @author Hardy Ferentschik */ -public class ColumnValues { +public class Column { private String name = ""; - private boolean unique = false; - private boolean nullable = true; - private boolean insertable = true; - private boolean updatable = true; - private String columnDefinition = ""; private String table = null; + + private Boolean unique; + private Boolean nullable; + private Boolean insertable; + private Boolean updatable; + private int length = 255; private int precision = 0; private int scale = 0; - ColumnValues() { - this( null ); - } + private String columnDefinition; // used for DDL creation - public ColumnValues(AnnotationInstance columnAnnotation) { - if ( columnAnnotation != null && !JPADotNames.COLUMN.equals( columnAnnotation.name() ) ) { - throw new AssertionFailure( "A @Column annotation needs to be passed to the constructor" ); - } + private String referencedColumnName; // from @JoinColumn + + public Column(AnnotationInstance columnAnnotation) { + applyCheck( columnAnnotation ); applyColumnValues( columnAnnotation ); } - private void applyColumnValues(AnnotationInstance columnAnnotation) { + protected void applyCheck(AnnotationInstance columnAnnotation) { + if ( columnAnnotation != null ) { + DotName name = columnAnnotation.name(); + if ( !( JPADotNames.COLUMN.equals( name ) + || JPADotNames.JOIN_COLUMN.equals( name ) + || JPADotNames.ORDER_COLUMN.equals( name ) + || HibernateDotNames.INDEX_COLUMN.equals( name ) + || JPADotNames.PRIMARY_KEY_JOIN_COLUMN.equals( name ) + || JPADotNames.MAP_KEY_COLUMN.equals( name ) + ) ) { + throw new AssertionFailure( "A @Column or @JoinColumn annotation needs to be passed to the constructor" ); + + } + } + } + + protected void applyColumnValues(AnnotationInstance columnAnnotation) { // if the column annotation is null we don't have to do anything. Everything is already defaulted. if ( columnAnnotation == null ) { return; @@ -70,7 +87,7 @@ public class ColumnValues { AnnotationValue uniqueValue = columnAnnotation.value( "unique" ); if ( uniqueValue != null ) { - this.unique = nameValue.asBoolean(); + this.unique = uniqueValue.asBoolean(); } AnnotationValue nullableValue = columnAnnotation.value( "nullable" ); @@ -112,25 +129,30 @@ public class ColumnValues { if ( scaleValue != null ) { this.scale = scaleValue.asInt(); } + + AnnotationValue referencedColumnNameValue = columnAnnotation.value( "referencedColumnName" ); + if ( referencedColumnNameValue != null ) { + this.referencedColumnName = referencedColumnNameValue.asString(); + } } public final String getName() { return name; } - public final boolean isUnique() { + public final Boolean isUnique() { return unique; } - public final boolean isNullable() { + public final Boolean isNullable() { return nullable; } - public final boolean isInsertable() { + public final Boolean isInsertable() { return insertable; } - public final boolean isUpdatable() { + public final Boolean isUpdatable() { return updatable; } @@ -158,19 +180,19 @@ public class ColumnValues { this.name = name; } - public void setUnique(boolean unique) { + public void setUnique(Boolean unique) { this.unique = unique; } - public void setNullable(boolean nullable) { + public void setNullable(Boolean nullable) { this.nullable = nullable; } - public void setInsertable(boolean insertable) { + public void setInsertable(Boolean insertable) { this.insertable = insertable; } - public void setUpdatable(boolean updatable) { + public void setUpdatable(Boolean updatable) { this.updatable = updatable; } @@ -194,20 +216,29 @@ public class ColumnValues { this.scale = scale; } + public String getReferencedColumnName() { + return referencedColumnName; + } + + public void setReferencedColumnName(String referencedColumnName) { + this.referencedColumnName = referencedColumnName; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "ColumnValues" ); sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", table='" ).append( table ).append( '\'' ); sb.append( ", unique=" ).append( unique ); sb.append( ", nullable=" ).append( nullable ); sb.append( ", insertable=" ).append( insertable ); sb.append( ", updatable=" ).append( updatable ); - sb.append( ", columnDefinition='" ).append( columnDefinition ).append( '\'' ); - sb.append( ", table='" ).append( table ).append( '\'' ); sb.append( ", length=" ).append( length ); sb.append( ", precision=" ).append( precision ); sb.append( ", scale=" ).append( scale ); + sb.append( ", columnDefinition='" ).append( columnDefinition ).append( '\'' ); + sb.append( ", referencedColumnName='" ).append( referencedColumnName ).append( '\'' ); sb.append( '}' ); return sb.toString(); } @@ -221,7 +252,7 @@ public class ColumnValues { return false; } - ColumnValues that = (ColumnValues) o; + Column that = (Column) o; if ( insertable != that.insertable ) { return false; @@ -250,6 +281,9 @@ public class ColumnValues { if ( name != null ? !name.equals( that.name ) : that.name != null ) { return false; } + if ( referencedColumnName != null ? !referencedColumnName.equals( that.referencedColumnName ) : that.referencedColumnName != null ) { + return false; + } if ( table != null ? !table.equals( that.table ) : that.table != null ) { return false; } @@ -260,15 +294,16 @@ public class ColumnValues { @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( table != null ? table.hashCode() : 0 ); result = 31 * result + ( unique ? 1 : 0 ); result = 31 * result + ( nullable ? 1 : 0 ); result = 31 * result + ( insertable ? 1 : 0 ); result = 31 * result + ( updatable ? 1 : 0 ); - result = 31 * result + ( columnDefinition != null ? columnDefinition.hashCode() : 0 ); - result = 31 * result + ( table != null ? table.hashCode() : 0 ); result = 31 * result + length; result = 31 * result + precision; result = 31 * result + scale; + result = 31 * result + ( columnDefinition != null ? columnDefinition.hashCode() : 0 ); + result = 31 * result + ( referencedColumnName != null ? referencedColumnName.hashCode() : 0 ); return result; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/FormulaValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/FormulaValue.java new file mode 100644 index 0000000000..e3e67ea313 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/FormulaValue.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +/** + * @author Strong Liu + */ +public class FormulaValue { + private final String tableName; + private final String expression; + + public FormulaValue(String tableName, String expression) { + this.tableName = tableName; + this.expression = expression; + } + + public String getExpression() { + return expression; + } + + public String getContainingTableName() { + return tableName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java new file mode 100644 index 0000000000..a0c8b797b6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java @@ -0,0 +1,338 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * Base class for the different types of mapped attributes + * + * @author Hardy Ferentschik + */ +public abstract class MappedAttribute implements Comparable { + /** + * Annotations defined on the attribute, keyed against the annotation dot name. + */ + private final Map> annotations; + + /** + * The property name. + */ + private final String name; + + /** + * The java type of the attribute + */ + private final Class attributeType; + + /** + * The nature of the attribute + */ + private final Nature attributeNature; + + /** + * The access type for this property. At the moment this is either 'field' or 'property', but Hibernate + * also allows custom named accessors (see {@link org.hibernate.property.PropertyAccessorFactory}). + */ + private final String accessType; + + /** + * Defines the column values (relational values) for this property. A mapped property can refer to multiple + * column values in case of components or join columns etc + */ + private final List columnValues = new ArrayList(); + + /** + * Is this a formula property ( annotated w/ {@code Formula}). + */ + private final FormulaValue formulaValue; + + + /** + * Is this property an id property (or part thereof). + */ + private final boolean isId; + + /** + * Is this property a natural id property and what's the mutability it is. + */ + private SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + + /** + * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic + * locking). + */ + private final boolean isOptimisticLockable; + + /** + * Contains the SQL check condition specified via {@link org.hibernate.annotations.Check} or null if no annotation + * is specified. + */ + private final String checkCondition; + + /** + * FQN of the attribute. + */ + private final String role; + + /** + * The binding context + */ + private final EntityBindingContext context; + + MappedAttribute(String name, + Class attributeType, + Nature attributeNature, + String accessType, + Map> annotations, + EntityBindingContext context + ) { + this.context = context; + this.annotations = annotations; + this.name = name; + this.attributeType = attributeType; + this.attributeNature = attributeNature; + this.accessType = accessType; + + //if this attribute has either @Id or @EmbeddedId, then it is an id attribute + AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); + AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.EMBEDDED_ID + ); + this.isId = ( idAnnotation != null || embeddedIdAnnotation != null ); + + this.isOptimisticLockable = checkOptimisticLockAnnotation(); + this.checkCondition = checkCheckAnnotation(); + this.naturalIdMutability = AnnotationParserHelper.checkNaturalId( annotations ); + this.role = context.getOrigin().getName() + "#" + name; + checkColumnAnnotations( annotations ); + this.formulaValue = checkFormulaValueAnnotation(); + + } + + public String getName() { + return name; + } + + public String getRole(){ + return role; + } + + public final Class getAttributeType() { + return attributeType; + } + + public String getAccessType() { + return accessType; + } + + public EntityBindingContext getContext() { + return context; + } + + public Map> annotations() { + return annotations; + } + + public List getColumnValues() { + return columnValues; + } + + public boolean isId() { + return isId; + } + + public boolean isOptimisticLockable() { + return isOptimisticLockable; + } + + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + this.naturalIdMutability = naturalIdMutability; + } + + public Nature getNature() { + return attributeNature; + } + + public String getCheckCondition() { + return checkCondition; + } + + public FormulaValue getFormulaValue() { + return formulaValue; + } + + @Override + public int compareTo(MappedAttribute mappedProperty) { + return name.compareTo( mappedProperty.getName() ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "MappedAttribute" ); + sb.append( "{name='" ).append( getRole() ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + public abstract AttributeTypeResolver getHibernateTypeResolver(); + + public abstract boolean isLazy(); + + public abstract boolean isOptional(); + + public abstract boolean isInsertable(); + + public abstract boolean isUpdatable(); + + public abstract PropertyGeneration getPropertyGeneration(); + + private boolean checkOptimisticLockAnnotation() { + boolean triggersVersionIncrement = true; + AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.OPTIMISTIC_LOCK + ); + if ( optimisticLockAnnotation != null ) { + boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean(); + triggersVersionIncrement = !exclude; + } + return triggersVersionIncrement; + } + + private FormulaValue checkFormulaValueAnnotation() { + AnnotationInstance formulaAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.FORMULA + ); + if ( formulaAnnotation != null ) { + if ( !getColumnValues().isEmpty() ) { + throw new AnnotationException( "Can't having both @Formula and @Column on same attribute : " + getRole() ); + } + final String expression = JandexHelper.getValue( formulaAnnotation, "value", String.class, + context.getServiceRegistry().getService( ClassLoaderService.class )); + if ( StringHelper.isEmpty( expression ) ) { + throw new AnnotationException( + String.format( + "Formula expression defined on %s can't be empty string", + getRole() + ) + ); + } + return new FormulaValue( null, expression ); + } + return null; + } + private void checkColumnAnnotations(Map> annotations) { + // single @Column + AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.COLUMN + ); + if ( columnAnnotation != null ) { + checkWrongColumnAnnotationLocation(); + columnValues.add( new Column( columnAnnotation ) ); + } + + // @org.hibernate.annotations.Columns + AnnotationInstance columnsAnnotation = JandexHelper.getSingleAnnotation( + annotations, + HibernateDotNames.COLUMNS + ); + if ( columnsAnnotation != null ) { + checkWrongColumnAnnotationLocation(); + List columnsList = Arrays.asList( + JandexHelper.getValue( columnsAnnotation, "columns", AnnotationInstance[].class, + context.getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + for ( AnnotationInstance annotation : columnsList ) { + columnValues.add( new Column( annotation ) ); + } + } + } + + private void checkWrongColumnAnnotationLocation() { + if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { + throw getContext().makeMappingException( + "@Column(s) not allowed on a " + getNature() + " property: " + getRole() + ); + } + } + + private String checkCheckAnnotation() { + final AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK ); + return checkAnnotation != null ? checkAnnotation.value( "constraints" ).toString() : null; + } + + /** + * An enum defining the type of a mapped attribute. + */ + public static enum Nature { + BASIC( JPADotNames.BASIC ), + ONE_TO_ONE( JPADotNames.ONE_TO_ONE ), + ONE_TO_MANY( JPADotNames.ONE_TO_MANY ), + MANY_TO_ONE( JPADotNames.MANY_TO_ONE ), + MANY_TO_MANY( JPADotNames.MANY_TO_MANY ), + MANY_TO_ANY( HibernateDotNames.MANY_TO_ANY ), + ELEMENT_COLLECTION_BASIC( JPADotNames.ELEMENT_COLLECTION ), + ELEMENT_COLLECTION_EMBEDDABLE( JPADotNames.ELEMENT_COLLECTION ), + EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), + EMBEDDED( JPADotNames.EMBEDDED ); + + private final DotName annotationDotName; + + Nature(DotName annotationDotName) { + this.annotationDotName = annotationDotName; + } + + public DotName getAnnotationDotName() { + return annotationDotName; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java new file mode 100644 index 0000000000..59b733146d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java @@ -0,0 +1,594 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; + +import javax.persistence.FetchType; + +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.LazyCollectionOption; +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.annotations.SortType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.EnumeratedTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.LobTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.attribute.type.TemporalTypeResolver; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Represents an collection (collection, list, set, map) association attribute. + * + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class PluralAssociationAttribute extends AssociationAttribute { + private final Class indexType; + private final String whereClause; + private final String orderBy; + private final boolean sorted; + private final String comparatorName; + private final Caching caching; + private final String customPersister; + private final String customLoaderName; + private final CustomSQL customInsert; + private final CustomSQL customUpdate; + private final CustomSQL customDelete; + private final CustomSQL customDeleteAll; + private final ClassInfo entityClassInfo; + private final boolean isExtraLazy; + private final OnDeleteAction onDeleteAction; + private final boolean isSequentiallyIndexed; + // Used for the non-owning side of a ManyToMany relationship + private final String inverseForeignKeyName; + private final String explicitForeignKeyName; + + private final PluralAttributeSource.Nature pluralAttributeNature; + + private static final EnumSet SHOULD_NOT_HAS_COLLECTION_ID = EnumSet.of( PluralAttributeSource.Nature.SET, + PluralAttributeSource.Nature.MAP, PluralAttributeSource.Nature.LIST, PluralAttributeSource.Nature.ARRAY ); + + private LazyCollectionOption lazyOption; + private final boolean isCollectionIdPresent; + private final boolean mutable; + private final int batchSize; + + private AttributeTypeResolver elementTypeResolver; + private AttributeTypeResolver indexTypeResolver; + + public static PluralAssociationAttribute createPluralAssociationAttribute( + ClassInfo entityClassInfo, + String name, + Class attributeType, + Class indexType, + Class referencedAttributeType, + Nature attributeNature, + String accessType, + Map> annotations, + EntityBindingContext context) { + return new PluralAssociationAttribute( + entityClassInfo, + name, + attributeType, + indexType, + referencedAttributeType, + attributeNature, + accessType, + annotations, + context + ); + } + + public PluralAttributeSource.Nature getPluralAttributeNature() { + return pluralAttributeNature; + } + + public Class getIndexType() { + return indexType; + } + + public String getWhereClause() { + return whereClause; + } + + public String getOrderBy() { + return orderBy; + } + + public String getInverseForeignKeyName() { + return inverseForeignKeyName; + } + public String getExplicitForeignKeyName(){ + return explicitForeignKeyName; + } + + public Caching getCaching() { + return caching; + } + + public String getCustomPersister() { + return customPersister; + } + + public String getCustomLoaderName() { + return customLoaderName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public CustomSQL getCustomDeleteAll() { + return customDeleteAll; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "PluralAssociationAttribute" ); + sb.append( "{name='" ).append( getName() ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; + } + + public String getComparatorName() { + return comparatorName; + } + + public boolean isSorted() { + return sorted; + } + + public boolean isSequentiallyIndexed() { + return isSequentiallyIndexed; + } + + private PluralAssociationAttribute( + final ClassInfo entityClassInfo, + final String name, + final Class attributeType, + final Class indexType, + final Class referencedAttributeType, + final Nature associationType, + final String accessType, + final Map> annotations, + final EntityBindingContext context) { + super( entityClassInfo, name, attributeType, referencedAttributeType, associationType, accessType, annotations, context ); + this.entityClassInfo = entityClassInfo; + this.indexType = indexType; + this.whereClause = determineWereClause(); + this.orderBy = determineOrderBy(); + + AnnotationInstance foreignKey = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.FOREIGN_KEY + ); + if ( foreignKey != null ) { + explicitForeignKeyName = JandexHelper.getValue( foreignKey, "name", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + String temp = JandexHelper.getValue( foreignKey, "inverseName", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + inverseForeignKeyName = StringHelper.isNotEmpty( temp ) ? temp : null; + } + else { + explicitForeignKeyName = null; + inverseForeignKeyName = null; + } + + this.mutable = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.IMMUTABLE ) == null; + + this.caching = determineCachingSettings(); + this.isExtraLazy = lazyOption == LazyCollectionOption.EXTRA; + this.customPersister = determineCustomPersister(); + this.customLoaderName = determineCustomLoaderName(); + this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_INSERT, annotations() + ); + this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_UPDATE, annotations() + ); + this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_DELETE, annotations() + ); + this.customDeleteAll = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_DELETE_ALL, annotations() + ); + this.onDeleteAction = determineOnDeleteAction(); + this.isCollectionIdPresent = JandexHelper.getSingleAnnotation( + annotations, + HibernateDotNames.COLLECTION_ID + ) != null; + final AnnotationInstance sortAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.SORT ); + final AnnotationInstance sortNaturalAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.SORT_NATURAL ); + final AnnotationInstance sortComparatorAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.SORT_COMPARATOR ); + + if ( sortNaturalAnnotation != null ) { + this.sorted = true; + this.comparatorName = "natural"; + } + else if ( sortComparatorAnnotation != null ) { + this.sorted = true; + this.comparatorName = JandexHelper.getValue( sortComparatorAnnotation, "value", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + else if ( sortAnnotation != null ) { + final SortType sortType = JandexHelper.getEnumValue( sortAnnotation, "type", SortType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + switch ( sortType ){ + + case NATURAL: + this.sorted = true; + this.comparatorName = "natural"; + break; + case COMPARATOR: + String comparatorName = JandexHelper.getValue( sortAnnotation, "comparator", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + if ( StringHelper.isEmpty( comparatorName ) ) { + throw new MappingException( + "Comparator class must be provided when using SortType.COMPARATOR on property: " + getRole(), + getContext().getOrigin() + ); + } + this.sorted = true; + this.comparatorName = comparatorName; + break; + default: + this.sorted = false; + this.comparatorName = null; + break; + } + } + else { + this.sorted = false; + this.comparatorName = null; + } + + + AnnotationInstance orderColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ORDER_COLUMN ); + AnnotationInstance indexColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.INDEX_COLUMN ); + if ( orderColumnAnnotation != null && indexColumnAnnotation != null ) { + throw new MappingException( + "@OrderColumn and @IndexColumn can't be used together on property: " + getRole(), + getContext().getOrigin() + ); + } + this.isSequentiallyIndexed = orderColumnAnnotation != null || indexColumnAnnotation != null; + this.pluralAttributeNature = resolvePluralAttributeNature(); + + AnnotationInstance batchAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.BATCH_SIZE ); + if ( batchAnnotation != null ) { + this.batchSize = batchAnnotation.value( "size" ).asInt(); + } + else { + this.batchSize = -1; + } + validateMapping(); + } + + private void validateMapping() { + checkSortedTypeIsSortable(); + checkIfCollectionIdIsWronglyPlaced(); + } + + private void checkIfCollectionIdIsWronglyPlaced() { + if ( isCollectionIdPresent && SHOULD_NOT_HAS_COLLECTION_ID.contains( pluralAttributeNature ) ) { + throw new MappingException( + "The Collection type doesn't support @CollectionId annotation: " + getRole(), + getContext().getOrigin() + ); + } + } + + private void checkSortedTypeIsSortable() { + //shortcut, a little performance improvement of avoiding the class type check + if ( pluralAttributeNature == PluralAttributeSource.Nature.MAP + || pluralAttributeNature == PluralAttributeSource.Nature.SET ) { + if ( SortedMap.class.isAssignableFrom( getAttributeType() ) + || SortedSet.class.isAssignableFrom( getAttributeType() ) ) { + if ( !isSorted() ) { + throw new MappingException( + "A sorted collection has to define @Sort: " + getRole(), + getContext().getOrigin() + ); + } + } + } + + } + + + //TODO org.hibernate.cfg.annotations.CollectionBinder#hasToBeSorted + private PluralAttributeSource.Nature resolvePluralAttributeNature() { + + if ( Map.class.isAssignableFrom( getAttributeType() ) ) { + return PluralAttributeSource.Nature.MAP; + } + else if ( List.class.isAssignableFrom( getAttributeType() ) ) { + if ( isSequentiallyIndexed() ) { + return PluralAttributeSource.Nature.LIST; + } + else if ( isCollectionIdPresent ) { + return PluralAttributeSource.Nature.ID_BAG; + } + else { + return PluralAttributeSource.Nature.BAG; + } + } + else if ( Set.class.isAssignableFrom( getAttributeType() ) ) { + return PluralAttributeSource.Nature.SET; + } + else if ( getAttributeType().isArray() ) { + return PluralAttributeSource.Nature.ARRAY; + } + else if ( Collection.class.isAssignableFrom( getAttributeType() ) ) { + return isCollectionIdPresent ? PluralAttributeSource.Nature.ID_BAG : PluralAttributeSource.Nature.BAG; + } + else { + return PluralAttributeSource.Nature.BAG; + } + } + + //todo duplicated with the one in EntityClass + private OnDeleteAction determineOnDeleteAction() { + final AnnotationInstance onDeleteAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.ON_DELETE + ); + if ( onDeleteAnnotation != null ) { + return JandexHelper.getEnumValue( onDeleteAnnotation, "action", OnDeleteAction.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + return null; + } + + @Override + public boolean isOptimisticLockable() { + return hasOptimisticLockAnnotation() ? super.isOptimisticLockable() : StringHelper.isEmpty( getMappedBy() ); + } + + public int getBatchSize() { + return batchSize; + } + + private String determineCustomLoaderName() { + String loader = null; + final AnnotationInstance customLoaderAnnotation = JandexHelper.getSingleAnnotation( + annotations(), HibernateDotNames.LOADER + ); + if ( customLoaderAnnotation != null ) { + loader = JandexHelper.getValue( customLoaderAnnotation, "namedQuery", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + return loader; + } + + private String determineCustomPersister() { + String entityPersisterClass = null; + final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( + annotations(), HibernateDotNames.PERSISTER + ); + if ( persisterAnnotation != null ) { + entityPersisterClass = JandexHelper.getValue( persisterAnnotation, "impl", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + return entityPersisterClass; + } + + @Override + protected boolean determineIsLazy(AnnotationInstance associationAnnotation) { + FetchType fetchType = JandexHelper.getEnumValue( associationAnnotation, "fetch", FetchType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + boolean lazy = fetchType == FetchType.LAZY; + final AnnotationInstance lazyCollectionAnnotationInstance = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.LAZY_COLLECTION + ); + if ( lazyCollectionAnnotationInstance != null ) { + lazyOption = JandexHelper.getEnumValue( + lazyCollectionAnnotationInstance, + "value", + LazyCollectionOption.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + lazy = !( lazyOption == LazyCollectionOption.FALSE ); + + } + final AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.FETCH + ); + if ( fetchAnnotation != null && fetchAnnotation.value() != null ) { + FetchMode fetchMode = FetchMode.valueOf( fetchAnnotation.value( ).asEnum().toUpperCase() ); + if ( fetchMode == FetchMode.JOIN ) { + lazy = false; + } + } + return lazy; + } + + public boolean isExtraLazy() { + return isExtraLazy; + } + + private String determineWereClause() { + String where = null; + + AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.WHERE ); + if ( whereAnnotation != null ) { + where = JandexHelper.getValue( whereAnnotation, "clause", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + return where; + } + + private String determineOrderBy() { + String orderBy = null; + + AnnotationInstance hibernateOrderByAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.ORDER_BY + ); + + AnnotationInstance jpaOrderByAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + JPADotNames.ORDER_BY + ); + + if ( jpaOrderByAnnotation != null && hibernateOrderByAnnotation != null ) { + throw new MappingException( + "Cannot use sql order by clause (@org.hibernate.annotations.OrderBy) " + + "in conjunction with JPA order by clause (@java.persistence.OrderBy) on " + getRole(), + getContext().getOrigin() + ); + } + + if ( hibernateOrderByAnnotation != null ) { + orderBy = JandexHelper.getValue( hibernateOrderByAnnotation, "clause", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + if ( jpaOrderByAnnotation != null ) { + // this could be an empty string according to JPA spec 11.1.38 - + // If the ordering element is not specified for an entity association, ordering by the primary key of the + // associated entity is assumed + // The binder will need to take this into account and generate the right property names + orderBy = JandexHelper.getValue( jpaOrderByAnnotation, "value", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + if ( orderBy == null ) { + orderBy = isBasicCollection() ? "$element$ asc" :"id asc" ; + } + if ( orderBy.equalsIgnoreCase( "desc" ) ) { + orderBy = isBasicCollection() ? "$element$ desc" :"id desc"; + } + } + + return orderBy; + } + + private boolean isBasicCollection(){ + return getNature() == Nature.ELEMENT_COLLECTION_BASIC || getNature() == Nature.ELEMENT_COLLECTION_EMBEDDABLE; + } + + private Caching determineCachingSettings() { + Caching caching = null; + final AnnotationInstance hibernateCacheAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.CACHE + ); + if ( hibernateCacheAnnotation != null ) { + org.hibernate.cache.spi.access.AccessType accessType; + if ( hibernateCacheAnnotation.value( "usage" ) == null ) { + accessType = getContext().getMappingDefaults().getCacheAccessType(); + } + else { + accessType = CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() ) + .toAccessType(); + } + + return new Caching( + hibernateCacheAnnotation.value( "region" ) == null + ? StringHelper.qualify( entityClassInfo.name().toString(), getName() ) + : hibernateCacheAnnotation.value( "region" ).asString(), + accessType, + hibernateCacheAnnotation.value( "include" ) != null + && "all".equals( hibernateCacheAnnotation.value( "include" ).asString() ) + ); + } + return caching; + } + + + public boolean isMutable() { + return mutable; + } + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + if ( elementTypeResolver == null ) { + elementTypeResolver = getDefaultElementHibernateTypeResolver(); + } + return elementTypeResolver; + } + + private AttributeTypeResolver getDefaultElementHibernateTypeResolver() { + CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this ); + resolver.addHibernateTypeResolver( HibernateTypeResolver.createCollectionElementTypeResolver( this ) ); + resolver.addHibernateTypeResolver( TemporalTypeResolver.createCollectionElementTypeResolver( this ) ); + resolver.addHibernateTypeResolver( LobTypeResolver.createCollectionElementTypeResolve( this ) ); + resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createCollectionElementTypeResolver( this ) ); + return resolver; + } + + public AttributeTypeResolver getIndexTypeResolver() { + if ( indexType == null ) { + return getDefaultHibernateTypeResolver(); + } + else if ( indexTypeResolver == null ) { + CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this ); + final String name = getName() + ".index"; + resolver.addHibernateTypeResolver( HibernateTypeResolver.createCollectionIndexTypeResolver( this ) ); + // TODO: Lob allowed as collection index? I don't see an annotation for that. + resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createCollectionIndexTypeResolver( this ) ); + resolver.addHibernateTypeResolver( TemporalTypeResolver.createCollectionIndexTypeResolver( this ) ); + indexTypeResolver = resolver; + } + return indexTypeResolver; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PrimaryKeyJoinColumn.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..78c16cb303 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PrimaryKeyJoinColumn.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Strong Liu + */ +public class PrimaryKeyJoinColumn extends Column { + private String referencedColumnName; + + public PrimaryKeyJoinColumn(AnnotationInstance columnAnnotation) { + super( columnAnnotation ); + } + + @Override + public void applyColumnValues(AnnotationInstance columnAnnotation) { + super.applyColumnValues( columnAnnotation ); + if ( columnAnnotation != null ) { + AnnotationValue nameValue = columnAnnotation.value( "referencedColumnName" ); + if ( nameValue != null ) { + this.referencedColumnName = nameValue.asString(); + } + } + } + + public String getReferencedColumnName() { + return referencedColumnName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SingularAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SingularAssociationAttribute.java new file mode 100644 index 0000000000..4bd3d9215c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SingularAssociationAttribute.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import java.util.List; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; + +/** + * @author Gail Badner + */ +public class SingularAssociationAttribute extends AssociationAttribute { + private final boolean hasPrimaryKeyJoinColumn; + public static AssociationAttribute createSingularAssociationAttribute( + ClassInfo classInfo, + String name, + Class attributeType, + Nature attributeNature, + String accessType, + Map> annotations, + EntityBindingContext context) { + return new SingularAssociationAttribute( + classInfo, + name, + attributeType, + attributeType, + attributeNature, + accessType, + annotations, + context + ); + } + + SingularAssociationAttribute( + ClassInfo classInfo, + String name, + Class attributeType, + Class referencedAttributeType, + Nature attributeNature, + String accessType, + Map> annotations, + EntityBindingContext context) { + super( classInfo, name, attributeType, referencedAttributeType, attributeNature, accessType, annotations, context ); + this.hasPrimaryKeyJoinColumn = + JandexHelper.containsSingleAnnotation( annotations, JPADotNames.PRIMARY_KEY_JOIN_COLUMN ) || + JandexHelper.containsSingleAnnotation( annotations, JPADotNames.PRIMARY_KEY_JOIN_COLUMNS ); + } + + public boolean hasPrimaryKeyJoinColumn() { + return hasPrimaryKeyJoinColumn; + } + + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/package.html new file mode 100755 index 0000000000..6f41661c51 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/package.html @@ -0,0 +1,34 @@ + + + + + +

          + This package contains classes related to mapped attributes and associations of a mapped entity. It also contains the + attribute related source implementations. +

          + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AbstractAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AbstractAttributeTypeResolver.java new file mode 100644 index 0000000000..a051fb9bb5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AbstractAttributeTypeResolver.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.usertype.DynamicParameterizedType; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public abstract class AbstractAttributeTypeResolver implements AttributeTypeResolver { + + private final String name; + private final Class javaClass; + private final AnnotationInstance annotation; + private final EntityBindingContext context; + + public AbstractAttributeTypeResolver( + String name, + Class javaClass, + AnnotationInstance annotation, + EntityBindingContext context){ + this.name = name; + this.javaClass = javaClass; + this.annotation = annotation; + this.context = context; + } + + @Override + final public String getExplicitHibernateTypeName() { + String type = getExplicitAnnotatedHibernateTypeName(); + // If the attribute is annotated with a type, use it. Otherwise, + // check for a @TypeDef. + if ( !StringHelper.isEmpty( type ) ) { + return type; + } else { + return hasTypeDef() ? javaClass().getName() : null; + } + } + + @Override + final public String getExplicitAnnotatedHibernateTypeName() { + return resolveHibernateTypeName(); + } + + @Override + final public Map getExplicitHibernateTypeParameters() { + Map result = new HashMap( ); + //this is only use by enum type and serializable blob type, but we put there anyway + // TODO: why? + //result.put( + // DynamicParameterizedType.RETURNED_CLASS, + // javaClass().getName() + //); + if ( StringHelper.isNotEmpty( getExplicitHibernateTypeName() ) ) { + result.putAll( resolveHibernateTypeParameters() ); + } + return result; + } + + final protected boolean hasTypeDef() { + return context.getMetadataImplementor().hasTypeDefinition( + javaClass().getName() + ); + } + + protected abstract String resolveHibernateTypeName(); + + protected Map resolveHibernateTypeParameters() { + return Collections.emptyMap(); + } + + protected String name() { + return name; + } + + protected Class javaClass() { + return javaClass; + } + + protected AnnotationInstance annotation() { + return annotation; + } + + protected static AnnotationInstance resolveAnnotationInstance( + Map> annotations, + DotName dotName) { + return JandexHelper.getSingleAnnotation( + annotations, + dotName + ); + } + + protected EntityBindingContext getContext() { + return context; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AttributeTypeResolver.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AttributeTypeResolver.java index 7333c64109..5ccc76f769 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/AttributeTypeResolver.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute.type; +package org.hibernate.metamodel.internal.source.annotations.attribute.type; import java.util.Map; @@ -35,12 +35,25 @@ import java.util.Map; */ public interface AttributeTypeResolver { /** - * @return returns an explicit hibernate type name in case the mapped attribute has an additional + * @return Returns an explicit hibernate type name in case the mapped attribute has an additional * {@link org.hibernate.annotations.Type} annotation or an implicit type is given via the use of annotations like * {@link javax.persistence.Lob}, {@link javax.persistence.Enumerated} and - * {@link javax.persistence.Temporal}. + * {@link javax.persistence.Temporal}. If no annotated types are + * available, checks for type definitions in + * {@link javax.persistence.TypeDefs}. Returns null if none of the + * above are found. */ String getExplicitHibernateTypeName(); + + /** + * @return Returns the same type name as + * {@link #getExplicitHibernateTypeName}, but skips the + * {@link javax.persistence.TypeDefs} check. This is mainly for + * {@link CompositeAttributeTypeResolver}, as it needs to check the + * {@link javax.persistence.TypeDefs} only once at the very end if nothing + * is returned by the list of resolvers. + */ + String getExplicitAnnotatedHibernateTypeName(); /** * @return Returns a map of optional type parameters. See {@link #getExplicitHibernateTypeName()}. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/CompositeAttributeTypeResolver.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/CompositeAttributeTypeResolver.java index 26c36ff4ba..8f3e5aeaa0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/CompositeAttributeTypeResolver.java @@ -22,28 +22,32 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute.type; +package org.hibernate.metamodel.internal.source.annotations.attribute.type; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; /** * @author Strong Liu + * @author Brett Meyer */ public class CompositeAttributeTypeResolver implements AttributeTypeResolver { + private final MappedAttribute mappedAttribute; private List resolvers = new ArrayList(); - private final AttributeTypeResolverImpl explicitHibernateTypeResolver; + private AttributeTypeResolver theResolver; - public CompositeAttributeTypeResolver(AttributeTypeResolverImpl explicitHibernateTypeResolver) { - if ( explicitHibernateTypeResolver == null ) { - throw new AssertionFailure( "The Given AttributeTypeResolver is null." ); - } - this.explicitHibernateTypeResolver = explicitHibernateTypeResolver; + public CompositeAttributeTypeResolver(MappedAttribute mappedAttribute, + AttributeTypeResolver... resolvers) { + this.mappedAttribute = mappedAttribute; + this.resolvers.addAll( Arrays.asList( resolvers ) ); } public void addHibernateTypeResolver(AttributeTypeResolver resolver) { @@ -55,29 +59,47 @@ public class CompositeAttributeTypeResolver implements AttributeTypeResolver { @Override public String getExplicitHibernateTypeName() { - String type = explicitHibernateTypeResolver.getExplicitHibernateTypeName(); - if ( StringHelper.isEmpty( type ) ) { - for ( AttributeTypeResolver resolver : resolvers ) { - type = resolver.getExplicitHibernateTypeName(); - if ( StringHelper.isNotEmpty( type ) ) { - break; - } + String type = getExplicitAnnotatedHibernateTypeName(); + if ( StringHelper.isNotEmpty( type ) ) { + return type; + } + else if ( mappedAttribute.getContext() + .getMetadataImplementor().hasTypeDefinition( + mappedAttribute.getAttributeType().getName() + ) ) { + return mappedAttribute.getAttributeType().getName(); + } + else { + return null; + } + } + + @Override + public String getExplicitAnnotatedHibernateTypeName() { + if ( theResolver != null ) { + return theResolver.getExplicitAnnotatedHibernateTypeName(); + } + for ( AttributeTypeResolver resolver : resolvers ) { + String type = resolver.getExplicitAnnotatedHibernateTypeName(); + if ( StringHelper.isNotEmpty( type ) ) { + theResolver = resolver; + return type; } } - return type; + return null; } @Override public Map getExplicitHibernateTypeParameters() { - Map parameters = explicitHibernateTypeResolver.getExplicitHibernateTypeParameters(); - if ( CollectionHelper.isEmpty( parameters ) ) { - for ( AttributeTypeResolver resolver : resolvers ) { - parameters = resolver.getExplicitHibernateTypeParameters(); - if ( CollectionHelper.isNotEmpty( parameters ) ) { - break; - } + if ( theResolver != null ) { + return theResolver.getExplicitHibernateTypeParameters(); + } + for ( AttributeTypeResolver resolver : resolvers ) { + Map parameters = resolver.getExplicitHibernateTypeParameters(); + if ( CollectionHelper.isNotEmpty( parameters ) ) { + return parameters; } } - return parameters; + return Collections.EMPTY_MAP; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/EnumeratedTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/EnumeratedTypeResolver.java new file mode 100644 index 0000000000..28bd701e35 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/EnumeratedTypeResolver.java @@ -0,0 +1,141 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.attribute.type; + +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.type.EnumType; +import org.hibernate.usertype.DynamicParameterizedType; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class EnumeratedTypeResolver extends AbstractAttributeTypeResolver { + private final boolean isEnum; + private final javax.persistence.EnumType enumType; + + public static EnumeratedTypeResolver createAttributeTypeResolver(MappedAttribute attribute) { + return new EnumeratedTypeResolver( + attribute.getName(), + attribute.getAttributeType(), + resolveAnnotationInstance( attribute.annotations(),JPADotNames.ENUMERATED ), + attribute.getContext() + ); + } + + public static EnumeratedTypeResolver createCollectionElementTypeResolver( + PluralAssociationAttribute pluralAssociationAttribute) { + return new EnumeratedTypeResolver( + pluralAssociationAttribute.getName(), + pluralAssociationAttribute.getReferencedAttributeType(), + resolveAnnotationInstance( pluralAssociationAttribute.annotations(),JPADotNames.ENUMERATED ), + pluralAssociationAttribute.getContext() + ); + } + + public static EnumeratedTypeResolver createCollectionIndexTypeResolver( + PluralAssociationAttribute pluralAssociationAttribute) { + return new EnumeratedTypeResolver( + pluralAssociationAttribute.getName(), + pluralAssociationAttribute.getIndexType(), + resolveAnnotationInstance( pluralAssociationAttribute.annotations(), JPADotNames.MAP_KEY_ENUMERATED ), + pluralAssociationAttribute.getContext() + ); + } + + private EnumeratedTypeResolver( + String name, + Class javaClass, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaClass, annotation, context ); + this.isEnum = javaClass().isEnum(); + this.enumType = annotation == null ? + null : + JandexHelper.getEnumValue( annotation, "value", javax.persistence.EnumType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + @Override + public String resolveHibernateTypeName() { + if ( annotation() != null ) { + if ( isEnum ) { + return EnumType.class.getName(); + } else { + throw new AnnotationException( + String.format( + "Attribute %s is not a Enumerated type, but has %s or %s annotation.", + name(), + JPADotNames.ENUMERATED, + JPADotNames.MAP_KEY_ENUMERATED + ) + ); + } + } + else if ( !hasTypeDef() && isEnum ) { + return EnumType.class.getName(); + } + return null; + } + + @Override + protected Map resolveHibernateTypeParameters() { + HashMap typeParameters = new HashMap(); + + if ( enumType != null ) { + typeParameters.put(EnumType.ENUM, javaClass().getName() ); + if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) { + typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); + typeParameters.put( EnumType.NAMED, String.valueOf( false ) ); + } + else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) { + typeParameters.put( EnumType.TYPE, String.valueOf( Types.VARCHAR ) ); + typeParameters.put( EnumType.NAMED, String.valueOf( true ) ); + } + else { + throw new AssertionFailure( "Unknown EnumType: " + enumType ); + } + } + else { + typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); + } + typeParameters.put( DynamicParameterizedType.RETURNED_CLASS, javaClass().getName() ); + return typeParameters; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/HibernateTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/HibernateTypeResolver.java new file mode 100644 index 0000000000..0fd25df22e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/HibernateTypeResolver.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.usertype.DynamicParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * Type Resolver which checks {@link org.hibernate.annotations.Type} to find the type info. + * + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class HibernateTypeResolver extends AbstractAttributeTypeResolver { + private final String typeName; + + public static HibernateTypeResolver createAttributeTypeResolver(MappedAttribute attribute) { + return new HibernateTypeResolver( + attribute.getName(), + attribute.getAttributeType(), + resolveAnnotationInstance( attribute.annotations(), HibernateDotNames.TYPE ), + attribute.getContext() + ); + } + + public static HibernateTypeResolver createCollectionElementTypeResolver( + PluralAssociationAttribute pluralAssociationAttribute) { + return new HibernateTypeResolver( + pluralAssociationAttribute.getName(), + pluralAssociationAttribute.getReferencedAttributeType(), + resolveAnnotationInstance( pluralAssociationAttribute.annotations(), HibernateDotNames.TYPE ), + pluralAssociationAttribute.getContext() + ); + } + + public static HibernateTypeResolver createCollectionIndexTypeResolver( + PluralAssociationAttribute pluralAssociationAttribute) { + final AnnotationInstance annotation = resolveAnnotationInstance( + pluralAssociationAttribute.annotations(), + HibernateDotNames.MAP_KEY_TYPE + ); + final AnnotationInstance typeAnnotation = annotation == null ? + null : + JandexHelper.getValue( annotation, "value", AnnotationInstance.class, + pluralAssociationAttribute.getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + return new HibernateTypeResolver( + pluralAssociationAttribute.getName(), + pluralAssociationAttribute.getIndexType(), + typeAnnotation, + pluralAssociationAttribute.getContext() + ); + } + + private HibernateTypeResolver( + String name, + Class javaClass, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaClass, annotation, context ); + this.typeName = + annotation() == null ? + null : + JandexHelper.getValue( annotation(), "type", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + + } + + @Override + protected String resolveHibernateTypeName() { + return typeName; + } + + @Override + protected Map resolveHibernateTypeParameters() { + if ( annotation() != null ) { + AnnotationValue parameterAnnotationValue = annotation().value( "parameters" ); + if ( parameterAnnotationValue != null ) { + AnnotationInstance[] parameterAnnotations = parameterAnnotationValue.asNestedArray(); + final HashMap typeParameters = new HashMap( parameterAnnotations.length ); + for ( AnnotationInstance parameterAnnotationInstance : parameterAnnotations ) { + typeParameters.put( + JandexHelper.getValue( parameterAnnotationInstance, "name", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ), + JandexHelper.getValue( parameterAnnotationInstance, "value", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + return typeParameters; + } + else if ( typeName != null && !hasTypeDef() ) { + try { + final Class typeClass = + getContext().getServiceRegistry().getService( ClassLoaderService.class ).classForName( typeName ); + if ( DynamicParameterizedType.class.isAssignableFrom( typeClass ) ) { + return Collections.singletonMap( + DynamicParameterizedType.RETURNED_CLASS, + javaClass().getName() + ); + } + } + catch (ClassLoadingException ex ) { + // ignore + } + } + } + + return Collections.emptyMap(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/LobTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/LobTypeResolver.java new file mode 100644 index 0000000000..9551b3c0f2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/LobTypeResolver.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.attribute.type; + +import java.io.Serializable; +import java.sql.Blob; +import java.sql.Clob; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; + +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.type.CharacterArrayClobType; +import org.hibernate.type.PrimitiveCharacterArrayClobType; +import org.hibernate.type.SerializableToBlobType; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.WrappedMaterializedBlobType; +import org.hibernate.usertype.DynamicParameterizedType; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class LobTypeResolver extends AbstractAttributeTypeResolver { + public static LobTypeResolver createAttributeTypeResolve(MappedAttribute attribute) { + return new LobTypeResolver( + attribute.getName(), + attribute.getAttributeType(), + resolveAnnotationInstance( attribute.annotations(), JPADotNames.LOB ), + attribute.getContext() + ); + } + + public static LobTypeResolver createCollectionElementTypeResolve(PluralAssociationAttribute pluralAssociationAttribute) { + return new LobTypeResolver( + pluralAssociationAttribute.getName(), + pluralAssociationAttribute.getReferencedAttributeType(), + resolveAnnotationInstance( pluralAssociationAttribute.annotations(), JPADotNames.LOB ), + pluralAssociationAttribute.getContext() + ); + } + + private LobTypeResolver(String name, + Class javaClass, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaClass, annotation, context ); + } + + @Override + public String resolveHibernateTypeName() { + if ( annotation() == null ) { + //only check attributes annotated with @Lob + return null; + } + String type = "blob"; + if ( Clob.class.isAssignableFrom( javaClass() ) ) { + type = StandardBasicTypes.CLOB.getName(); + } + else if ( Blob.class.isAssignableFrom( javaClass() ) ) { + type = StandardBasicTypes.BLOB.getName(); + } + else if ( String.class.isAssignableFrom( javaClass() ) ) { + type = StandardBasicTypes.MATERIALIZED_CLOB.getName(); + } + else if ( Character[].class.isAssignableFrom( javaClass() ) ) { + type = CharacterArrayClobType.class.getName(); + } + else if ( char[].class.isAssignableFrom( javaClass() ) ) { + type = PrimitiveCharacterArrayClobType.class.getName(); + } + else if ( Byte[].class.isAssignableFrom( javaClass() ) ) { + type = WrappedMaterializedBlobType.class.getName(); + } + else if ( byte[].class.isAssignableFrom( javaClass() ) ) { + type = StandardBasicTypes.MATERIALIZED_BLOB.getName(); + } + else if ( Serializable.class.isAssignableFrom( javaClass() ) ) { + type = SerializableToBlobType.class.getName(); + } + return type; + } + + protected Map resolveHibernateTypeParameters() { + if ( SerializableToBlobType.class.getName().equals( getExplicitHibernateTypeName() ) ) { + return Collections.singletonMap( SerializableToBlobType.CLASS_NAME, javaClass().getName() ); + } + else { + return super.resolveHibernateTypeParameters(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/TemporalTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/TemporalTypeResolver.java new file mode 100644 index 0000000000..57a8878873 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/TemporalTypeResolver.java @@ -0,0 +1,158 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.attribute.type; + +import java.sql.Time; +import java.util.Calendar; +import java.util.Date; + +import javax.persistence.TemporalType; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.annotations.SourceType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.type.StandardBasicTypes; +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class TemporalTypeResolver extends AbstractAttributeTypeResolver { + private final SourceType versionSourceType; + + public static TemporalTypeResolver createAttributeTypeResolver(BasicAttribute attribute) { + return new TemporalTypeResolver( + attribute.getName(), + attribute.getAttributeType(), + resolveAnnotationInstance( attribute.annotations(), JPADotNames.TEMPORAL ), + attribute.getContext(), + attribute.isVersioned() ? attribute.getVersionSourceType() : null + ); + } + + public static TemporalTypeResolver createCollectionElementTypeResolver(PluralAssociationAttribute attribute) { + return new TemporalTypeResolver( + attribute.getName(), + attribute.getReferencedAttributeType(), + resolveAnnotationInstance( attribute.annotations(), JPADotNames.TEMPORAL ), + attribute.getContext(), + null + ); + } + + public static TemporalTypeResolver createCollectionIndexTypeResolver(PluralAssociationAttribute attribute) { + return new TemporalTypeResolver( + attribute.getName(), + attribute.getIndexType(), + resolveAnnotationInstance( attribute.annotations(), JPADotNames.MAP_KEY_TEMPORAL ), + attribute.getContext(), + null + ); + } + private TemporalTypeResolver(String name, + Class javaClass, + AnnotationInstance annotation, + EntityBindingContext context, + SourceType versionSourceType) { + super( name, javaClass, annotation, context ); + this.versionSourceType = versionSourceType; + } + + @Override + public String resolveHibernateTypeName() { + Class attributeType = javaClass(); + + if ( isTemporalType( attributeType ) ) { + if (versionSourceType != null ) { + return versionSourceType.typeName(); + } + if ( annotation() == null ) { + // Although JPA 2.1 states that @Temporal is required on + // Date/Calendar attributes, allow it to be left off in order + // to support legacy mappings. + // java.util.Date -> TimestampType + // java.sql.Timestamp -> TimestampType + // java.sql.Date -> DateType + // java.sql.Time -> TimeType + // java.util.Calendar -> CalendarType + if ( java.sql.Date.class.isAssignableFrom( attributeType ) ) { + return StandardBasicTypes.DATE.getName(); + } else if ( Time.class.isAssignableFrom( attributeType ) ) { + return StandardBasicTypes.TIME.getName(); + } else if ( Calendar.class.isAssignableFrom( attributeType ) ) { + return StandardBasicTypes.CALENDAR.getName(); + } else { + return StandardBasicTypes.TIMESTAMP.getName(); + } + } else { + final TemporalType temporalType = JandexHelper.getEnumValue( + annotation(), + "value", + TemporalType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + final boolean isDate = Date.class.isAssignableFrom( attributeType ); + String type; + switch ( temporalType ) { + case DATE: + type = isDate ? StandardBasicTypes.DATE.getName() : StandardBasicTypes.CALENDAR_DATE.getName(); + break; + case TIME: + type = StandardBasicTypes.TIME.getName(); + if ( !isDate ) { + throw new NotYetImplementedException( "Calendar cannot persist TIME only" ); + } + break; + case TIMESTAMP: + type = isDate ? StandardBasicTypes.TIMESTAMP.getName() : StandardBasicTypes.CALENDAR.getName(); + break; + default: + throw new AssertionFailure( "Unknown temporal type: " + temporalType ); + } + return type; + } + } else { + if ( annotation() != null ) { + throw new AnnotationException( + "@Temporal should only be set on a java.util.Date or java.util.Calendar property: " + name() + ); + } + } + return null; + } + + private static boolean isTemporalType(Class type) { + return Date.class.isAssignableFrom( type ) || Calendar.class.isAssignableFrom( type ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/package.html new file mode 100755 index 0000000000..bff34d014c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/type/package.html @@ -0,0 +1,33 @@ + + + + + +

          + This package contains classes to resolve explicit Hibernate type information for mapped attributes. +

          + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java new file mode 100644 index 0000000000..01bab955a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java @@ -0,0 +1,841 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import javax.persistence.AccessType; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability; +import org.hibernate.metamodel.spi.source.MappingException; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.members.ResolvedMember; + +/** + * Base class for a configured entity, mapped super class or embeddable + * + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class ConfiguredClass { + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AssertionFailure.class.getName()); + + /** + * The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy. + */ + private final ConfiguredClass parent; + + /** + * The Jandex class info for this configured class. Provides access to the annotation defined on this configured class. + */ + private final ClassInfo classInfo; + + /** + * The actual java type. + */ + private final Class clazz; + + /** + * Is this class abstract? + */ + private final boolean isAbstract; + + /** + * The default access type for this entity + */ + private final AccessType classAccessType; + + /** + * The generically resolved type + */ + private final ResolvedTypeWithMembers genericResolvedType; + + /** + * The id attributes + */ + private final Map idAttributeMap; + + /** + * The mapped association attributes for this entity + */ + private final Map associationAttributeMap; + + /** + * The mapped simple attributes for this entity + */ + private final Map simpleAttributeMap; + + /** + * The version attribute or {@code null} in case none exists. + */ + private BasicAttribute versionAttribute; + + /** + * The embedded classes for this entity + */ + private final Map embeddedClasses + = new HashMap(); + + /** + * The collection element embedded classes for this entity + */ + private final Map collectionEmbeddedClasses + = new HashMap(); + + private final Map attributeOverrideMap =new HashMap( ); + private final Map associationOverrideMap = new HashMap( ); + + private final Set transientFieldNames = new HashSet(); + private final Set transientMethodNames = new HashSet(); + + /** + * Fully qualified name of a custom tuplizer + */ + private final String customTuplizer; + + private final EntityBindingContext localBindingContext; + /** + * + */ + private final String contextPath; + + public ConfiguredClass( + final ClassInfo classInfo, + final ResolvedTypeWithMembers fullyResolvedType, + final AccessType defaultAccessType, + final ConfiguredClass parent, + final AnnotationBindingContext context) { + this(classInfo, fullyResolvedType, defaultAccessType, parent, "",context ); + } + + + public ConfiguredClass( + final ClassInfo classInfo, + final ResolvedTypeWithMembers fullyResolvedType, + final AccessType defaultAccessType, + final ConfiguredClass parent, + final String contextPath, + final AnnotationBindingContext context) { + this.parent = parent; + this.classInfo = classInfo; + this.contextPath = contextPath; + this.clazz = context.locateClassByName( classInfo.toString() ); + this.genericResolvedType = fullyResolvedType; + this.localBindingContext = new EntityBindingContext( context, this ); + this.isAbstract = ReflectHelper.isAbstractClass( this.clazz ); + this.classAccessType = determineClassAccessType( defaultAccessType ); + this.customTuplizer = AnnotationParserHelper.determineCustomTuplizer( classInfo.annotations(), classInfo, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + this.simpleAttributeMap = new TreeMap(); + this.idAttributeMap = new TreeMap(); + this.associationAttributeMap = new TreeMap(); + collectAttributeOverrides(); + collectAssociationOverrides(); + + collectAttributes(); + + } + + public String getName() { + return clazz.getName(); + } + + public Class getConfiguredClass() { + return clazz; + } + + public ClassInfo getClassInfo() { + return classInfo; + } + + public ConfiguredClass getParent() { + return parent; + } + + public boolean isAbstract() { + return isAbstract; + } + + public EntityBindingContext getLocalBindingContext() { + return localBindingContext; + } + + public boolean hostsAnnotation(DotName annotationName) { + List annotationList = classInfo.annotations().get( annotationName ); + return CollectionHelper.isNotEmpty( annotationList ); + } + + public Map getSimpleAttributes() { + return simpleAttributeMap; + } + + public boolean isIdAttribute(String attributeName) { + return idAttributeMap.containsKey( attributeName ); + } + + public Map getIdAttributes() { + return idAttributeMap; + } + + public BasicAttribute getVersionAttribute() { + return versionAttribute; + } + + public Map getAssociationAttributes() { + return associationAttributeMap; + } + + public Map getEmbeddedClasses() { + return embeddedClasses; + } + + public Map getCollectionEmbeddedClasses() { + return collectionEmbeddedClasses; + } + + private final ValueHolder> attributeOverrideMapHolder = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + Map map = new HashMap(); + for ( EmbeddableClass embeddableClass : getEmbeddedClasses().values() ) { + map.putAll( embeddableClass.getAttributeOverrideMap() ); + } + for(EmbeddableClass embeddableClass : getCollectionEmbeddedClasses().values()){ + map.putAll( embeddableClass.getAttributeOverrideMap() ); + } + map.putAll( attributeOverrideMap ); + return map; + } + } + ); + + public Map getAttributeOverrideMap() { + return attributeOverrideMapHolder.getValue(); + } + + private final ValueHolder> associationOverrideMapHolder = new ValueHolder>( new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + Map map = new HashMap( ); + for ( EmbeddableClass embeddableClass : getEmbeddedClasses().values() ) { + map.putAll( embeddableClass.getAssociationOverrideMap() ); + } + for(EmbeddableClass embeddableClass : getCollectionEmbeddedClasses().values()){ + map.putAll( embeddableClass.getAssociationOverrideMap() ); + } + map.putAll( associationOverrideMap ); + return map; + } + } ); + + public Map getAssociationOverrideMap() { + return associationOverrideMapHolder.getValue(); + } + + public AccessType getClassAccessType() { + return classAccessType; + } + + public String getCustomTuplizer() { + return customTuplizer; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "ConfiguredClass" ); + sb.append( "{clazz=" ).append( clazz.getSimpleName() ); + sb.append( '}' ); + return sb.toString(); + } + + private AccessType determineClassAccessType(AccessType defaultAccessType) { + // default to the hierarchy access type to start with + AccessType accessType = defaultAccessType; + + AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( + classInfo, + JPADotNames.ACCESS, + ClassInfo.class + ); + if ( accessAnnotation != null ) { + accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + } else { + accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, HibernateDotNames.ACCESS_TYPE, ClassInfo.class ); + if ( accessAnnotation != null ) { + accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() ); + } + } + + return accessType; + } + + /** + * Find all attributes for this configured class and add them to the corresponding map + */ + private void collectAttributes() { + // find transient field and method names + findTransientFieldAndMethodNames(); + + + final Set explicitlyConfiguredMemberNames = createExplicitlyConfiguredAccessProperties( ); + + if ( AccessType.FIELD.equals( classAccessType ) ) { + Field fields[] = clazz.getDeclaredFields(); + Field.setAccessible( fields, true ); + for ( Field field : fields ) { + if ( AnnotationParserHelper.isPersistentMember( + transientFieldNames, + explicitlyConfiguredMemberNames, + field + ) ) { + createMappedAttribute( field, AccessType.FIELD ); + } + } + } + else { + Method[] methods = clazz.getDeclaredMethods(); + Method.setAccessible( methods, true ); + for ( Method method : methods ) { + if ( AnnotationParserHelper.isPersistentMember( + transientMethodNames, + explicitlyConfiguredMemberNames, + method + ) ) { + createMappedAttribute( method, AccessType.PROPERTY ); + } + } + } + } + + /** + * Creates {@code MappedProperty} instances for the explicitly configured persistent properties + * + * + * @return the property names of the explicitly configured attribute names in a set + */ + private Set createExplicitlyConfiguredAccessProperties() { + Set explicitAccessPropertyNames = new HashSet(); + + List accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS ); + List hibernateAccessAnnotations = classInfo.annotations().get( HibernateDotNames.ACCESS_TYPE ); + if ( accessAnnotations == null ) { + accessAnnotations = hibernateAccessAnnotations; + if ( accessAnnotations == null ) { + return explicitAccessPropertyNames; + } + } else if ( hibernateAccessAnnotations != null ) { + accessAnnotations.addAll( hibernateAccessAnnotations ); + } + + // iterate over all @Access annotations defined on the current class + for ( AnnotationInstance accessAnnotation : accessAnnotations ) { + // we are only interested at annotations defined on fields and methods + AnnotationTarget annotationTarget = accessAnnotation.target(); + if ( !( annotationTarget.getClass().equals( MethodInfo.class ) || annotationTarget.getClass() + .equals( FieldInfo.class ) ) ) { + continue; + } + + final AccessType accessType; + if ( JPADotNames.ACCESS.equals( accessAnnotation.name() ) ) { + accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ); + } else { + accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() ); + } + + // the placement is correct, get the member + Member member; + if ( annotationTarget instanceof MethodInfo ) { + try { + member = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() ); + } + catch ( NoSuchMethodException e ) { + throw new HibernateException( + "Unable to load method " + + ( ( MethodInfo ) annotationTarget ).name() + + " of class " + clazz.getName() + ); + } + } + else { + try { + member = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() ); + } + catch ( NoSuchFieldException e ) { + throw new HibernateException( + "Unable to load field " + + ( ( FieldInfo ) annotationTarget ).name() + + " of class " + clazz.getName() + ); + } + } + if ( ReflectHelper.isProperty( member ) ) { + createMappedAttribute( member, accessType ); + explicitAccessPropertyNames.add( ReflectHelper.getPropertyName( member ) ); + } + } + return explicitAccessPropertyNames; + } + + private void checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) { + // when the access type of the class is FIELD + // overriding access annotations must be placed on properties AND have the access type PROPERTY + if ( AccessType.FIELD.equals( classAccessType ) ) { + if ( !MethodInfo.class.isInstance( annotationTarget ) ) { + String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnProperty( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); + } + + if ( !AccessType.PROPERTY.equals( accessType ) ) { + String msg = LOG.accessTypeOverrideShouldBeProperty( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); + } + } + + // when the access type of the class is PROPERTY + // overriding access annotations must be placed on fields and have the access type FIELD + if ( AccessType.PROPERTY.equals( classAccessType ) ) { + if ( !FieldInfo.class.isInstance( annotationTarget ) ) { + String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnField( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); + } + + if ( !AccessType.FIELD.equals( accessType ) ) { + String msg = LOG.accessTypeOverrideShouldBeField( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); + } + } + } + + private void createMappedAttribute(Member member, AccessType accessType) { + final String attributeName = ReflectHelper.getPropertyName( member ); + final ResolvedMember[] resolvedMembers = Field.class.isInstance( member ) ? genericResolvedType.getMemberFields() : genericResolvedType + .getMemberMethods(); + ResolvedMember resolvedMember = findResolvedMember( member.getName(), resolvedMembers ); + final Map> annotations = JandexHelper.getMemberAnnotations( + classInfo, member.getName(), localBindingContext.getServiceRegistry() + ); + Class attributeType = resolvedMember.getType().getErasedType(); + Class collectionElementType = AnnotationParserHelper.resolveCollectionElementType( + resolvedMember, + annotations, + getLocalBindingContext() + ); + Class collectionIndexType = null; + if ( Map.class.isAssignableFrom( attributeType ) && !resolvedMember.getType().getTypeParameters().isEmpty()) { + collectionIndexType = resolvedMember.getType().getTypeParameters().get( 0 ).getErasedType(); + } + MappedAttribute.Nature attributeNature = determineAttributeNature( + annotations, attributeType, collectionElementType + ); + String accessTypeString = accessType.toString().toLowerCase(); + switch ( attributeNature ) { + case BASIC: { + BasicAttribute attribute = BasicAttribute.createSimpleAttribute( + attributeName, + attributeType, + attributeNature, + annotations, + accessTypeString, + getLocalBindingContext() + ); + if ( attribute.isId() ) { + idAttributeMap.put( attributeName, attribute ); + } + else if ( attribute.isVersioned() ) { + if ( versionAttribute == null ) { + versionAttribute = attribute; + } + else { + throw new MappingException( "Multiple version attributes", localBindingContext.getOrigin() ); + } + } + else { + simpleAttributeMap.put( attributeName, attribute ); + } + break; + } + case EMBEDDED_ID: { + final BasicAttribute attribute = BasicAttribute.createSimpleAttribute( + attributeName, + attributeType, + attributeNature, + annotations, + accessTypeString, + getLocalBindingContext() + ); + idAttributeMap.put( attributeName, attribute ); + } + case EMBEDDED: { + final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.TARGET + ); + if ( targetAnnotation != null ) { + attributeType = localBindingContext.locateClassByName( + JandexHelper.getValue( targetAnnotation, "value", String.class, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + embeddedClasses.put( attributeName, resolveEmbeddable( + attributeName, attributeType, resolvedMember.getType(), annotations ) ); + break; + } + case ONE_TO_ONE: + case MANY_TO_ONE: { + final AssociationAttribute attribute = SingularAssociationAttribute.createSingularAssociationAttribute( + classInfo, + attributeName, + resolvedMember.getType().getErasedType(), + attributeNature, + accessTypeString, + annotations, + getLocalBindingContext() + ); + if ( attribute.isId() ) { + idAttributeMap.put( attributeName, attribute ); + } + associationAttributeMap.put( attributeName, attribute ); + break; + } + case ELEMENT_COLLECTION_EMBEDDABLE: + collectionEmbeddedClasses.put( attributeName, resolveEmbeddable( + attributeName+".element", collectionElementType,resolvedMember.getType().getTypeBindings().getBoundType( 0 ), annotations ) ); + // fall through + case ELEMENT_COLLECTION_BASIC: + case ONE_TO_MANY: + case MANY_TO_MANY: { + AssociationAttribute attribute = PluralAssociationAttribute.createPluralAssociationAttribute( + classInfo, + attributeName, + resolvedMember.getType().getErasedType(), + collectionIndexType, + collectionElementType, + attributeNature, + accessTypeString, + annotations, + getLocalBindingContext() + ); + associationAttributeMap.put( attributeName, attribute ); + break; + } + case MANY_TO_ANY: {} + } + } + + private EmbeddableClass resolveEmbeddable( + String attributeName, + Class type, + ResolvedType resolvedType, + Map> annotations) { + final ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() ); + if ( embeddableClassInfo == null ) { + final String msg = String.format( + "Attribute '%s#%s' is annotated with @Embedded,\n but '%s' does not seem to be annotated " + + "with @Embeddable.\n Are all annotated classes added to the configuration?", + getConfiguredClass().getName(), + attributeName, + type.getName() + ); + throw new AnnotationException( msg ); + } + + final NaturalIdMutability naturalIdMutability = AnnotationParserHelper.checkNaturalId( annotations ); + //tuplizer on field + final String customTuplizerClass = AnnotationParserHelper.determineCustomTuplizer( annotations, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + + final EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy( + localBindingContext.locateClassByName( embeddableClassInfo.toString() ), + attributeName, + resolvedType, + classAccessType, + naturalIdMutability, + customTuplizerClass, + localBindingContext + ); + return hierarchy.getLeaf(); + } + + /** + * Given the annotations defined on a persistent attribute this methods determines the attribute type. + * + * @param annotations the annotations defined on the persistent attribute + * @param attributeType the attribute's type + * @param referencedCollectionType the type of the collection element in case the attribute is collection valued + * + * @return an instance of the {@code AttributeType} enum + */ + private MappedAttribute.Nature determineAttributeNature( + final Map> annotations, + final Class attributeType, + final Class referencedCollectionType ) { + EnumSet discoveredAttributeTypes = EnumSet.noneOf( MappedAttribute.Nature.class ); + AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ); + if ( oneToOne != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.ONE_TO_ONE ); + } + + AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ); + if ( oneToMany != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.ONE_TO_MANY ); + } + + AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ); + if ( manyToOne != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.MANY_TO_ONE ); + } + + AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ); + if ( manyToMany != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.MANY_TO_MANY ); + } + + AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); + if ( embeddedId != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.EMBEDDED_ID ); + } + AnnotationInstance id = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); + AnnotationInstance embedded = JandexHelper.getSingleAnnotation( + annotations, JPADotNames.EMBEDDED ); + if ( embedded != null ) { + discoveredAttributeTypes.add( MappedAttribute.Nature.EMBEDDED ); + } else if ( embeddedId == null ) { + // For backward compatibility, we're allowing attributes of an + // @Embeddable type to leave off @Embedded. Check the type's + // annotations. (see HHH-7678) + // However, it's important to ignore this if the field is + // annotated with @EmbeddedId. + if ( isEmbeddableType( attributeType ) ) { + LOG.warn( attributeType.getName() + " has @Embeddable on it, but the attribute of this type in entity[" + + getName() + + "] doesn't have @Embedded, which may cause compatibility issue" ); + discoveredAttributeTypes.add( id!=null? MappedAttribute.Nature.EMBEDDED_ID : MappedAttribute.Nature.EMBEDDED ); + } + } + + + + AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.ELEMENT_COLLECTION + ); + if ( elementCollection != null || ( discoveredAttributeTypes.isEmpty() && CollectionHelper.isCollectionOrArray( attributeType ) )) { + boolean isEmbeddable = isEmbeddableType( referencedCollectionType ); + discoveredAttributeTypes.add( isEmbeddable? MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE : MappedAttribute.Nature.ELEMENT_COLLECTION_BASIC ); + } + + int size = discoveredAttributeTypes.size(); + switch ( size ) { + case 0: + return MappedAttribute.Nature.BASIC; + case 1: + return discoveredAttributeTypes.iterator().next(); + default: + throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() ); + } + } + + protected boolean isEmbeddableType(Class referencedCollectionType) { + // class info can be null for types like string, etc where there are no annotations + ClassInfo classInfo = getLocalBindingContext().getIndex().getClassByName( + DotName.createSimple( + referencedCollectionType.getName() + ) + ); + return classInfo != null && CollectionHelper.isNotEmpty( classInfo.annotations().get( JPADotNames.EMBEDDABLE ) ); + } + + private ResolvedMember findResolvedMember(String name, ResolvedMember[] resolvedMembers) { + for ( ResolvedMember resolvedMember : resolvedMembers ) { + if ( resolvedMember.getName().equals( name ) ) { + return resolvedMember; + } + } + throw new AssertionFailure( + String.format( + "Unable to resolve type of attribute %s of class %s", + name, + classInfo.name().toString() + ) + ); + } + + /** + * Populates the sets of transient field and method names. + */ + private void findTransientFieldAndMethodNames() { + List transientMembers = classInfo.annotations().get( JPADotNames.TRANSIENT ); + if ( transientMembers == null ) { + return; + } + + for ( AnnotationInstance transientMember : transientMembers ) { + AnnotationTarget target = transientMember.target(); + if ( target instanceof FieldInfo ) { + transientFieldNames.add( ( ( FieldInfo ) target ).name() ); + } + else if(target instanceof MethodInfo) { + transientMethodNames.add( ( ( MethodInfo ) target ).name() ); + } + else { + throw new MappingException( "@Transient can be only defined on field or property", getLocalBindingContext().getOrigin() ); + } + } + } + + protected void collectAssociationOverrides() { + + // Add all instances of @AssociationOverride + List overrideAnnotations = JandexHelper + .getAnnotations( classInfo, JPADotNames.ASSOCIATION_OVERRIDE ); + if ( overrideAnnotations != null ) { + for ( AnnotationInstance annotation : overrideAnnotations ) { + AssociationOverride override = new AssociationOverride( + createPathPrefix( annotation.target() ), annotation, localBindingContext + ); + associationOverrideMap.put( + override.getAttributePath(), override + ); + } + } + + // Add all instances of @AssociationOverrides children + List overridesAnnotations = JandexHelper + .getAnnotations( classInfo, JPADotNames.ASSOCIATION_OVERRIDES ); + if ( overridesAnnotations != null ) { + for ( AnnotationInstance attributeOverridesAnnotation : overridesAnnotations ) { + AnnotationInstance[] annotationInstances + = attributeOverridesAnnotation.value().asNestedArray(); + for ( AnnotationInstance annotation : annotationInstances ) { + AssociationOverride override = new AssociationOverride( + createPathPrefix( + attributeOverridesAnnotation.target() + ), + annotation, + localBindingContext + ); + associationOverrideMap.put( + override.getAttributePath(), override + ); + } + } + } + } + + protected void collectAttributeOverrides() { + + // Add all instances of @AttributeOverride + List attributeOverrideAnnotations = JandexHelper + .getAnnotations(classInfo, JPADotNames.ATTRIBUTE_OVERRIDE ); + if ( attributeOverrideAnnotations != null ) { + for ( AnnotationInstance annotation : attributeOverrideAnnotations ) { + AttributeOverride override = new AttributeOverride( + createPathPrefix( annotation.target() ), annotation, localBindingContext ); + attributeOverrideMap.put( + override.getAttributePath(), override + ); + } + } + + // Add all instances of @AttributeOverrides children + List attributeOverridesAnnotations = JandexHelper + .getAnnotations(classInfo, JPADotNames.ATTRIBUTE_OVERRIDES); + if ( attributeOverridesAnnotations != null ) { + for ( AnnotationInstance attributeOverridesAnnotation : attributeOverridesAnnotations ) { + AnnotationInstance[] annotationInstances + = attributeOverridesAnnotation.value().asNestedArray(); + for ( AnnotationInstance annotation : annotationInstances ) { + AttributeOverride override = new AttributeOverride( + createPathPrefix( + attributeOverridesAnnotation.target() ), + annotation, + localBindingContext ); + attributeOverrideMap.put( + override.getAttributePath(), override + ); + } + } + } + } + + protected String createPathPrefix(AnnotationTarget target) { + if ( target instanceof FieldInfo || target instanceof MethodInfo ) { + String path = JandexHelper.getPropertyName( target ); + if( StringHelper.isEmpty( contextPath )){ + return path; + } + return contextPath + "." + path; + } + return contextPath; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableClass.java new file mode 100644 index 0000000000..fa3cc5b154 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableClass.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.AccessType; + +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; + +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +/** + * Represents the information about an entity annotated with {@code @Embeddable}. + * + * @author Hardy Ferentschik + */ +public class EmbeddableClass extends ConfiguredClass { + private final String embeddedAttributeName; + private final String parentReferencingAttributeName; + //custom tuplizer defined on the embedded field + private final String customTuplizerClass; + private SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + + public EmbeddableClass( + ClassInfo classInfo, + ResolvedTypeWithMembers fullyResolvedType, + String embeddedAttributeName, + ConfiguredClass parent, + AccessType defaultAccessType, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + String customTuplizerClass, + AnnotationBindingContext context) { + super( classInfo, fullyResolvedType, defaultAccessType, parent, embeddedAttributeName, context ); + this.embeddedAttributeName = embeddedAttributeName; + this.naturalIdMutability = naturalIdMutability; + this.parentReferencingAttributeName = checkParentAnnotation(); + this.customTuplizerClass = customTuplizerClass; + + overrideNaturalIdMutability(naturalIdMutability); + } + + private void overrideNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + for ( BasicAttribute attribute : getSimpleAttributes().values() ) { + attribute.setNaturalIdMutability( naturalIdMutability ); + } + for ( EmbeddableClass embeddable : getEmbeddedClasses().values() ) { + embeddable.setNaturalIdMutability( naturalIdMutability ); + embeddable.overrideNaturalIdMutability( naturalIdMutability ); + } + for ( AssociationAttribute associationAttribute : getAssociationAttributes().values() ) { + associationAttribute.setNaturalIdMutability( naturalIdMutability ); + } + } + + private String checkParentAnnotation() { + AnnotationInstance parentAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.PARENT + ); + return parentAnnotation == null? null : JandexHelper.getPropertyName( parentAnnotation.target() ); + } + + public String getEmbeddedAttributeName() { + return embeddedAttributeName; + } + + public String getParentReferencingAttributeName() { + return parentReferencingAttributeName; + } + + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + this.naturalIdMutability = naturalIdMutability; + } + + public String getCustomTuplizerClass() { + return customTuplizerClass; + } + + +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableHierarchy.java similarity index 61% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableHierarchy.java index 41f46f489c..ae6953f3e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableHierarchy.java @@ -21,21 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.persistence.AccessType; -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.ClassmateHelper; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; + +import static org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability; + /** * Contains information about the access and inheritance type for all classes within a class hierarchy. * @@ -44,7 +50,6 @@ import org.jboss.jandex.DotName; public class EmbeddableHierarchy implements Iterable { private final AccessType defaultAccessType; private final List embeddables; - /** * Builds the configured class hierarchy for a an embeddable class. * @@ -55,18 +60,46 @@ public class EmbeddableHierarchy implements Iterable { * * @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity. */ - public static EmbeddableHierarchy createEmbeddableHierarchy(Class embeddableClass, String propertyName, AccessType accessType, AnnotationBindingContext context) { + public static EmbeddableHierarchy createEmbeddableHierarchy( + final Class embeddableClass, + final String propertyName, + final ResolvedType resolvedType, + final AccessType accessType, + final NaturalIdMutability naturalIdMutability, + final String customTuplizerClass, + final AnnotationBindingContext context) { - ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() ); - if ( embeddableClassInfo == null ) { - throw new AssertionFailure( - String.format( - "The specified class %s cannot be found in the annotation index", - embeddableClass.getName() - ) - ); + final ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() ); + checkIndexed( embeddableClass, embeddableClassInfo ); + checkEmbeddableAnnotation( embeddableClass, embeddableClassInfo ); + Map resolvedTypeWithMembers = ClassmateHelper.resolveClassHierarchyTypesFromAttributeType( + embeddableClass, + resolvedType, + context + ); + List classInfoList = new ArrayList(); + Class clazz = embeddableClass; + while ( clazz != null && !clazz.equals( Object.class ) ) { + ClassInfo tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) ); + if ( tmpClassInfo == null ) { + continue; + } + clazz = clazz.getSuperclass(); + classInfoList.add( 0, tmpClassInfo ); } + return new EmbeddableHierarchy( + classInfoList, + resolvedTypeWithMembers, + propertyName, + naturalIdMutability, + customTuplizerClass, + context, + accessType + ); + } + + private static void checkEmbeddableAnnotation(Class embeddableClass, ClassInfo embeddableClassInfo) { if ( JandexHelper.getSingleAnnotation( embeddableClassInfo, JPADotNames.EMBEDDABLE ) == null ) { throw new AssertionFailure( String.format( @@ -75,45 +108,46 @@ public class EmbeddableHierarchy implements Iterable { ) ); } + } - List classInfoList = new ArrayList(); - ClassInfo tmpClassInfo; - Class clazz = embeddableClass; - while ( clazz != null && !clazz.equals( Object.class ) ) { - tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) ); - clazz = clazz.getSuperclass(); - if ( tmpClassInfo == null ) { - continue; - } - - classInfoList.add( 0, tmpClassInfo ); + private static void checkIndexed(Class embeddableClass, ClassInfo embeddableClassInfo) { + if ( embeddableClassInfo == null ) { + throw new AssertionFailure( + String.format( + "The specified class %s cannot be found in the annotation index", + embeddableClass.getName() + ) + ); } - - return new EmbeddableHierarchy( - classInfoList, - propertyName, - context, - accessType - ); } @SuppressWarnings("unchecked") private EmbeddableHierarchy( - List classInfoList, - String propertyName, - AnnotationBindingContext context, - AccessType defaultAccessType) { + final List classInfoList, + final Map resolvedTypeWithMembers, + final String propertyName, + final NaturalIdMutability naturalIdMutability, + final String customTuplizerClass, + final AnnotationBindingContext context, + final AccessType defaultAccessType) { this.defaultAccessType = defaultAccessType; - // the resolved type for the top level class in the hierarchy - context.resolveAllTypes( classInfoList.get( classInfoList.size() - 1 ).name().toString() ); - - embeddables = new ArrayList(); + this.embeddables = new ArrayList(); ConfiguredClass parent = null; - EmbeddableClass embeddable; for ( ClassInfo info : classInfoList ) { - embeddable = new EmbeddableClass( - info, propertyName, parent, defaultAccessType, context + ResolvedTypeWithMembers fullyResolvedType = resolvedTypeWithMembers.get( info.toString() ); + if ( fullyResolvedType == null ) { + throw new AssertionFailure( "Unable to find resolved type information for " + info.toString() ); + } + EmbeddableClass embeddable = new EmbeddableClass( + info, + fullyResolvedType, + propertyName, + parent, + defaultAccessType, + naturalIdMutability, + customTuplizerClass, + context ); embeddables.add( embeddable ); parent = embeddable; @@ -128,6 +162,7 @@ public class EmbeddableHierarchy implements Iterable { /** * @return An iterator iterating in top down manner over the configured classes in this hierarchy. */ + @Override public Iterator iterator() { return embeddables.iterator(); } @@ -148,4 +183,6 @@ public class EmbeddableHierarchy implements Iterable { sb.append( '}' ); return sb.toString(); } + + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityBindingContext.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityBindingContext.java index 70c0b2f07e..3b9601c96c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityBindingContext.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,24 +21,25 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MappingDefaults; +import org.hibernate.metamodel.spi.source.MappingException; import org.hibernate.service.ServiceRegistry; - import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.MemberResolver; +import com.fasterxml.classmate.TypeResolver; /** * Annotation version of a local binding context. @@ -59,6 +60,16 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind return origin; } + @Override + public MappingException makeMappingException(String message) { + return new MappingException( message, getOrigin() ); + } + + @Override + public MappingException makeMappingException(String message, Exception cause) { + return new MappingException( message, cause, getOrigin() ); + } + @Override public ServiceRegistry getServiceRegistry() { return contextDelegate.getServiceRegistry(); @@ -105,7 +116,7 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind } @Override - public Index getIndex() { + public IndexView getIndex() { return contextDelegate.getIndex(); } @@ -115,17 +126,17 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind } @Override - public void resolveAllTypes(String className) { - contextDelegate.resolveAllTypes( className ); + public MemberResolver getMemberResolver() { + return contextDelegate.getMemberResolver(); } @Override - public ResolvedType getResolvedType(Class clazz) { - return contextDelegate.getResolvedType( clazz ); + public TypeResolver getTypeResolver() { + return contextDelegate.getTypeResolver(); } @Override - public ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type) { - return contextDelegate.resolveMemberTypes( type ); + public IdentifierGeneratorDefinition findIdGenerator(String name) { + return contextDelegate.findIdGenerator( name ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java new file mode 100644 index 0000000000..696a891060 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java @@ -0,0 +1,594 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.persistence.AccessType; + +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.annotations.OptimisticLockType; +import org.hibernate.annotations.PolymorphismType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPAListenerHelper; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +import com.fasterxml.classmate.ResolvedTypeWithMembers; + +/** + * Represents an entity or mapped superclass configured via annotations/orm-xml. + * + * @author Hardy Ferentschik + */ +public class EntityClass extends ConfiguredClass { + private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId"; + + private final InheritanceType inheritanceType; + + private final String explicitEntityName; + private final String customLoaderQueryName; + private final String[] synchronizedTableNames; + private final int batchSize; + + private boolean isImmutable; + private boolean isExplicitPolymorphism; + private OptimisticLockStyle optimisticLockStyle; + private String whereClause; + private String rowId; + private Caching caching; + private Caching naturalIdCaching; + private boolean isDynamicInsert; + private boolean isDynamicUpdate; + private boolean isSelectBeforeUpdate; + private String customPersister; + + private final CustomSQL customInsert; + private final CustomSQL customUpdate; + private final CustomSQL customDelete; + + + private final String inverseForeignKeyName; + private final String explicitForeignKeyName; + + private final OnDeleteAction onDeleteAction; + + private boolean isLazy; + private String proxy; + + private String discriminatorMatchValue; + + private List jpaCallbacks; + private final List joinedSubclassPrimaryKeyJoinColumnSources; + + /** + * Constructor used for entities within a hierarchy (non entity roots) + * + * @param classInfo the jandex class info this this entity + * @param parent the parent entity + * @param hierarchyAccessType the default access type + * @param inheritanceType the inheritance type this entity + * @param context the binding context + */ + public EntityClass( + ClassInfo classInfo, + ResolvedTypeWithMembers fullyResolvedType, + EntityClass parent, + AccessType hierarchyAccessType, + InheritanceType inheritanceType, + AnnotationBindingContext context) { + super( classInfo, fullyResolvedType, hierarchyAccessType, parent, context ); + this.inheritanceType = inheritanceType; + + this.explicitEntityName = determineExplicitEntityName(); + this.customLoaderQueryName = determineCustomLoader(); + this.synchronizedTableNames = determineSynchronizedTableNames(); + this.batchSize = determineBatchSize(); + + this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_INSERT, + getClassInfo().annotations(), + getClassInfo() + ); + this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_UPDATE, + getClassInfo().annotations(), + getClassInfo() + ); + this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_DELETE, + getClassInfo().annotations(), + getClassInfo() + ); + + + processHibernateEntitySpecificAnnotations(); + processProxyGeneration(); + processDiscriminatorValue(); + + AnnotationInstance foreignKey = JandexHelper.getSingleAnnotation( + classInfo, + HibernateDotNames.FOREIGN_KEY, + ClassInfo.class + ); + this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns(); + if ( foreignKey != null ) { + ensureJoinedSubEntity(); + explicitForeignKeyName = JandexHelper.getValue( foreignKey, "name", String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + String temp = JandexHelper.getValue( foreignKey, "inverseName", String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + inverseForeignKeyName = StringHelper.isNotEmpty( temp ) ? temp : null; + } + else { + explicitForeignKeyName = null; + inverseForeignKeyName = null; + } + this.onDeleteAction = determineOnDeleteAction(); + + } + + private OnDeleteAction determineOnDeleteAction() { + final AnnotationInstance onDeleteAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.ON_DELETE, + ClassInfo.class + ); + if ( onDeleteAnnotation != null ) { + ensureJoinedSubEntity(); + return JandexHelper.getEnumValue( onDeleteAnnotation, "action", OnDeleteAction.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + return null; + } + + private void ensureJoinedSubEntity() { + if ( !( getParent() != null && inheritanceType == InheritanceType.JOINED ) ) { + throw getLocalBindingContext().makeMappingException( explicitEntityName + "is not a joined sub entity" ); + } + } + + public boolean isExplicitPolymorphism() { + return isExplicitPolymorphism; + } + + public boolean isMutable() { + return !isImmutable; + } + + public OptimisticLockStyle getOptimisticLockStyle() { + return optimisticLockStyle; + } + + public String getWhereClause() { + return whereClause; + } + + public String getRowId() { + return rowId; + } + + public Caching getCaching() { + return caching; + } + + public Caching getNaturalIdCaching() { + return naturalIdCaching; + } + + public String getExplicitEntityName() { + return explicitEntityName; + } + + public String getEntityName() { + return getConfiguredClass().getSimpleName(); + } + + public boolean isDynamicInsert() { + return isDynamicInsert; + } + + public boolean isDynamicUpdate() { + return isDynamicUpdate; + } + + public boolean isSelectBeforeUpdate() { + return isSelectBeforeUpdate; + } + + public String getCustomLoaderQueryName() { + return customLoaderQueryName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public String[] getSynchronizedTableNames() { + return synchronizedTableNames; + } + + public List getJoinedSubclassPrimaryKeyJoinColumnSources() { + return joinedSubclassPrimaryKeyJoinColumnSources; + } + + public String getCustomPersister() { + return customPersister; + } + + public boolean isLazy() { + return isLazy; + } + + public String getProxy() { + return proxy; + } + + public int getBatchSize() { + return batchSize; + } + + public boolean isEntityRoot() { + return getParent() == null; + } + + public String getDiscriminatorMatchValue() { + return discriminatorMatchValue; + } + + public List getJpaCallbacks() { + if ( jpaCallbacks == null ) { + jpaCallbacks = new JPAListenerHelper( this ).bindJPAListeners(); + } + return jpaCallbacks; + } + + public String getInverseForeignKeyName() { + return inverseForeignKeyName; + } + public String getExplicitForeignKeyName(){ + return explicitForeignKeyName; + } + public List getMappedSuperclasses() { + return Collections.emptyList(); + } + + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; + } + + public boolean definesItsOwnTable() { + return !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) || isEntityRoot(); + } + + private String determineExplicitEntityName() { + final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.ENTITY + ); + return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + protected List determinePrimaryKeyJoinColumns() { + final AnnotationInstance primaryKeyJoinColumns = JandexHelper.getSingleAnnotation( + getClassInfo(), + JPADotNames.PRIMARY_KEY_JOIN_COLUMNS, + ClassInfo.class + ); + final AnnotationInstance primaryKeyJoinColumn = JandexHelper.getSingleAnnotation( + getClassInfo(), + JPADotNames.PRIMARY_KEY_JOIN_COLUMN, + ClassInfo.class + ); + + if ( primaryKeyJoinColumn != null || primaryKeyJoinColumns != null ) { + ensureJoinedSubEntity(); + } + + final List results; + if ( primaryKeyJoinColumns != null ) { + AnnotationInstance[] values = primaryKeyJoinColumns.value().asNestedArray(); + results = new ArrayList( values.length ); + for ( final AnnotationInstance annotationInstance : values ) { + results.add( new PrimaryKeyJoinColumn( annotationInstance ) ); + } + } + else if ( primaryKeyJoinColumn != null ) { + results = new ArrayList( 1 ); + results.add( new PrimaryKeyJoinColumn( primaryKeyJoinColumn ) ); + } + else { + results = null; + } + return results; + } + + + private void processDiscriminatorValue() { + final AnnotationInstance discriminatorValueAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.DISCRIMINATOR_VALUE + ); + if ( discriminatorValueAnnotation != null ) { + this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); + } + } + + private void processHibernateEntitySpecificAnnotations() { + // see HHH-6400 + PolymorphismType polymorphism = PolymorphismType.IMPLICIT; + final AnnotationInstance polymorphismAnnotation = JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.POLYMORPHISM ); + if ( polymorphismAnnotation != null && polymorphismAnnotation.value( "type" ) != null ) { + polymorphism = PolymorphismType.valueOf( polymorphismAnnotation.value( "type" ).asEnum() ); + } + isExplicitPolymorphism = polymorphism == PolymorphismType.EXPLICIT; + + // see HHH-6401 + OptimisticLockType optimisticLockType = OptimisticLockType.VERSION; + final AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.OPTIMISTIC_LOCK, + ClassInfo.class + ); + if ( optimisticLockAnnotation != null ) { + optimisticLockType = JandexHelper.getEnumValue( + optimisticLockAnnotation, + "type", + OptimisticLockType.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + } + optimisticLockStyle = OptimisticLockStyle.valueOf( optimisticLockType.name() ); + + final AnnotationInstance hibernateImmutableAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.IMMUTABLE, + ClassInfo.class + ); + isImmutable = hibernateImmutableAnnotation != null ; + final AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.WHERE + ); + whereClause = whereAnnotation != null && whereAnnotation.value( "clause" ) != null ? + whereAnnotation.value( "clause" ).asString() : null; + + final AnnotationInstance rowIdAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.ROW_ID + ); + rowId = rowIdAnnotation != null && rowIdAnnotation.value() != null + ? rowIdAnnotation.value().asString() : null; + + caching = determineCachingSettings(); + + naturalIdCaching = determineNaturalIdCachingSettings( caching ); + + // see HHH-6397 + final AnnotationInstance dynamicInsertAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.DYNAMIC_INSERT + ); + if ( dynamicInsertAnnotation != null ) { + isDynamicInsert = JandexHelper.getValue( dynamicInsertAnnotation, "value", Boolean.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + // see HHH-6398 + final AnnotationInstance dynamicUpdateAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.DYNAMIC_UPDATE + ); + if ( dynamicUpdateAnnotation != null ) { + isDynamicUpdate = JandexHelper.getValue( dynamicUpdateAnnotation, "value", Boolean.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + + // see HHH-6399 + final AnnotationInstance selectBeforeUpdateAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.SELECT_BEFORE_UPDATE + ); + if ( selectBeforeUpdateAnnotation != null ) { + isSelectBeforeUpdate = JandexHelper.getValue( selectBeforeUpdateAnnotation, "value", Boolean.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + // Custom persister + String entityPersisterClass = null; + final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.PERSISTER, ClassInfo.class + ); + if ( persisterAnnotation != null && persisterAnnotation.value( "impl" ) != null ) { + entityPersisterClass = persisterAnnotation.value( "impl" ).asString(); + } + this.customPersister = entityPersisterClass; + } + + private Caching determineNaturalIdCachingSettings(final Caching entityCache) { + final AnnotationInstance naturalIdCacheAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.NATURAL_ID_CACHE + ); + if ( naturalIdCacheAnnotation == null ) { + return null; + } + final String region; + if ( naturalIdCacheAnnotation.value( "region" ) == null || StringHelper.isEmpty( + naturalIdCacheAnnotation.value( + "region" + ).asString() + ) ) { + region = entityCache == null ? getEntityName() + NATURAL_ID_CACHE_SUFFIX : entityCache.getRegion() + NATURAL_ID_CACHE_SUFFIX; + } + else { + region = naturalIdCacheAnnotation.value( "region" ).asString(); + } + return new Caching( region, null, false ); + } + + private Caching determineCachingSettings() { + final List annotationInstanceList = getClassInfo().annotations().get( HibernateDotNames.CACHE ); + if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) { + for ( final AnnotationInstance hibernateCacheAnnotation : annotationInstanceList ) { + if ( ClassInfo.class.isInstance( hibernateCacheAnnotation.target() ) ) { + final org.hibernate.cache.spi.access.AccessType accessType = hibernateCacheAnnotation.value( "usage" ) == null + ? getLocalBindingContext().getMappingDefaults().getCacheAccessType() + : CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() ) + .toAccessType(); + return new Caching( + hibernateCacheAnnotation.value( "region" ) == null + ? getName() + : hibernateCacheAnnotation.value( "region" ).asString(), + accessType, + hibernateCacheAnnotation.value( "include" ) != null + && "all".equals( hibernateCacheAnnotation.value( "include" ).asString() ) + ); + } + } + } + + final AnnotationInstance jpaCacheableAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.CACHEABLE + ); + + final boolean doCaching; + switch ( getLocalBindingContext().getMetadataImplementor().getOptions().getSharedCacheMode() ) { + case ALL: { + doCaching = true; + break; + } + case ENABLE_SELECTIVE: { + doCaching = jpaCacheableAnnotation != null + && JandexHelper.getValue( jpaCacheableAnnotation, "value", Boolean.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + break; + } + case DISABLE_SELECTIVE: { + doCaching = jpaCacheableAnnotation == null + || !JandexHelper.getValue( jpaCacheableAnnotation, "value", Boolean.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + break; + } + default: { + // treat both NONE and UNSPECIFIED the same + doCaching = false; + break; + } + } + + if ( !doCaching ) { + return null; + } + + return new Caching( + getName(), + getLocalBindingContext().getMappingDefaults().getCacheAccessType(), + true + ); + } + + public boolean hasMultiTenancySourceInformation() { + return JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.MULTI_TENANT ) != null + || JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.TENANT_COLUMN ) != null + || JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.TENANT_FORMULA ) != null; + } + + private String determineCustomLoader() { + String customLoader = null; + // Custom sql loader + final AnnotationInstance sqlLoaderAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.LOADER + ); + if ( sqlLoaderAnnotation != null && sqlLoaderAnnotation.target() instanceof ClassInfo) { + customLoader = sqlLoaderAnnotation.value( "namedQuery" ).asString(); + } + return customLoader; + } + + private String[] determineSynchronizedTableNames() { + final AnnotationInstance synchronizeAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.SYNCHRONIZE + ); + if ( synchronizeAnnotation != null ) { + return synchronizeAnnotation.value().asStringArray(); + } + else { + return StringHelper.EMPTY_STRINGS; + } + } + + private void processProxyGeneration() { + // Proxy generation + final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.PROXY + ); + if ( hibernateProxyAnnotation != null ) { + isLazy = hibernateProxyAnnotation.value( "lazy" ) == null + || hibernateProxyAnnotation.value( "lazy" ).asBoolean(); + if ( isLazy ) { + final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" ); + proxy = proxyClassValue == null ? getName() : proxyClassValue.asString(); + } + else { + proxy = null; + } + } + else { + isLazy = true; + proxy = getName(); + } + } + + private int determineBatchSize() { + final AnnotationInstance batchSizeAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.BATCH_SIZE + ); + return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt(); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java new file mode 100644 index 0000000000..59a6cfbe10 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +/** + * An enum for the type of id configuration for an entity. + * + * @author Hardy Ferentschik + */ +public enum IdType { + /** + * single @Id annotation. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE} + */ + SIMPLE, + + /** + * multiple @Id annotations. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#NON_AGGREGATED_COMPOSITE} + */ + COMPOSED, + + /** + * Indicates encountered {@code @EmbeddedId} annotation. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE} + */ + // + EMBEDDED, + + /** + * does not contain any identifier mappings + */ + NONE +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclass.java new file mode 100644 index 0000000000..81a2c5d04a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclass.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.AccessType; + +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import org.jboss.jandex.ClassInfo; + +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; + +/** + * Represents the information about an entity annotated with {@code @MappedSuperclass}. + * + * @author Hardy Ferentschik + */ +public class MappedSuperclass extends ConfiguredClass { + /** + * Default constructor + * + * @param classInfo the Jandex {@code ClassInfo} for this mapped superclass + * @param parent the parent class + * @param defaultAccessType the default access type + * @param context context + */ + public MappedSuperclass( + ClassInfo classInfo, + ResolvedTypeWithMembers fullyResolvedType, + ConfiguredClass parent, + AccessType defaultAccessType, + AnnotationBindingContext context) { + super( classInfo, fullyResolvedType, defaultAccessType, parent, context ); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java new file mode 100644 index 0000000000..cab5f86979 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java @@ -0,0 +1,395 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.AccessType; +import javax.persistence.DiscriminatorType; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; +import org.hibernate.metamodel.internal.source.annotations.attribute.FormulaValue; +import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute; +import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; + +import com.fasterxml.classmate.ResolvedTypeWithMembers; + +/** + * Represents an root entity configured via annotations/orm-xml. + * + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class RootEntityClass extends EntityClass { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + RootEntityClass.class.getName() + ); + + private final IdType idType; + private final List mappedSuperclasses= new ArrayList(); + + // discriminator related fields + private Column discriminatorColumnValues; + private FormulaValue discriminatorFormula; + private Class discriminatorType; + + private boolean isDiscriminatorForced = false; + private boolean isDiscriminatorIncludedInSql = true; + private boolean needsDiscriminatorColumn = false; + + + /** + * Constructor used for entity roots + * + * @param classInfo the jandex class info this this entity + * @param mappedSuperclasses a list of class info instances representing the mapped super classes for this root entity + * @param hierarchyAccessType the default access type + * @param inheritanceType the inheritance type this entity + * @param hasSubclasses flag indicating whether this root entity has sub classes + * @param context the binding context + */ + public RootEntityClass( + ClassInfo classInfo, + Map resolvedTypeWithMembers, + List mappedSuperclasses, + AccessType hierarchyAccessType, + InheritanceType inheritanceType, + boolean hasSubclasses, + AnnotationBindingContext context) { + super( classInfo, resolvedTypeWithMembers.get( classInfo.toString() ), null, hierarchyAccessType, inheritanceType, context ); + for ( ClassInfo mappedSuperclassInfo : mappedSuperclasses ) { + MappedSuperclass configuredClass = new MappedSuperclass( + mappedSuperclassInfo, + resolvedTypeWithMembers.get( mappedSuperclassInfo.toString() ), + null, + hierarchyAccessType, + context + ); + this.mappedSuperclasses.add( configuredClass ); + } + if ( InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) { + processDiscriminator(); + this.needsDiscriminatorColumn = hasSubclasses || isDiscriminatorForced; + } + + this.idType = determineIdType(); + } + + public boolean needsDiscriminatorColumn() { + return needsDiscriminatorColumn; + } + + public Column getDiscriminatorColumnValues() { + return discriminatorColumnValues; + } + + public FormulaValue getDiscriminatorFormula() { + return discriminatorFormula; + } + + public Class getDiscriminatorType() { + return discriminatorType; + } + + public List getMappedSuperclasses() { + return mappedSuperclasses; + } + + public IdType getIdType() { + return idType; + } + + public boolean isDiscriminatorForced() { + return isDiscriminatorForced; + } + + public boolean isDiscriminatorIncludedInSql() { + return isDiscriminatorIncludedInSql; + } + + protected List determinePrimaryKeyJoinColumns() { + List results = super.determinePrimaryKeyJoinColumns(); + if ( CollectionHelper.isNotEmpty( results ) ) { + LOG.invalidPrimaryKeyJoinColumnAnnotation(); + } + return null; + } + + private final ValueHolder> simpleAttributes = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + final Map map = new HashMap(); + for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) { + map.putAll( mappedSuperclass.getSimpleAttributes() ); + } + map.putAll( RootEntityClass.super.getSimpleAttributes() ); + return map; + } + } + ); + + @Override + public Map getSimpleAttributes() { + return simpleAttributes.getValue(); + } + + private final ValueHolder> associationAttributes = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + Map map = new HashMap(); + for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) { + map.putAll( mappedSuperclass.getAssociationAttributes() ); + } + map.putAll( RootEntityClass.super.getAssociationAttributes() ); + return map; + } + } + ); + + @Override + public Map getAssociationAttributes() { + return associationAttributes.getValue(); + } + + private final ValueHolder> attributeOverrideMap = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + if ( CollectionHelper.isEmpty( getMappedSuperclasses() ) ) { + return RootEntityClass.super.getAttributeOverrideMap(); + } + Map map = new HashMap(); + for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) { + map.putAll( mappedSuperclass.getAttributeOverrideMap() ); + } + map.putAll( RootEntityClass.super.getAttributeOverrideMap() ); + return map; + } + } + ); + + private final ValueHolder> associationOverrideMap = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + if ( CollectionHelper.isEmpty( getMappedSuperclasses() ) ) { + return RootEntityClass.super.getAssociationOverrideMap(); + } + Map map = new HashMap(); + for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) { + map.putAll( mappedSuperclass.getAssociationOverrideMap() ); + } + map.putAll( RootEntityClass.super.getAssociationOverrideMap() ); + return map; + } + } + ); + + + @Override + public Map getAssociationOverrideMap() { + return associationOverrideMap.getValue(); + } + + @Override + public Map getAttributeOverrideMap() { + return attributeOverrideMap.getValue(); + } + + private final ValueHolder> idAttributes = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + Map attributes = new HashMap(); + + // get all id attributes defined on this entity + attributes.putAll( RootEntityClass.super.getIdAttributes() ); + + // now mapped super classes + for ( MappedSuperclass mappedSuperclass : mappedSuperclasses ) { + attributes.putAll( mappedSuperclass.getIdAttributes() ); + } + + return attributes; + } + } + ); + + public Map getIdAttributes() { + return idAttributes.getValue(); + } + + public AnnotationInstance getIdClassAnnotation() { + // TODO: refactor + final List idClassAnnotations = findIdAnnotations( + JPADotNames.ID_CLASS + ); + + return ( idClassAnnotations.size() > 0 ) ? idClassAnnotations.get( 0 ) : null; + } + + private IdType determineIdType() { + Collection idAttributes = getIdAttributes().values(); + int size = idAttributes.size(); + switch ( size ){ + case 0: + return IdType.NONE; + case 1: + MappedAttribute idAttribute = idAttributes.iterator().next(); + switch ( idAttribute.getNature() ){ + case BASIC: + return IdType.SIMPLE; + case EMBEDDED_ID: + return IdType.EMBEDDED; + } + default: + return IdType.COMPOSED; + } + } + + private List findIdAnnotations(DotName idAnnotationType) { + List idAnnotationList = new ArrayList(); + + // check the class itself + if ( getClassInfo().annotations().containsKey( idAnnotationType ) ) { + idAnnotationList.addAll( getClassInfo().annotations().get( idAnnotationType ) ); + } + + // check mapped super classes + for ( MappedSuperclass mappedSuperclass : mappedSuperclasses ) { + if ( mappedSuperclass.getClassInfo().annotations().containsKey( idAnnotationType ) ) { + idAnnotationList.addAll( mappedSuperclass.getClassInfo().annotations().get( idAnnotationType ) ); + } + } + + return idAnnotationList; + } + + private void processDiscriminator() { + final AnnotationInstance discriminatorColumnAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN + ); + + final AnnotationInstance discriminatorFormulaAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), + HibernateDotNames.DISCRIMINATOR_FORMULA + ); + + + Class type = String.class; // string is the discriminator default + if ( discriminatorFormulaAnnotation != null ) { + String expression = JandexHelper.getValue( discriminatorFormulaAnnotation, "value", String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + discriminatorFormula = new FormulaValue( null, expression ); + } + discriminatorColumnValues = new Column( null ); //(stliu) give null here, will populate values below + discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null + if ( discriminatorColumnAnnotation != null ) { + DiscriminatorType discriminatorType = JandexHelper.getEnumValue( + discriminatorColumnAnnotation, + "discriminatorType", DiscriminatorType.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) ); + switch ( discriminatorType ) { + case STRING: { + type = String.class; + break; + } + case CHAR: { + type = Character.class; + break; + } + case INTEGER: { + type = Integer.class; + break; + } + default: { + throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); + } + } + + discriminatorColumnValues.setName( + JandexHelper.getValue( + discriminatorColumnAnnotation, + "name", + String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + discriminatorColumnValues.setLength( + JandexHelper.getValue( + discriminatorColumnAnnotation, + "length", + Integer.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + discriminatorColumnValues.setColumnDefinition( + JandexHelper.getValue( + discriminatorColumnAnnotation, + "columnDefinition", + String.class, + getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + } + discriminatorType = type; + + AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), HibernateDotNames.DISCRIMINATOR_OPTIONS + ); + if ( discriminatorOptionsAnnotation != null ) { + isDiscriminatorForced = discriminatorOptionsAnnotation.value( "force" ).asBoolean(); + isDiscriminatorIncludedInSql = discriminatorOptionsAnnotation.value( "insert" ).asBoolean(); + } + else { + isDiscriminatorForced = false; + isDiscriminatorIncludedInSql = true; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/package.html new file mode 100755 index 0000000000..2d0629a274 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/package.html @@ -0,0 +1,33 @@ + + + + + +

          + This package contains classes related to mapped entities and their hierarchy structure. +

          + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileProcessor.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileProcessor.java index 712d52c3f1..70968a025c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileProcessor.java @@ -21,22 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.global; +package org.hibernate.metamodel.internal.source.annotations.global; +import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.hibernate.MappingException; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchProfiles; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.FetchProfile.Fetch; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.FetchProfile.Fetch; import org.jboss.jandex.AnnotationInstance; /** @@ -44,9 +43,9 @@ import org.jboss.jandex.AnnotationInstance; * * @author Hardy Ferentschik */ -public class FetchProfileBinder { +public class FetchProfileProcessor { - private FetchProfileBinder() { + private FetchProfileProcessor() { } /** @@ -57,10 +56,10 @@ public class FetchProfileBinder { // TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex() + Collection annotations = bindingContext.getIndex() .getAnnotations( HibernateDotNames.FETCH_PROFILE ); for ( AnnotationInstance fetchProfile : annotations ) { - bind( bindingContext.getMetadataImplementor(), fetchProfile ); + bind( bindingContext, fetchProfile ); } annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FETCH_PROFILES ); @@ -68,31 +67,34 @@ public class FetchProfileBinder { AnnotationInstance[] fetchProfileAnnotations = JandexHelper.getValue( fetchProfiles, "value", - AnnotationInstance[].class + AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); for ( AnnotationInstance fetchProfile : fetchProfileAnnotations ) { - bind( bindingContext.getMetadataImplementor(), fetchProfile ); + bind( bindingContext, fetchProfile ); } } } - private static void bind(MetadataImplementor metadata, AnnotationInstance fetchProfile) { - String name = JandexHelper.getValue( fetchProfile, "name", String.class ); + private static void bind(AnnotationBindingContext bindingContext, AnnotationInstance fetchProfile) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + String name = JandexHelper.getValue( fetchProfile, "name", String.class, classLoaderService); Set fetches = new HashSet(); AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( fetchProfile, "fetchOverrides", - AnnotationInstance[].class + AnnotationInstance[].class, + classLoaderService ); for ( AnnotationInstance override : overrideAnnotations ) { - FetchMode fetchMode = JandexHelper.getEnumValue( override, "mode", FetchMode.class ); + FetchMode fetchMode = JandexHelper.getEnumValue( override, "mode", FetchMode.class, classLoaderService ); if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { throw new MappingException( "Only FetchMode.JOIN is currently supported" ); } - final String entityName = JandexHelper.getValue( override, "entity", String.class ); - final String associationName = JandexHelper.getValue( override, "association", String.class ); + final String entityName = JandexHelper.getValue( override, "entity", String.class, classLoaderService ); + final String associationName = JandexHelper.getValue( override, "association", String.class, classLoaderService ); fetches.add( new Fetch( entityName, associationName, fetchMode.toString().toLowerCase() ) ); } - metadata.addFetchProfile( new FetchProfile( name, fetches ) ); + bindingContext.getMetadataImplementor().addFetchProfile( new FetchProfile( name, fetches ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/IdGeneratorProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/IdGeneratorProcessor.java new file mode 100644 index 0000000000..b11f33aa03 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/IdGeneratorProcessor.java @@ -0,0 +1,280 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.global; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.GenerationType; +import javax.persistence.SequenceGenerator; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.GenericGenerators; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.SequenceHiLoGenerator; +import org.hibernate.id.TableHiLoGenerator; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.id.enhanced.TableGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.logging.Logger; + +/** + * Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and + * {@link GenericGenerators} annotations. + * + * @author Hardy Ferentschik + */ +public class IdGeneratorProcessor { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + IdGeneratorProcessor.class.getName() + ); + + private IdGeneratorProcessor() { + } + + /** + * Binds all {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and + * {@link GenericGenerators} annotations to the supplied metadata. + * + * @param bindingContext the context for annotation binding + */ + public static Iterable extractGlobalIdentifierGeneratorSources(AnnotationBindingContext bindingContext) { + List identifierGeneratorSources = new ArrayList(); + Collection annotations = bindingContext.getIndex() + .getAnnotations( JPADotNames.SEQUENCE_GENERATOR ); + for ( AnnotationInstance generator : annotations ) { + bindSequenceGenerator( bindingContext.getMetadataImplementor(), generator, identifierGeneratorSources, bindingContext ); + } + + annotations = bindingContext.getIndex().getAnnotations( JPADotNames.TABLE_GENERATOR ); + for ( AnnotationInstance generator : annotations ) { + bindTableGenerator( bindingContext.getMetadataImplementor(), generator, identifierGeneratorSources, bindingContext ); + } + + annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + HibernateDotNames.GENERIC_GENERATOR, + HibernateDotNames.GENERIC_GENERATORS, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance generator : annotations ) { + bindGenericGenerator( generator, identifierGeneratorSources, bindingContext ); + } + return identifierGeneratorSources; + } + + private static void addStringParameter( + final AnnotationInstance annotation, + final String element, + final Map parameters, + final String parameter, + final AnnotationBindingContext bindingContext) { + String string = JandexHelper.getValue( annotation, element, String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class )); + if ( StringHelper.isNotEmpty( string ) ) { + parameters.put( parameter, string ); + } + } + + private static void bindGenericGenerator( + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + final Map parameterMap = new HashMap(); + final AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + generator, + "parameters", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMap.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class, classLoaderService ), + JandexHelper.getValue( parameterAnnotation, "value", String.class, classLoaderService ) + ); + } + identifierGeneratorSources.add( + new IdentifierGeneratorSourceImpl( + name, + JandexHelper.getValue( generator, "strategy", String.class, classLoaderService ), + parameterMap + ) + ); + LOG.tracef( "Add generic generator with name: %s", name ); + } + + private static void bindSequenceGenerator( + final MetadataImplementor metadata, + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + + final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); + final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + GenerationType.SEQUENCE, + useNewIdentifierGenerators + ); + + final Map parameterMap = new HashMap(); + addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM, bindingContext ); + + if ( useNewIdentifierGenerators ) { + addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG, bindingContext ); + addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA, bindingContext ); + parameterMap.put( + SequenceStyleGenerator.INCREMENT_PARAM, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) ) + ); + parameterMap.put( + SequenceStyleGenerator.INITIAL_PARAM, + String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class, + classLoaderService ) ) + ); + } + else { + if ( JandexHelper.getValue( generator, "initialValue", Integer.class, classLoaderService ) != 1 ) { + LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); + } + parameterMap.put( + SequenceHiLoGenerator.MAX_LO, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) - 1 ) + ); + } + identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) ); + LOG.tracef( "Add sequence generator with name: %s", name ); + } + + private static void bindTableGenerator( + final MetadataImplementor metadata, + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + + final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); + final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + GenerationType.TABLE, + useNewIdentifierGenerators + ); + + final Map parameterMap = new HashMap(); + addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG, bindingContext ); + addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA, bindingContext ); + + if ( useNewIdentifierGenerators ) { + parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); + addStringParameter( generator, "table", parameterMap, TableGenerator.TABLE_PARAM, bindingContext ); + addStringParameter( generator, "pkColumnName", parameterMap, TableGenerator.SEGMENT_COLUMN_PARAM, bindingContext ); + addStringParameter( generator, "pkColumnValue", parameterMap, TableGenerator.SEGMENT_VALUE_PARAM, bindingContext ); + addStringParameter( generator, "valueColumnName", parameterMap, TableGenerator.VALUE_COLUMN_PARAM, bindingContext ); + parameterMap.put( + TableGenerator.INCREMENT_PARAM, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) ) + ); + parameterMap.put( + TableGenerator.INITIAL_PARAM, + String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class, + classLoaderService ) + 1 ) + ); + } + else { + addStringParameter( generator, "table", parameterMap, MultipleHiLoPerTableGenerator.ID_TABLE, bindingContext ); + addStringParameter( generator, "pkColumnName", parameterMap, MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, bindingContext ); + addStringParameter( generator, "pkColumnValue", parameterMap, MultipleHiLoPerTableGenerator.PK_VALUE_NAME, bindingContext ); + addStringParameter( + generator, + "valueColumnName", + parameterMap, + MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, + bindingContext + ); + parameterMap.put( + TableHiLoGenerator.MAX_LO, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) - 1 ) + ); + } + if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class, + classLoaderService ).length > 0 ) { + LOG.ignoringTableGeneratorConstraints( name ); + } + identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) ); + LOG.tracef( "Add table generator with name: %s", name ); + } + + private static class IdentifierGeneratorSourceImpl implements IdentifierGeneratorSource { + private final String generatorName; + private final String generatorImplementationName; + private final Map parameterMap; + + public IdentifierGeneratorSourceImpl( + String generatorName, + String generatorImplementationName, + Map parameterMap) { + this.generatorName = generatorName; + this.generatorImplementationName = generatorImplementationName; + this.parameterMap = parameterMap; + } + + @Override + public String getGeneratorName() { + return generatorName; + } + + @Override + public String getGeneratorImplementationName() { + return generatorImplementationName; + } + + @Override + public Map getParameters() { + return parameterMap; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/QueryProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/QueryProcessor.java new file mode 100644 index 0000000000..5e0ab2d4e6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/QueryProcessor.java @@ -0,0 +1,437 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.global; + +import java.util.Collection; +import java.util.HashMap; + +import javax.persistence.LockModeType; +import javax.persistence.NamedNativeQueries; +import javax.persistence.NamedNativeQuery; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.CacheMode; +import org.hibernate.FlushMode; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.MappingException; +import org.hibernate.annotations.CacheModeType; +import org.hibernate.annotations.FlushModeType; +import org.hibernate.annotations.QueryHints; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.LockModeConverter; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.logging.Logger; + +/** + * Binds {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, + * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, + * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries}. + * + * @author Hardy Ferentschik + */ +public class QueryProcessor { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + QueryProcessor.class.getName() + ); + + private QueryProcessor() { + } + + /** + * Binds all {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, + * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, + * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries} + * annotations to the supplied metadata. + * + * @param bindingContext the context for annotation binding + */ + public static void bind(AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + Collection annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + JPADotNames.NAMED_QUERY, + JPADotNames.NAMED_QUERIES, + classLoaderService + ); + for ( AnnotationInstance query : annotations ) { + bindNamedQuery( bindingContext, query ); + } + + annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + JPADotNames.NAMED_NATIVE_QUERY, + JPADotNames.NAMED_NATIVE_QUERIES, + classLoaderService + ); + for ( AnnotationInstance query : annotations ) { + bindNamedNativeQuery( query, bindingContext ); + } + + annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + HibernateDotNames.NAMED_QUERY, + HibernateDotNames.NAMED_QUERIES, + classLoaderService + ); + for ( AnnotationInstance query : annotations ) { + bindNamedQuery( bindingContext, query ); + } + + annotations = JandexHelper.getAnnotations( + bindingContext.getIndex(), + HibernateDotNames.NAMED_NATIVE_QUERY, + HibernateDotNames.NAMED_NATIVE_QUERIES, + classLoaderService + ); + for ( AnnotationInstance query : annotations ) { + bindNamedNativeQuery( query, bindingContext ); + } + } + + /** + * Binds {@link javax.persistence.NamedQuery} as well as {@link org.hibernate.annotations.NamedQuery}. + * + * @param metadata the current metadata + * @param annotation the named query annotation + */ + private static void bindNamedQuery(AnnotationBindingContext bindingContext, AnnotationInstance annotation) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( annotation, "name", String.class, classLoaderService ); + if ( StringHelper.isEmpty( name ) ) { + throw new AnnotationException( "A named query must have a name when used in class or package level" ); + } + NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder(); + builder.setName( name ); + + final String query = JandexHelper.getValue( annotation, "query", String.class, classLoaderService ); + builder.setQuery( query ); + if ( annotation.name().equals( JPADotNames.NAMED_QUERY ) ) { + bindJPANamedQuery( annotation, builder, name, query, bindingContext ); + } else { + builder.setFlushMode( + getFlushMode( JandexHelper.getEnumValue( annotation, "flushMode", FlushModeType.class, classLoaderService ) ) ) + .setCacheable( JandexHelper.getValue( annotation, "cacheable", Boolean.class, classLoaderService ) ) + .setCacheRegion( defaultToNull( JandexHelper.getValue( annotation, "cacheRegion", String.class, classLoaderService ) ) ) + .setFetchSize( defaultToNull( JandexHelper.getValue( annotation, "fetchSize", Integer.class, classLoaderService ) ) ) + .setTimeout( defaultToNull( JandexHelper.getValue( annotation, "timeout", Integer.class, classLoaderService ) ) ) + .setComment( JandexHelper.getValue( annotation, "comment", String.class, classLoaderService ) ) + .setCacheMode( getCacheMode( JandexHelper.getValue( annotation, "cacheMode", CacheModeType.class, classLoaderService ) ) ) + .setReadOnly( JandexHelper.getValue( annotation, "readOnly", Boolean.class, classLoaderService ) ); + } + + + bindingContext.getMetadataImplementor().addNamedQuery(builder.createNamedQueryDefinition()); + LOG.debugf( "Binding named query: %s => %s", name, query ); + } + + public static FlushMode getFlushMode(FlushModeType flushModeType) { + FlushMode flushMode; + switch ( flushModeType ) { + case ALWAYS: + flushMode = FlushMode.ALWAYS; + break; + case AUTO: + flushMode = FlushMode.AUTO; + break; + case COMMIT: + flushMode = FlushMode.COMMIT; + break; + case NEVER: + flushMode = FlushMode.MANUAL; + break; + case MANUAL: + flushMode = FlushMode.MANUAL; + break; + case PERSISTENCE_CONTEXT: + flushMode = null; + break; + default: + throw new AssertionFailure( "Unknown flushModeType: " + flushModeType ); + } + return flushMode; + } + private static CacheMode getCacheMode(CacheModeType cacheModeType) { + switch ( cacheModeType ) { + case GET: + return CacheMode.GET; + case IGNORE: + return CacheMode.IGNORE; + case NORMAL: + return CacheMode.NORMAL; + case PUT: + return CacheMode.PUT; + case REFRESH: + return CacheMode.REFRESH; + default: + throw new AssertionFailure( "Unknown cacheModeType: " + cacheModeType ); + } + } + + + private static void bindJPANamedQuery( + AnnotationInstance annotation, + NamedQueryDefinitionBuilder builder, + String name, + String query, + AnnotationBindingContext bindingContext){ + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class, + classLoaderService ); + + String cacheRegion = getString( hints, QueryHints.CACHE_REGION, bindingContext ); + if ( StringHelper.isEmpty( cacheRegion ) ) { + cacheRegion = null; + } + + Integer timeout = getTimeout( hints, query, bindingContext ); + if ( timeout != null && timeout < 0 ) { + timeout = null; + } + //TODO this 'javax.persistence.lock.timeout' has been mvoed to {@code AvailableSettings} in master + //we should change this when we merge this branch back. + Integer lockTimeout = getInteger( hints, "javax.persistence.lock.timeout" , query, bindingContext ); + lockTimeout = defaultToNull( lockTimeout ); + + LockOptions lockOptions = new LockOptions( LockModeConverter.convertToLockMode( JandexHelper.getEnumValue( + annotation, + "lockMode", + LockModeType.class, + classLoaderService + ) ) ); + if ( lockTimeout != null ) { + lockOptions.setTimeOut( lockTimeout ); + } + + builder.setCacheable( getBoolean( hints, QueryHints.CACHEABLE, name, bindingContext ) ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setLockOptions( lockOptions ) + .setFetchSize( defaultToNull( getInteger( hints, QueryHints.FETCH_SIZE, name, bindingContext ) ) ) + .setFlushMode( getFlushMode( hints, QueryHints.FLUSH_MODE, name, bindingContext ) ) + .setCacheMode( getCacheMode( hints, QueryHints.CACHE_MODE, name, bindingContext ) ) + .setReadOnly( getBoolean( hints, QueryHints.READ_ONLY, name, bindingContext ) ) + .setComment( defaultToNull( getString( hints, QueryHints.COMMENT, bindingContext ) ) ) + .setParameterTypes( null ); + } + + private static void bindNamedNativeQuery(AnnotationInstance annotation, AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + String name = JandexHelper.getValue( annotation, "name", String.class, classLoaderService ); + if ( StringHelper.isEmpty( name ) ) { + throw new AnnotationException( "A named native query must have a name when used in class or package level" ); + } + + String query = JandexHelper.getValue( annotation, "query", String.class, classLoaderService ); + + String resultSetMapping = JandexHelper.getValue( annotation, "resultSetMapping", String.class, classLoaderService ); + + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class, classLoaderService ); + + boolean cacheable = getBoolean( hints, "org.hibernate.cacheable", name, bindingContext ); + String cacheRegion = getString( hints, QueryHints.CACHE_REGION, bindingContext ); + if ( StringHelper.isEmpty( cacheRegion ) ) { + cacheRegion = null; + } + + Integer timeout = getTimeout( hints, query, bindingContext ); + if ( timeout != null && timeout < 0 ) { + timeout = null; + } + + Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name, bindingContext ); + if ( fetchSize != null && fetchSize < 0 ) { + fetchSize = null; + } + + FlushMode flushMode = getFlushMode( hints, QueryHints.FLUSH_MODE, name, bindingContext ); + CacheMode cacheMode = getCacheMode( hints, QueryHints.CACHE_MODE, name, bindingContext ); + + boolean readOnly = getBoolean( hints, QueryHints.READ_ONLY, name, bindingContext ); + + String comment = getString( hints, QueryHints.COMMENT, bindingContext ); + if ( StringHelper.isEmpty( comment ) ) { + comment = null; + } + + boolean callable = getBoolean( hints, QueryHints.CALLABLE, name, bindingContext ); + NamedSQLQueryDefinition def; + if ( StringHelper.isNotEmpty( resultSetMapping ) ) { + boolean resultSetMappingExists = bindingContext.getMetadataImplementor().getResultSetMappingDefinitions().containsKey( resultSetMapping ); + if ( !resultSetMappingExists ) { + throw new MappingException( + String.format( + "Named SQL Query [%s] referenced an non-existent result set mapping [%s] ", + name, + resultSetMapping + ) + ); + } + def = new NamedSQLQueryDefinitionBuilder().setName( name ) + .setQuery( query ) + .setResultSetRef( + resultSetMapping + ) + .setQuerySpaces( null ) + .setCacheable( cacheable ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setFetchSize( fetchSize ) + .setFlushMode( flushMode ) + .setCacheMode( cacheMode ) + .setReadOnly( readOnly ) + .setComment( comment ) + .setParameterTypes( null ) + .setCallable( callable ) + .createNamedQueryDefinition(); + } + else { + AnnotationValue annotationValue = annotation.value( "resultClass" ); + NativeSQLQueryRootReturn[] queryRoots; + if ( annotationValue == null ) { + // pure native scalar query + queryRoots = new NativeSQLQueryRootReturn[0]; + } + else { + queryRoots = new NativeSQLQueryRootReturn[] { + new NativeSQLQueryRootReturn( + "alias1", + annotationValue.asString(), + new HashMap(), + LockMode.READ + ) + }; + } + def = new NamedSQLQueryDefinitionBuilder().setName( name ) + .setQuery( query ) + .setQueryReturns( queryRoots ) + .setQuerySpaces( null ) + .setCacheable( cacheable ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setFetchSize( fetchSize ) + .setFlushMode( flushMode ) + .setCacheMode( cacheMode ) + .setReadOnly( readOnly ) + .setComment( comment ) + .setParameterTypes( null ) + .setCallable( callable ) + .createNamedQueryDefinition(); + } + bindingContext.getMetadataImplementor().addNamedNativeQuery( def ); + LOG.debugf( "Binding named native query: %s => %s", name, query ); + } + + private static boolean getBoolean(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null || val.equalsIgnoreCase( "false" ) ) { + return false; + } + if ( val.equalsIgnoreCase( "true" ) ) { + return true; + } + throw new AnnotationException( "Not a boolean in hint: " + query + ":" + element ); + } + + private static CacheMode getCacheMode(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return CacheMode.valueOf( val.toUpperCase() ); + } + catch ( IllegalArgumentException e ) { + throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element ); + } + } + + private static FlushMode getFlushMode(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return FlushMode.valueOf( val.toUpperCase() ); + } + catch ( IllegalArgumentException e ) { + throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + element ); + } + } + + private static Integer getInteger(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return Integer.decode( val ); + } + catch ( NumberFormatException nfe ) { + throw new AnnotationException( "Not an integer in hint: " + query + ":" + element, nfe ); + } + } + + private static String getString(AnnotationInstance[] hints, String element, AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + for ( AnnotationInstance hint : hints ) { + if ( element.equals( JandexHelper.getValue( hint, "name", String.class, classLoaderService ) ) ) { + return JandexHelper.getValue( hint, "value", String.class, classLoaderService ); + } + } + return null; + } + + private static Integer getTimeout(AnnotationInstance[] hints, String query, AnnotationBindingContext bindingContext) { + Integer timeout = getInteger( hints, QueryHints.TIMEOUT_JPA, query, bindingContext ); + if ( timeout == null ) { + return getInteger( hints, QueryHints.TIMEOUT_HIBERNATE, query, bindingContext ); // timeout is already in seconds + } + return ( ( timeout + 500 ) / 1000 ); // convert milliseconds to seconds (rounded) + } + + private static String defaultToNull( String s ) { + return StringHelper.isEmpty( s ) ? null : s; + } + + private static Integer defaultToNull( Integer i ) { + return i == null || i < 0 ? null : i; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/SqlResultSetProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/SqlResultSetProcessor.java new file mode 100644 index 0000000000..6955582a78 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/SqlResultSetProcessor.java @@ -0,0 +1,344 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.global; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.logging.Logger; + +import org.hibernate.LockMode; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding; + +/** + * Binds
            + *
          • {@link javax.persistence.SqlResultSetMapping}
          • + *
          • {@link javax.persistence.SqlResultSetMappings}
          • + *
          • {@link javax.persistence.EntityResult}
          • + *
          • {@link javax.persistence.FieldResult}
          • + *
          • {@link javax.persistence.ColumnResult}
          • + *
          + * + * @author Strong Liu + */ +public class SqlResultSetProcessor { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + QueryProcessor.class.getName() + ); + + private SqlResultSetProcessor() { + } + + public static void bind(final AnnotationBindingContext bindingContext) { + Collection annotations = bindingContext.getIndex() + .getAnnotations( JPADotNames.SQL_RESULT_SET_MAPPING ); + for ( final AnnotationInstance sqlResultSetMappingAnnotationInstance : annotations ) { + bindSqlResultSetMapping( bindingContext, sqlResultSetMappingAnnotationInstance ); + } + + annotations = bindingContext.getIndex().getAnnotations( JPADotNames.SQL_RESULT_SET_MAPPINGS ); + for ( final AnnotationInstance sqlResultSetMappingsAnnotationInstance : annotations ) { + for ( AnnotationInstance annotationInstance : JandexHelper.getValue( + sqlResultSetMappingsAnnotationInstance, + "value", + AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ) ) { + bindSqlResultSetMapping( bindingContext, annotationInstance ); + } + } + } + + private static int entityAliasIndex = 0; + + private static void bindSqlResultSetMapping(final AnnotationBindingContext bindingContext, final AnnotationInstance annotation) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + entityAliasIndex = 0; + final String name = JandexHelper.getValue( annotation, "name", String.class, classLoaderService ); + LOG.debugf( "Binding @SqlResultSetMapping(name=%s)", name ); + final ResultSetMappingDefinition definition = new ResultSetMappingDefinition( name ); + for ( final AnnotationInstance entityResult : JandexHelper.getValue( + annotation, + "entities", + AnnotationInstance[].class, + classLoaderService + ) ) { + bindEntityResult( bindingContext, entityResult, definition ); + } + for ( final AnnotationInstance columnResult : JandexHelper.getValue( + annotation, + "columns", + AnnotationInstance[].class, + classLoaderService + ) ) { + bindColumnResult( bindingContext, columnResult, definition ); + } + + bindingContext.getMetadataImplementor().addResultSetMapping( definition ); + } + + private static void bindEntityResult(final AnnotationBindingContext bindingContext, + final AnnotationInstance entityResult, + final ResultSetMappingDefinition definition) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String className = JandexHelper.getValue( entityResult, "entityClass", String.class, classLoaderService ); + final EntityBinding targetEntityBinding = bindingContext.getMetadataImplementor().getEntityBinding( className ); + if ( targetEntityBinding == null ) { + throw new MappingException( + String.format( + "Entity[%s] not found in SqlResultMapping[%s]", + className, + definition.getName() + ) + ); + } + + final String discriminatorColumn = JandexHelper.getValue( entityResult, "discriminatorColumn", String.class, + classLoaderService ); + + final Map propertyResults = new HashMap(); + + + if ( StringHelper.isNotEmpty( discriminatorColumn ) ) { + final String quotingNormalizedName = bindingContext.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( + discriminatorColumn + ); + propertyResults.put( "class", new String[] { quotingNormalizedName } ); + } + List fieldResultList = reorderFieldResult( + bindingContext, + entityResult, + targetEntityBinding, + definition.getName() + ); + + for ( final FieldResult fieldResult : fieldResultList ) { + insert( fieldResult.column, StringHelper.root( fieldResult.name ), propertyResults ); + } + + final NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn( + "alias" + entityAliasIndex++, + targetEntityBinding.getEntity().getName(), + propertyResults, + LockMode.READ + ); + definition.addQueryReturn( result ); + } + + //todo see org.hibernate.cfg.annotations.ResultsetMappingSecondPass#getSubPropertyIterator + private static List reorderFieldResult(AnnotationBindingContext bindingContext, + AnnotationInstance entityResult, + EntityBinding entityBinding, + String resultSetMappingDefinitionName) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final AnnotationInstance[] fieldResultAnnotationInstances = JandexHelper.getValue( + entityResult, + "fields", + AnnotationInstance[].class, + classLoaderService + ); + List results = new ArrayList( fieldResultAnnotationInstances.length ); + List propertyNames = new ArrayList(); + final Set uniqueReturnProperty = new HashSet(); + for ( final AnnotationInstance fieldResult : fieldResultAnnotationInstances ) { + final String name = JandexHelper.getValue( fieldResult, "name", String.class, classLoaderService ); + if ( !uniqueReturnProperty.add( name ) ) { + throw new MappingException( + "duplicate @FieldResult for property " + name + + " on @Entity " + entityBinding.getEntity() + .getName() + " in " + resultSetMappingDefinitionName + ); + } + if ( "class".equals( name ) ) { + throw new MappingException( + "class is not a valid property name to use in a @FieldResult, use @EntityResult(discriminatorColumn) instead" + ); + } + final String column = JandexHelper.getValue( fieldResult, "column", String.class, + classLoaderService ); + final String quotingNormalizedColumnName = normalize( bindingContext, column ); + if ( name.contains( "." ) ) { + int dotIndex = name.lastIndexOf( '.' ); + String reducedName = name.substring( 0, dotIndex ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( reducedName ); + Iterable attributeBindings = null; + if ( CompositeAttributeBinding.class.isInstance( attributeBinding ) ) { + CompositeAttributeBinding compositeAttributeBinding = CompositeAttributeBinding.class.cast( + attributeBinding + ); + attributeBindings = compositeAttributeBinding.attributeBindings(); + + } + else if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ) { + ManyToOneAttributeBinding manyToOneAttributeBinding = ManyToOneAttributeBinding.class.cast( + attributeBinding + ); + EntityBinding referencedEntityBinding = manyToOneAttributeBinding.getReferencedEntityBinding(); + Set referencingAttributeBindings = manyToOneAttributeBinding.getEntityReferencingAttributeBindings(); + + if ( CollectionHelper.isNotEmpty( referencingAttributeBindings ) ) { + attributeBindings = referencingAttributeBindings; + } + else { +// EntityIdentifierNature entityIdentifierNature= referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getNature(); +// switch ( entityIdentifierNature ) { +// case SIMPLE: +// throw new MappingException( +// "dotted notation reference neither a component nor a many/one to one" +// ); +// case AGGREGATED_COMPOSITE: +// case COMPOSITE: +// referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().isSingleAttribute();//.isIdentifierMapper(); +// } + //todo check if this logic is correct + SingularNonAssociationAttributeBinding identifierAttributeBinding = referencedEntityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding(); + if ( CompositeAttributeBinding.class.isInstance( identifierAttributeBinding ) ) { + attributeBindings = CompositeAttributeBinding.class.cast( identifierAttributeBinding ) + .attributeBindings(); + } + else { + throw new MappingException( + "dotted notation reference neither a component nor a many/one to one" + ); + } + } + + + } + else { + throw new MappingException( "dotted notation reference neither a component nor a many/one to one" ); + } + List followers = getFollowers( attributeBindings, reducedName, name ); + int index = results.size(); + int followersSize = followers.size(); + for ( int loop = 0; loop < followersSize; loop++ ) { + String follower = followers.get( loop ); + int currentIndex = getIndexOfFirstMatchingProperty( propertyNames, follower ); + index = currentIndex != -1 && currentIndex < index ? currentIndex : index; + } + propertyNames.add( index, name ); + results.add( index, new FieldResult( name, quotingNormalizedColumnName ) ); + } + else { + propertyNames.add( name ); + results.add( new FieldResult( name, quotingNormalizedColumnName ) ); + } + + } + return results; + } + + private static int getIndexOfFirstMatchingProperty(List propertyNames, String follower) { + int propertySize = propertyNames.size(); + for ( int propIndex = 0; propIndex < propertySize; propIndex++ ) { + if ( ( propertyNames.get( propIndex ) ).startsWith( follower ) ) { + return propIndex; + } + } + return -1; + } + + private static class FieldResult { + String name; + String column; + + private FieldResult(String column, String name) { + this.column = column; + this.name = name; + } + } + + private static List getFollowers(Iterable attributeBindings, String reducedName, String name) { + boolean hasFollowers = false; + List followers = new ArrayList(); + for ( final AttributeBinding attributeBinding : attributeBindings ) { + String currentPropertyName = attributeBinding.getAttribute().getName(); + String currentName = reducedName + '.' + currentPropertyName; + if ( hasFollowers ) { + followers.add( currentName ); + } + if ( name.equals( currentName ) ) { + hasFollowers = true; + } + } + return followers; + } + + + private static void insert(String key, String value, Map map) { + if ( map.containsKey( key ) ) { + String[] oldValues = map.get( key ); + String[] values = Arrays.copyOf( oldValues, oldValues.length + 1 ); + values[oldValues.length] = value; + map.put( key, values ); + } + else { + map.put( key, new String[] { value } ); + } + } + + private static void bindColumnResult(final AnnotationBindingContext bindingContext, + final AnnotationInstance columnResult, + final ResultSetMappingDefinition definition) { + final String name = JandexHelper.getValue( columnResult, "name", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + final String normalizedName = normalize( bindingContext, name ); + //todo TYPE + definition.addQueryReturn( new NativeSQLQueryScalarReturn( normalizedName, null ) ); + } + + private static String normalize(final AnnotationBindingContext bindingContext, String name) { + return bindingContext.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java new file mode 100644 index 0000000000..294bf648d0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java @@ -0,0 +1,162 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.global; + +import java.util.Collection; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.logging.Logger; + +/** + * Binds table related information. This binder is called after the entities are bound. + * + * @author Hardy Ferentschik + */ +public class TableProcessor { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + TableProcessor.class.getName() + ); + + private TableProcessor() { + } + + /** + * Binds {@link org.hibernate.annotations.Tables} and {@link org.hibernate.annotations.Table} annotations to the supplied + * metadata. + * + * @param bindingContext the context for annotation binding + */ + public static void bind(AnnotationBindingContext bindingContext) { + Collection annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLE ); + for ( AnnotationInstance tableAnnotation : annotations ) { + bind( bindingContext, tableAnnotation ); + } + + annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLES ); + for ( AnnotationInstance tables : annotations ) { + for ( AnnotationInstance table : JandexHelper.getValue( tables, "value", AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ) ) { + bind( bindingContext, table ); + } + } + } + + private static void bind(AnnotationBindingContext bindingContext, AnnotationInstance tableAnnotation) { + MetadataImplementor metadata = bindingContext.getMetadataImplementor(); + String tableName = JandexHelper.getValue( tableAnnotation, "appliesTo", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + ObjectName objectName = ObjectName.parse( tableName ); + Schema schema = metadata.getDatabase().getSchema( objectName.getCatalog(), objectName.getSchema() ); + Table table = schema.locateTable( objectName.getName() ); + if ( table != null ) { + boolean isSecondaryTable = metadata.getSecondaryTables().containsKey( table.getLogicalName() ); + bindHibernateTableAnnotation( table, tableAnnotation,isSecondaryTable, bindingContext ); + } + else { + throw new MappingException( "Can't find table[" + tableName + "] from Annotation @Table" ); + } + } + + private static void bindHibernateTableAnnotation( + final Table table, + final AnnotationInstance tableAnnotation, + final boolean isSecondaryTable, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class, + classLoaderService ); + if ( StringHelper.isNotEmpty( comment ) ) { + table.addComment( comment.trim() ); + } + if ( !isSecondaryTable ) { + return; + } + SecondaryTable secondaryTable = bindingContext.getMetadataImplementor().getSecondaryTables().get( table.getLogicalName() ); + if ( tableAnnotation.value( "fetch" ) != null ) { + FetchMode fetchMode = JandexHelper.getEnumValue( tableAnnotation, "fetch", FetchMode.class, + classLoaderService ); + secondaryTable.setFetchStyle( EnumConversionHelper.annotationFetchModeToFetchStyle( fetchMode ) ); + } + if ( tableAnnotation.value( "inverse" ) != null ) { + secondaryTable.setInverse( tableAnnotation.value( "inverse" ).asBoolean() ); + } + if ( tableAnnotation.value( "optional" ) != null ) { + secondaryTable.setOptional( tableAnnotation.value( "optional" ).asBoolean() ); + } + + if ( tableAnnotation.value( "sqlInsert" ) != null ) { + secondaryTable.setCustomInsert( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlInsert" ) + .asNested() + ) + ); + } + if ( tableAnnotation.value( "sqlUpdate" ) != null ) { + secondaryTable.setCustomUpdate( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlUpdate" ) + .asNested() + ) + ); + + } + if ( tableAnnotation.value( "sqlDelete" ) != null ) { + secondaryTable.setCustomDelete( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlDelete" ) + .asNested() + ) + ); + } + // TODO: ForeignKey is not binded right now, because constrint name is not modifyable after it is set + // another option would be create something like tableDefinition and look up it when we bind table / secondary table + +// if ( tableAnnotation.value( "foreignKey" ) != null ) { +// AnnotationInstance foreignKeyAnnotation = tableAnnotation.value( "foreignKey" ).asNested(); +// if ( foreignKeyAnnotation.value( "name" ) != null ) { +// secondaryTable.getForeignKeyReference().setName( foreignKeyAnnotation.value( "name" ).asString() ); +// } +// } + + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/package.html new file mode 100755 index 0000000000..2891a8165f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/package.html @@ -0,0 +1,34 @@ + + + + + +

          + This package contains the implementations of the source interfaces defined in + org.hibernate.metamodel.spi.source +

          + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/AnnotationParserHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/AnnotationParserHelper.java new file mode 100644 index 0000000000..9faa5d0206 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/AnnotationParserHelper.java @@ -0,0 +1,242 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.EntityMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +import com.fasterxml.classmate.members.ResolvedMember; + +/** + * Some annotation processing is identical between entity and attribute level (aka you can place the annotation on + * entity as well as attribute level. This class tries to avoid code duplication for these cases. + * + * @author Hardy Ferentschik + */ +public class AnnotationParserHelper { + + // should not be instantiated + private AnnotationParserHelper() { + + } + + public static CustomSQL processCustomSqlAnnotation(DotName annotationName, + Map> annotations) { + final AnnotationInstance sqlAnnotation = JandexHelper.getSingleAnnotation( annotations, annotationName ); + + return createCustomSQL( sqlAnnotation ); + } + + public static CustomSQL processCustomSqlAnnotation(DotName annotationName, + Map> annotations, ClassInfo target) { + final AnnotationInstance sqlAnnotation = JandexHelper.getSingleAnnotation( annotations, annotationName, target ); + + return createCustomSQL( sqlAnnotation ); + } + + public static CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation) { + if ( customSqlAnnotation == null ) { + return null; + } + + final String sql = customSqlAnnotation.value( "sql" ).asString(); + final boolean isCallable = customSqlAnnotation.value( "callable" ) != null + && customSqlAnnotation.value( "callable" ).asBoolean(); + + final ExecuteUpdateResultCheckStyle checkStyle = customSqlAnnotation.value( "check" ) == null + ? isCallable + ? ExecuteUpdateResultCheckStyle.NONE + : ExecuteUpdateResultCheckStyle.COUNT + : ExecuteUpdateResultCheckStyle.valueOf( customSqlAnnotation.value( "check" ).asEnum() ); + + return new CustomSQL( sql, isCallable, checkStyle ); + } + + public static String determineCustomTuplizer(Map> annotations, + AnnotationTarget target, ClassLoaderService classLoaderService){ + //tuplizer on field + final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation( + annotations, HibernateDotNames.TUPLIZERS, target + ); + final AnnotationInstance tuplizerAnnotation = JandexHelper.getSingleAnnotation( + annotations, + HibernateDotNames.TUPLIZER, + target + ); + return determineCustomTuplizer( + tuplizersAnnotation, + tuplizerAnnotation, + classLoaderService + ); + } + + public static String determineCustomTuplizer(Map> annotations, + ClassLoaderService classLoaderService){ + return determineCustomTuplizer( annotations, null, classLoaderService ); + } + + public static String determineCustomTuplizer( + final AnnotationInstance tuplizersAnnotation, + final AnnotationInstance tuplizerAnnotation, + final ClassLoaderService classLoaderService) { + if ( tuplizersAnnotation != null ) { + AnnotationInstance[] annotations = JandexHelper.getValue( + tuplizersAnnotation, + "value", + AnnotationInstance[].class, + classLoaderService + ); + for ( final AnnotationInstance annotationInstance : annotations ) { + final String impl = findTuplizerImpl( annotationInstance ); + if ( StringHelper.isNotEmpty( impl ) ) { + return impl; + } + } + } + else if ( tuplizerAnnotation != null ) { + final String impl = findTuplizerImpl( tuplizerAnnotation ); + if ( StringHelper.isNotEmpty( impl ) ) { + return impl; + } + } + return null; + } + + private static String findTuplizerImpl(final AnnotationInstance tuplizerAnnotation) { + final EntityMode mode; + if ( tuplizerAnnotation.value( "entityModeType" ) != null ) { + mode = EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() ); + } + else if ( tuplizerAnnotation.value( "entityMode" ) != null ) { + mode = EntityMode.parse( tuplizerAnnotation.value( "entityMode" ).asString() ); + } + else { + mode = EntityMode.POJO; + } + return mode == EntityMode.POJO ? tuplizerAnnotation.value( "impl" ).asString() : null; + } + + public static Class resolveCollectionElementType( + ResolvedMember resolvedMember, Map> annotations, + EntityBindingContext context) { + final AnnotationInstance annotation; + final String targetElementName; + if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ) ) { + annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ); + targetElementName = "targetEntity"; + } + else if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) ) { + annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ); + targetElementName = "targetEntity"; + } + else if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION ) ) { + annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION ); + targetElementName = "targetClass"; + } + else { + annotation = null; + targetElementName = null; + } + if ( annotation != null && annotation.value( targetElementName ) != null ) { + return context.locateClassByName( + JandexHelper.getValue( annotation, targetElementName, String.class, + context.getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + if ( resolvedMember.getType().isArray() ) { + return resolvedMember.getType().getArrayElementType().getErasedType(); + } + if ( resolvedMember.getType().getTypeParameters().isEmpty() ) { + return null; // no generic at all + } + Class type = resolvedMember.getType().getErasedType(); + if ( Collection.class.isAssignableFrom( type ) ) { + return resolvedMember.getType().getTypeParameters().get( 0 ).getErasedType(); + } + else if ( Map.class.isAssignableFrom( type ) ) { + return resolvedMember.getType().getTypeParameters().get( 1 ).getErasedType(); + } + else { + return null; + } + } + + public static SingularAttributeBinding.NaturalIdMutability checkNaturalId(Map> annotations) { + final AnnotationInstance naturalIdAnnotation = JandexHelper.getSingleAnnotation( + annotations, + HibernateDotNames.NATURAL_ID + ); + if ( naturalIdAnnotation == null ) { + return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + } + final boolean mutable = naturalIdAnnotation.value( "mutable" ) != null && naturalIdAnnotation.value( "mutable" ) + .asBoolean(); + return mutable ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE; + } + + public static boolean isPersistentMember(Set transientNames, Set explicitlyConfiguredMemberNames, Member member) { + if ( !ReflectHelper.isProperty( member ) ) { + return false; + } + + if ( member instanceof Field && Modifier.isStatic( member.getModifiers() ) ) { + // static fields are no instance variables! Catches also the case of serialVersionUID + return false; + } + + if ( member instanceof Method && Method.class.cast( member ).getReturnType().equals( void.class ) ){ + // not a getter + return false; + } + + if ( transientNames.contains( member.getName() ) ) { + return false; + } + + return !explicitlyConfiguredMemberNames.contains( ReflectHelper.getPropertyName( member ) ); + + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/ClassmateHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/ClassmateHelper.java new file mode 100644 index 0000000000..3e9aa34b92 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/ClassmateHelper.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; + +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; + +/** + * @author Strong Liu + */ +public class ClassmateHelper { + /** + * @param clazz + * @param contextResolveType + * @param bindingContext + * + * @return + */ + public static Map resolveClassHierarchyTypesFromAttributeType( + final Class clazz, + final ResolvedType contextResolveType, + final AnnotationBindingContext bindingContext) { + if ( clazz == null ) { + return Collections.emptyMap(); + } + final Map resolvedTypes = new HashMap(); + ResolvedType resolvedType = resolveClassType( clazz, contextResolveType, bindingContext ); +// String className = clazz.getName(); + if ( resolvedType != null ) { + //move this out of loop, since it returns all members from the hierarchy + final ResolvedTypeWithMembers resolvedTypeWithMembers = bindingContext.getMemberResolver() + .resolve( resolvedType, null, null ); + Class currentClass = clazz; + while ( currentClass != null && !Object.class.equals( currentClass ) ) { + resolvedTypes.put( currentClass.getName(), resolvedTypeWithMembers ); + currentClass = currentClass.getSuperclass(); + + } + +// while ( resolvedType != null && !Object.class.equals( resolvedType.getErasedType() ) ) { +// resolvedTypes.put( className, resolvedTypeWithMembers ); +// resolvedType = resolvedType.getParentClass(); +// if ( resolvedType != null ) { +// className = resolvedType.getErasedType().getName(); +// } +// } + } + + + return resolvedTypes; + } + + private static ResolvedType resolveClassType( + final Class clazz, + final ResolvedType contextResolveType, + final AnnotationBindingContext bindingContext) { + if ( contextResolveType == null || contextResolveType.isPrimitive() || clazz.isPrimitive() || clazz.getTypeParameters().length == 0 ) { + return bindingContext.getTypeResolver().resolve( clazz ); + } + else if ( contextResolveType.canCreateSubtype( clazz ) ) { + return bindingContext.getTypeResolver() + .resolve( + clazz, + contextResolveType.getTypeParameters() + .toArray( new ResolvedType[contextResolveType.getTypeBindings().size()] ) + ); + } + else if ( contextResolveType.isArray() ) { + return resolveClassType( clazz, contextResolveType.getArrayElementType(), bindingContext ); + } + else if ( contextResolveType.isInstanceOf( Collection.class ) || contextResolveType.isInstanceOf( Map.class ) ) { + return resolveClassType( clazz, contextResolveType.getTypeParameters(), bindingContext ); + } + return null; + } + + private static ResolvedType resolveClassType( + final Class clazz, + final List contextResolveTypes, + final AnnotationBindingContext bindingContext) { + if ( contextResolveTypes != null ) { + for ( ResolvedType contextResolveType : contextResolveTypes ) { + ResolvedType type = resolveClassType( clazz, contextResolveType, bindingContext ); + if ( type != null ) { + return type; + } + } + } + return null; + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyBuilder.java similarity index 66% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyBuilder.java index 1584c5c0d0..8b874e6b1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyBuilder.java @@ -21,9 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations.util; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -31,31 +32,42 @@ import java.util.Map; import java.util.Set; import javax.persistence.AccessType; -import org.hibernate.AnnotationException; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.annotations.entity.EntityClass; -import org.hibernate.metamodel.source.annotations.entity.RootEntitySourceImpl; -import org.hibernate.metamodel.source.annotations.entity.SubclassEntitySourceImpl; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.EntityHierarchyImpl; +import org.hibernate.metamodel.internal.source.annotations.JoinedSubclassEntitySourceImpl; +import org.hibernate.metamodel.internal.source.annotations.RootEntitySourceImpl; +import org.hibernate.metamodel.internal.source.annotations.SubclassEntitySourceImpl; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; /** * Given a (jandex) annotation index build processes all classes with JPA relevant annotations and pre-orders * JPA entities respectively their inheritance hierarchy. * * @author Hardy Ferentschik + * @author Strong Liu */ public class EntityHierarchyBuilder { - private static final DotName OBJECT = DotName.createSimple( Object.class.getName() ); + private static final Logger LOG = Logger.getLogger( + EntityHierarchyBuilder.class); + /** * Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound @@ -67,24 +79,20 @@ public class EntityHierarchyBuilder { */ public static Set createEntityHierarchies(AnnotationBindingContext bindingContext) { Set hierarchies = new HashSet(); - - List processedEntities = new ArrayList(); + Map processedEntities = new HashMap( ); Map> classToDirectSubClassMap = new HashMap>(); - Index index = bindingContext.getIndex(); - for ( ClassInfo info : index.getKnownClasses() ) { - if ( !isEntityClass( info ) ) { + IndexView index = bindingContext.getIndex(); + for ( ClassInfo classInfo : index.getKnownClasses() ) { + if ( processedEntities.containsKey( classInfo.name() ) ) { + continue; + } + if ( !isEntityClass( classInfo ) ) { continue; } - if ( processedEntities.contains( info.name() ) ) { - continue; - } - ClassInfo rootClassInfo = findRootEntityClassInfo( index, info ); + ClassInfo rootClassInfo = findRootEntityClassInfo( index, classInfo, bindingContext ); List rootClassWithAllSubclasses = new ArrayList(); - // the root entity might have some mapped super classes which we have to take into consideration - // for inheritance type and default access - addMappedSuperclasses( index, rootClassInfo, rootClassWithAllSubclasses ); // collect the current root entity and all its subclasses processHierarchy( @@ -94,6 +102,17 @@ public class EntityHierarchyBuilder { processedEntities, classToDirectSubClassMap ); + boolean hasSubclasses = rootClassWithAllSubclasses.size() > 1; + // using the root entity, resolve generic parameters in the whole class hierarchy + final Map resolvedTypeWithMembers = resolveGenerics( + rootClassInfo.toString(), + bindingContext + ); + List mappedSuperclasses = findMappedSuperclasses( index, rootClassInfo ); + + // the root entity might have some mapped super classes which we have to take into consideration + // for inheritance type and default access + rootClassWithAllSubclasses.addAll( mappedSuperclasses ); AccessType defaultAccessType = determineDefaultAccessType( rootClassWithAllSubclasses ); InheritanceType hierarchyInheritanceType = determineInheritanceType( @@ -102,11 +121,13 @@ public class EntityHierarchyBuilder { ); // create the root entity source - EntityClass rootEntityClass = new EntityClass( + RootEntityClass rootEntityClass = new RootEntityClass( rootClassInfo, - null, + resolvedTypeWithMembers, + mappedSuperclasses, defaultAccessType, hierarchyInheritanceType, + hasSubclasses, bindingContext ); RootEntitySourceImpl rootSource = new RootEntitySourceImpl( rootEntityClass ); @@ -114,41 +135,52 @@ public class EntityHierarchyBuilder { addSubclassEntitySources( bindingContext, classToDirectSubClassMap, + resolvedTypeWithMembers, defaultAccessType, hierarchyInheritanceType, rootEntityClass, rootSource ); - hierarchies.add( new EntityHierarchyImpl( rootSource, hierarchyInheritanceType ) ); } return hierarchies; } - private static void addSubclassEntitySources(AnnotationBindingContext bindingContext, - Map> classToDirectSubClassMap, - AccessType defaultAccessType, - InheritanceType hierarchyInheritanceType, - EntityClass entityClass, - EntitySource entitySource) { + private static void addSubclassEntitySources( + AnnotationBindingContext bindingContext, + Map> classToDirectSubClassMap, + Map resolvedTypeWithMembers, + AccessType defaultAccessType, + InheritanceType hierarchyInheritanceType, + EntityClass entityClass, + EntitySource entitySource) { List subClassInfoList = classToDirectSubClassMap.get( DotName.createSimple( entitySource.getClassName() ) ); if ( subClassInfoList == null ) { return; } for ( ClassInfo subClassInfo : subClassInfoList ) { + resolvedTypeWithMembers.putAll( resolveGenerics( subClassInfo.name().toString(), bindingContext ) ); + ResolvedTypeWithMembers typeWithMembers = resolvedTypeWithMembers.get( subClassInfo.toString() ); + if ( typeWithMembers == null ) { + throw new AssertionFailure( "Missing generic information for " + subClassInfo.toString() ); + } EntityClass subclassEntityClass = new EntityClass( subClassInfo, + typeWithMembers, entityClass, defaultAccessType, hierarchyInheritanceType, bindingContext ); - SubclassEntitySource subclassEntitySource = new SubclassEntitySourceImpl( subclassEntityClass ); + SubclassEntitySource subclassEntitySource = hierarchyInheritanceType == InheritanceType.JOINED ? + new JoinedSubclassEntitySourceImpl( subclassEntityClass, entitySource ) + : new SubclassEntitySourceImpl( subclassEntityClass, entitySource ); entitySource.add( subclassEntitySource ); addSubclassEntitySources( bindingContext, classToDirectSubClassMap, + resolvedTypeWithMembers, defaultAccessType, hierarchyInheritanceType, subclassEntityClass, @@ -166,14 +198,28 @@ public class EntityHierarchyBuilder { * * @return Finds the root entity starting at the entity given by {@code info} */ - private static ClassInfo findRootEntityClassInfo(Index index, ClassInfo info) { + private static ClassInfo findRootEntityClassInfo(IndexView index, ClassInfo info, AnnotationBindingContext bindingContext) { ClassInfo rootEntity = info; DotName superName = info.superName(); ClassInfo tmpInfo; // walk up the hierarchy until java.lang.Object - while ( !OBJECT.equals( superName ) ) { + while ( !JandexHelper.OBJECT.equals( superName ) ) { tmpInfo = index.getClassByName( superName ); + if ( tmpInfo == null && superName != null ) { + Class clazz = bindingContext.locateClassByName( superName.toString() ); + if ( clazz != null ) { + throw new AnnotationException( + info.name() + .toString() + "'s parent class [" + clazz.getName() + "] is not added into Jandex repository" + ); + }else { + throw new AnnotationException( + info.name() + .toString() + "'s parent class [" + superName.toString() + "] doesn't exist in classpath" + ); + } + } if ( isEntityClass( tmpInfo ) ) { rootEntity = tmpInfo; } @@ -182,17 +228,18 @@ public class EntityHierarchyBuilder { return rootEntity; } - private static void addMappedSuperclasses(Index index, ClassInfo info, List classInfoList) { + private static List findMappedSuperclasses(IndexView index, ClassInfo info) { + List mappedSuperclasses = new ArrayList( ); DotName superName = info.superName(); - ClassInfo tmpInfo; // walk up the hierarchy until java.lang.Object - while ( !OBJECT.equals( superName ) ) { - tmpInfo = index.getClassByName( superName ); + while ( !JandexHelper.OBJECT.equals( superName ) ) { + ClassInfo tmpInfo = index.getClassByName( superName ); if ( isMappedSuperclass( tmpInfo ) ) { - classInfoList.add( tmpInfo ); + mappedSuperclasses.add( tmpInfo ); } superName = tmpInfo.superName(); } + return mappedSuperclasses; } /** @@ -212,19 +259,17 @@ public class EntityHierarchyBuilder { private static void processHierarchy(AnnotationBindingContext bindingContext, ClassInfo classInfo, List rootClassWithAllSubclasses, - List processedEntities, + Map processedEntities, Map> classToDirectSubclassMap) { - processedEntities.add( classInfo.name() ); + processedEntities.put( classInfo.name(), classInfo.name() ); rootClassWithAllSubclasses.add( classInfo ); - List subClasses = bindingContext.getIndex().getKnownDirectSubclasses( classInfo.name() ); - - // if there are no more subclasses we reached the leaf class. In order to properly resolve generics we - // need to resolve the type information using this leaf class - if ( subClasses.isEmpty() ) { - bindingContext.resolveAllTypes( classInfo.name().toString() ); - } + Collection subClasses = bindingContext.getIndex().getKnownDirectSubclasses( classInfo.name() ); for ( ClassInfo subClassInfo : subClasses ) { + if ( !isEntityClass( subClassInfo ) ) { + MappingAssertion.assertSubEntityIsNotEmbeddableNorMappedSuperclass( subClassInfo ); + continue; + } addSubClassToSubclassMap( classInfo.name(), subClassInfo, classToDirectSubclassMap ); processHierarchy( bindingContext, @@ -270,12 +315,19 @@ public class EntityHierarchyBuilder { info, JPADotNames.MAPPED_SUPERCLASS ); String className = info.toString(); - assertNotEntityAndMappedSuperClass( jpaEntityAnnotation, mappedSuperClassAnnotation, className ); + MappingAssertion.assertNotEntityAndMappedSuperClass( + jpaEntityAnnotation, + mappedSuperClassAnnotation, + className + ); AnnotationInstance embeddableAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.EMBEDDABLE ); - assertNotEntityAndEmbeddable( jpaEntityAnnotation, embeddableAnnotation, className ); + MappingAssertion.assertNotEntityAndEmbeddable( + jpaEntityAnnotation, + embeddableAnnotation, + className ); return true; } @@ -300,22 +352,6 @@ public class EntityHierarchyBuilder { return mappedSuperclassAnnotation != null; } - private static void assertNotEntityAndMappedSuperClass(AnnotationInstance jpaEntityAnnotation, AnnotationInstance mappedSuperClassAnnotation, String className) { - if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) { - throw new AnnotationException( - "An entity cannot be annotated with both @Entity and @MappedSuperclass. " + className + " has both annotations." - ); - } - } - - private static void assertNotEntityAndEmbeddable(AnnotationInstance jpaEntityAnnotation, AnnotationInstance embeddableAnnotation, String className) { - if ( jpaEntityAnnotation != null && embeddableAnnotation != null ) { - throw new AnnotationException( - "An entity cannot be annotated with both @Entity and @Embeddable. " + className + " has both annotations." - ); - } - } - /** * @param classes the classes in the hierarchy * @@ -384,7 +420,7 @@ public class EntityHierarchyBuilder { AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation( rootClassInfo, JPADotNames.INHERITANCE ); - if ( inheritanceAnnotation != null ) { + if ( inheritanceAnnotation != null && inheritanceAnnotation.value( "strategy" )!=null) { String enumName = inheritanceAnnotation.value( "strategy" ).asEnum(); javax.persistence.InheritanceType jpaInheritanceType = Enum.valueOf( javax.persistence.InheritanceType.class, enumName @@ -401,10 +437,10 @@ public class EntityHierarchyBuilder { info, JPADotNames.INHERITANCE ); if ( inheritanceAnnotation != null ) { - throw new AnnotationException( + LOG.warn( String.format( - "The inheritance type for %s must be specified on the root entity %s", - hierarchyListString( classes ), + "The inheritance type for %s should be specified only on the root entity %s. Ignoring...", + info.name(), rootClassInfo.name().toString() ) ); @@ -436,6 +472,28 @@ public class EntityHierarchyBuilder { builder.append( "]" ); return builder.toString(); } + + /** + * TODO this is incorrect, we should do it from bottom to top, not inverse, since the actual type info should be dedined in the sub class. + * we need this info to resolve super class type. + */ + private static Map resolveGenerics(String className, AnnotationBindingContext bindingContext) { + final Map resolvedTypes = new HashMap(); + final Class clazz = bindingContext.locateClassByName( className ); + ResolvedType resolvedType = bindingContext.getTypeResolver().resolve( clazz ); + while ( resolvedType!= null && !Object.class.equals( resolvedType.getErasedType() ) ) { + final ResolvedTypeWithMembers resolvedTypeWithMembers = bindingContext.getMemberResolver() + .resolve( resolvedType, null, null ); + resolvedTypes.put( className, resolvedTypeWithMembers ); + + resolvedType = resolvedType.getParentClass(); + if ( resolvedType != null ) { + className = resolvedType.getErasedType().getName(); + } + } + + return resolvedTypes; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EnumConversionHelper.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EnumConversionHelper.java index 98ae17a720..fbb273c9da 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/EnumConversionHelper.java @@ -21,9 +21,8 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations.util; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; @@ -31,15 +30,19 @@ import javax.persistence.GenerationType; import org.hibernate.AssertionFailure; import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; /** * Helper class which converts between different enum types. * * @author Hardy Ferentschik + * @author Brett Meyer */ public class EnumConversionHelper { private EnumConversionHelper() { @@ -90,6 +93,48 @@ public class EnumConversionHelper { } } } + + public static CascadeStyle cascadeTypeToCascadeStyle( + org.hibernate.annotations.CascadeType cascadeType) { + switch ( cascadeType ) { + case ALL: { + return CascadeStyles.ALL; + } + case PERSIST: { + return CascadeStyles.PERSIST; + } + case MERGE: { + return CascadeStyles.MERGE; + } + case REMOVE: { + return CascadeStyles.DELETE; + } + case REFRESH: { + return CascadeStyles.REFRESH; + } + case DETACH: { + return CascadeStyles.EVICT; + } + case DELETE: { + return CascadeStyles.DELETE; + } + case SAVE_UPDATE: { + return CascadeStyles.UPDATE; + } + case REPLICATE: { + return CascadeStyles.REPLICATE; + } + case LOCK: { + return CascadeStyles.LOCK; + } + case DELETE_ORPHAN: { + return CascadeStyles.DELETE_ORPHAN; + } + default: { + throw new AssertionFailure( "Unknown cascade type: " + cascadeType ); + } + } + } public static FetchMode annotationFetchModeToHibernateFetchMode(org.hibernate.annotations.FetchMode annotationFetchMode) { switch ( annotationFetchMode ) { @@ -110,13 +155,42 @@ public class EnumConversionHelper { } } - public static Set cascadeTypeToCascadeStyleSet(Set cascadeTypes) { - if ( CollectionHelper.isEmpty( cascadeTypes ) ) { - return Collections.emptySet(); + public static FetchStyle annotationFetchModeToFetchStyle(org.hibernate.annotations.FetchMode annotationFetchMode) { + switch ( annotationFetchMode ) { + case JOIN: { + return FetchStyle.JOIN; + } + case SELECT: { + return FetchStyle.SELECT; + } + case SUBSELECT: { + return FetchStyle.SUBSELECT; + } + default: { + throw new AssertionFailure( "Unknown fetch mode" ); + } } + } + + public static Set cascadeTypeToCascadeStyleSet( + Set cascadeTypes, + Set hibernateCascadeTypes, + EntityBindingContext context) { Set cascadeStyleSet = new HashSet(); - for ( CascadeType cascadeType : cascadeTypes ) { - cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + if ( CollectionHelper.isEmpty( cascadeTypes ) + && CollectionHelper.isEmpty( hibernateCascadeTypes ) ) { + String cascades = context.getMappingDefaults().getCascadeStyle(); + for ( String cascade : StringHelper.split( ",", cascades ) ) { + cascadeStyleSet.add( CascadeStyles.getCascadeStyle( cascade ) ); + } + } + else { + for ( CascadeType cascadeType : cascadeTypes ) { + cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + } + for ( org.hibernate.annotations.CascadeType cascadeType : hibernateCascadeTypes ) { + cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + } } return cascadeStyleSet; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/HibernateDotNames.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/HibernateDotNames.java index 932b672d00..92ac7f05d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/HibernateDotNames.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations.util; + +import org.jboss.jandex.DotName; import org.hibernate.annotations.AccessType; import org.hibernate.annotations.Any; @@ -37,7 +39,8 @@ import org.hibernate.annotations.ColumnTransformers; import org.hibernate.annotations.Columns; import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.DiscriminatorOptions; -import org.hibernate.annotations.Entity; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchProfile; import org.hibernate.annotations.FetchProfiles; @@ -64,11 +67,13 @@ import org.hibernate.annotations.Loader; import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.MapKeyType; import org.hibernate.annotations.MetaValue; +import org.hibernate.annotations.MultiTenancy; import org.hibernate.annotations.NamedNativeQueries; import org.hibernate.annotations.NamedNativeQuery; import org.hibernate.annotations.NamedQueries; import org.hibernate.annotations.NamedQuery; import org.hibernate.annotations.NaturalId; +import org.hibernate.annotations.NaturalIdCache; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OptimisticLock; @@ -77,19 +82,25 @@ import org.hibernate.annotations.ParamDef; import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parent; import org.hibernate.annotations.Persister; +import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.Proxy; import org.hibernate.annotations.RowId; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDeleteAll; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; import org.hibernate.annotations.Sort; +import org.hibernate.annotations.SortComparator; +import org.hibernate.annotations.SortNatural; import org.hibernate.annotations.Source; import org.hibernate.annotations.Subselect; import org.hibernate.annotations.Synchronize; import org.hibernate.annotations.Table; import org.hibernate.annotations.Tables; import org.hibernate.annotations.Target; +import org.hibernate.annotations.TenantColumn; +import org.hibernate.annotations.TenantFormula; import org.hibernate.annotations.Tuplizer; import org.hibernate.annotations.Tuplizers; import org.hibernate.annotations.Type; @@ -98,8 +109,6 @@ import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.Where; import org.hibernate.annotations.WhereJoinTable; -import org.jboss.jandex.DotName; - /** * Defines the dot names for the Hibernate specific mapping annotations. * @@ -120,16 +129,18 @@ public interface HibernateDotNames { DotName COLUMN_TRANSFORMERS = DotName.createSimple( ColumnTransformers.class.getName() ); DotName DISCRIMINATOR_FORMULA = DotName.createSimple( DiscriminatorFormula.class.getName() ); DotName DISCRIMINATOR_OPTIONS = DotName.createSimple( DiscriminatorOptions.class.getName() ); - DotName ENTITY = DotName.createSimple( Entity.class.getName() ); + DotName DYNAMIC_INSERT = DotName.createSimple( DynamicInsert.class.getName() ); + DotName DYNAMIC_UPDATE = DotName.createSimple( DynamicUpdate.class.getName() ); DotName FETCH = DotName.createSimple( Fetch.class.getName() ); DotName FETCH_PROFILE = DotName.createSimple( FetchProfile.class.getName() ); DotName FETCH_PROFILES = DotName.createSimple( FetchProfiles.class.getName() ); + DotName FETCH_OVERRIDE = DotName.createSimple( FetchProfile.FetchOverride.class.getName() ); DotName FILTER = DotName.createSimple( Filter.class.getName() ); + DotName FILTERS = DotName.createSimple( Filters.class.getName() ); DotName FILTER_DEF = DotName.createSimple( FilterDef.class.getName() ); DotName FILTER_DEFS = DotName.createSimple( FilterDefs.class.getName() ); DotName FILTER_JOIN_TABLE = DotName.createSimple( FilterJoinTable.class.getName() ); DotName FILTER_JOIN_TABLES = DotName.createSimple( FilterJoinTables.class.getName() ); - DotName FILTERS = DotName.createSimple( Filters.class.getName() ); DotName FOREIGN_KEY = DotName.createSimple( ForeignKey.class.getName() ); DotName FORMULA = DotName.createSimple( Formula.class.getName() ); DotName GENERATED = DotName.createSimple( Generated.class.getName() ); @@ -147,11 +158,13 @@ public interface HibernateDotNames { DotName MANY_TO_ANY = DotName.createSimple( ManyToAny.class.getName() ); DotName MAP_KEY_TYPE = DotName.createSimple( MapKeyType.class.getName() ); DotName META_VALUE = DotName.createSimple( MetaValue.class.getName() ); + DotName MULTI_TENANT = DotName.createSimple( MultiTenancy.class.getName() ); DotName NAMED_NATIVE_QUERIES = DotName.createSimple( NamedNativeQueries.class.getName() ); DotName NAMED_NATIVE_QUERY = DotName.createSimple( NamedNativeQuery.class.getName() ); DotName NAMED_QUERIES = DotName.createSimple( NamedQueries.class.getName() ); DotName NAMED_QUERY = DotName.createSimple( NamedQuery.class.getName() ); DotName NATURAL_ID = DotName.createSimple( NaturalId.class.getName() ); + DotName NATURAL_ID_CACHE = DotName.createSimple( NaturalIdCache.class.getName() ); DotName NOT_FOUND = DotName.createSimple( NotFound.class.getName() ); DotName ON_DELETE = DotName.createSimple( OnDelete.class.getName() ); DotName OPTIMISTIC_LOCK = DotName.createSimple( OptimisticLock.class.getName() ); @@ -160,9 +173,13 @@ public interface HibernateDotNames { DotName PARAMETER = DotName.createSimple( Parameter.class.getName() ); DotName PARENT = DotName.createSimple( Parent.class.getName() ); DotName PERSISTER = DotName.createSimple( Persister.class.getName() ); + DotName POLYMORPHISM = DotName.createSimple( Polymorphism.class.getName() ); DotName PROXY = DotName.createSimple( Proxy.class.getName() ); DotName ROW_ID = DotName.createSimple( RowId.class.getName() ); + DotName SELECT_BEFORE_UPDATE = DotName.createSimple( SelectBeforeUpdate.class.getName() ); DotName SORT = DotName.createSimple( Sort.class.getName() ); + DotName SORT_COMPARATOR = DotName.createSimple( SortComparator.class.getName()); + DotName SORT_NATURAL = DotName.createSimple( SortNatural.class.getName() ); DotName SOURCE = DotName.createSimple( Source.class.getName() ); DotName SQL_DELETE = DotName.createSimple( SQLDelete.class.getName() ); DotName SQL_DELETE_ALL = DotName.createSimple( SQLDeleteAll.class.getName() ); @@ -173,6 +190,8 @@ public interface HibernateDotNames { DotName TABLE = DotName.createSimple( Table.class.getName() ); DotName TABLES = DotName.createSimple( Tables.class.getName() ); DotName TARGET = DotName.createSimple( Target.class.getName() ); + DotName TENANT_COLUMN = DotName.createSimple( TenantColumn.class.getName() ); + DotName TENANT_FORMULA = DotName.createSimple( TenantFormula.class.getName() ); DotName TUPLIZER = DotName.createSimple( Tuplizer.class.getName() ); DotName TUPLIZERS = DotName.createSimple( Tuplizers.class.getName() ); DotName TYPE = DotName.createSimple( Type.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java index 20aa8a30e1..182c6c3b90 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations.util; import javax.persistence.Access; import javax.persistence.AccessType; @@ -37,6 +37,7 @@ import javax.persistence.Column; import javax.persistence.ColumnResult; import javax.persistence.Convert; import javax.persistence.Converter; +import javax.persistence.Converts; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; @@ -53,10 +54,12 @@ import javax.persistence.ExcludeDefaultListeners; import javax.persistence.ExcludeSuperclassListeners; import javax.persistence.FetchType; import javax.persistence.FieldResult; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.IdClass; +import javax.persistence.Index; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; @@ -75,10 +78,16 @@ import javax.persistence.MapKeyJoinColumns; import javax.persistence.MapKeyTemporal; import javax.persistence.MappedSuperclass; import javax.persistence.MapsId; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.NamedEntityGraphs; import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.NamedStoredProcedureQueries; +import javax.persistence.NamedStoredProcedureQuery; +import javax.persistence.NamedSubgraph; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderBy; @@ -103,6 +112,7 @@ import javax.persistence.SecondaryTables; import javax.persistence.SequenceGenerator; import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMappings; +import javax.persistence.StoredProcedureParameter; import javax.persistence.Table; import javax.persistence.TableGenerator; import javax.persistence.Temporal; @@ -133,6 +143,7 @@ public interface JPADotNames { DotName COLUMN_RESULT = DotName.createSimple( ColumnResult.class.getName() ); DotName CONVERT = DotName.createSimple( Convert.class.getName() ); DotName CONVERTER = DotName.createSimple( Converter.class.getName() ); + DotName CONVERTS = DotName.createSimple( Converts.class.getName() ); DotName DISCRIMINATOR_COLUMN = DotName.createSimple( DiscriminatorColumn.class.getName() ); DotName DISCRIMINATOR_TYPE = DotName.createSimple( DiscriminatorType.class.getName() ); DotName DISCRIMINATOR_VALUE = DotName.createSimple( DiscriminatorValue.class.getName() ); @@ -149,13 +160,15 @@ public interface JPADotNames { DotName EXCLUDE_SUPERCLASS_LISTENERS = DotName.createSimple( ExcludeSuperclassListeners.class.getName() ); DotName FETCH_TYPE = DotName.createSimple( FetchType.class.getName() ); DotName FIELD_RESULT = DotName.createSimple( FieldResult.class.getName() ); + DotName FOREIGNKEY = DotName.createSimple( ForeignKey.class.getName() ); DotName GENERATION_TYPE = DotName.createSimple( GenerationType.class.getName() ); DotName GENERATED_VALUE = DotName.createSimple( GeneratedValue.class.getName() ); DotName ID = DotName.createSimple( Id.class.getName() ); DotName ID_CLASS = DotName.createSimple( IdClass.class.getName() ); + DotName INDEX = DotName.createSimple( Index.class.getName() ); + DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName INHERITANCE_TYPE = DotName.createSimple( InheritanceType.class.getName() ); DotName JOIN_COLUMN = DotName.createSimple( JoinColumn.class.getName() ); - DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName JOIN_COLUMNS = DotName.createSimple( JoinColumns.class.getName() ); DotName JOIN_TABLE = DotName.createSimple( JoinTable.class.getName() ); DotName LOB = DotName.createSimple( Lob.class.getName() ); @@ -171,10 +184,16 @@ public interface JPADotNames { DotName MAP_KEY_TEMPORAL = DotName.createSimple( MapKeyTemporal.class.getName() ); DotName MAPPED_SUPERCLASS = DotName.createSimple( MappedSuperclass.class.getName() ); DotName MAPS_ID = DotName.createSimple( MapsId.class.getName() ); + DotName NAMED_ATTRIBUTE_NODE = DotName.createSimple( NamedAttributeNode.class.getName() ); + DotName NAMED_ENTITY_GRAPH = DotName.createSimple( NamedEntityGraph.class.getName() ); + DotName NAMED_ENTITY_GRAPHS = DotName.createSimple( NamedEntityGraphs.class.getName() ); DotName NAMED_NATIVE_QUERIES = DotName.createSimple( NamedNativeQueries.class.getName() ); DotName NAMED_NATIVE_QUERY = DotName.createSimple( NamedNativeQuery.class.getName() ); DotName NAMED_QUERIES = DotName.createSimple( NamedQueries.class.getName() ); DotName NAMED_QUERY = DotName.createSimple( NamedQuery.class.getName() ); + DotName NAMED_STORED_PROCEDURE_QUERIES = DotName.createSimple( NamedStoredProcedureQueries.class.getName() ); + DotName NAMED_STORED_PROCEDURE_QUERY = DotName.createSimple( NamedStoredProcedureQuery.class.getName() ); + DotName NAMED_SUB_GRAPH = DotName.createSimple( NamedSubgraph.class.getName() ); DotName ONE_TO_MANY = DotName.createSimple( OneToMany.class.getName() ); DotName ONE_TO_ONE = DotName.createSimple( OneToOne.class.getName() ); DotName ORDER_BY = DotName.createSimple( OrderBy.class.getName() ); @@ -199,6 +218,7 @@ public interface JPADotNames { DotName SEQUENCE_GENERATOR = DotName.createSimple( SequenceGenerator.class.getName() ); DotName SQL_RESULT_SET_MAPPING = DotName.createSimple( SqlResultSetMapping.class.getName() ); DotName SQL_RESULT_SET_MAPPINGS = DotName.createSimple( SqlResultSetMappings.class.getName() ); + DotName STORED_PROCEDURE_PARAMETER = DotName.createSimple( StoredProcedureParameter.class.getName() ); DotName TABLE = DotName.createSimple( Table.class.getName() ); DotName TABLE_GENERATOR = DotName.createSimple( TableGenerator.class.getName() ); DotName TEMPORAL = DotName.createSimple( Temporal.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPAListenerHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPAListenerHelper.java new file mode 100644 index 0000000000..bcaee034b6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPAListenerHelper.java @@ -0,0 +1,365 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.PersistenceException; +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; +import javax.persistence.PostRemove; +import javax.persistence.PostUpdate; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.Type; + +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.JpaCallbackSourceImpl; +import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.internal.source.annotations.entity.MappedSuperclass; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; + +/** + * @author Strong Liu + */ +public class JPAListenerHelper { + private static final Map, DotName> EVENT_TYPE; + + static { + EVENT_TYPE = new HashMap, DotName>( 7 ); + EVENT_TYPE.put( PrePersist.class, JPADotNames.PRE_PERSIST ); + EVENT_TYPE.put( PreRemove.class, JPADotNames.PRE_REMOVE ); + EVENT_TYPE.put( PreUpdate.class, JPADotNames.PRE_UPDATE ); + EVENT_TYPE.put( PostLoad.class, JPADotNames.POST_LOAD ); + EVENT_TYPE.put( PostPersist.class, JPADotNames.POST_PERSIST ); + EVENT_TYPE.put( PostRemove.class, JPADotNames.POST_REMOVE ); + EVENT_TYPE.put( PostUpdate.class, JPADotNames.POST_UPDATE ); + + } + + private final EntityClass entityClass; + private final EntityBindingContext context; + private final List mappingClassHierarchy; + + public JPAListenerHelper(EntityClass entityClass) { + this.entityClass = entityClass; + this.context = entityClass.getLocalBindingContext(); + this.mappingClassHierarchy = buildHierarchy(); + } + + private List buildHierarchy() { + List list = new ArrayList(); + list.add( entityClass ); + if ( !excludeSuperClassListeners( entityClass.getClassInfo() ) ) { + for ( MappedSuperclass mappedSuperclass : entityClass.getMappedSuperclasses() ) { + list.add( mappedSuperclass ); + if ( excludeSuperClassListeners( mappedSuperclass.getClassInfo() ) ) { + break; + } + + } + } + return list; + } + + private List findAllEntityListeners() { + List result = new ArrayList(); + for ( final ConfiguredClass configuredClass : mappingClassHierarchy ) { + List list = configuredClass.getClassInfo() + .annotations() + .get( JPADotNames.ENTITY_LISTENERS ); + if ( CollectionHelper.isNotEmpty( list ) ) { + result.addAll( list ); + } + } + return result; + } + + + public List bindJPAListeners() { + final List callbackClassList = new ArrayList(); + bindEntityCallbackEvents( callbackClassList ); + bindEntityListeners( callbackClassList ); + bindDefaultListeners( callbackClassList ); + return callbackClassList; + } + + private void bindEntityCallbackEvents(List callbackClassList) { + Map overrideMethodCheck = new HashMap(); + for ( final ConfiguredClass configuredClass : mappingClassHierarchy ) { + try { + internalProcessCallbacks( + configuredClass.getClassInfo(), + callbackClassList, + false, + false, + overrideMethodCheck + ); + } + catch ( PersistenceException error ) { + throw new PersistenceException( error.getMessage() + "entity listener " + configuredClass.getName() ); + } + } + } + + private void bindEntityListeners(List callbackClassList) { + List entityListenerAnnotations = findAllEntityListeners(); + for ( AnnotationInstance annotation : entityListenerAnnotations ) { + Type[] types = annotation.value().asClassArray(); + for ( int i = types.length - 1; i >= 0; i-- ) { + String callbackClassName = types[i].name().toString(); + try { + processJpaCallbacks( callbackClassName, true, callbackClassList, null ); + } + catch ( PersistenceException error ) { + throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName ); + } + } + } + } + + private void processJpaCallbacks( + final String instanceCallbackClassName, + final boolean isListener, + final List callbackClassList, + final Map overrideMethodCheck) { + final ClassInfo callbackClassInfo = findClassInfoByName( instanceCallbackClassName ); + internalProcessCallbacks( callbackClassInfo, callbackClassList, isListener, false, overrideMethodCheck ); + } + + + private void bindDefaultListeners(final List callbackClassList) { + // Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded) + + Collection defaultEntityListenerAnnotations = context + .getIndex() + .getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); + for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) { + for ( Type callbackClass : annotation.value().asClassArray() ) { + String callbackClassName = callbackClass.name().toString(); + ClassInfo callbackClassInfo = findClassInfoByName( callbackClassName ); + try { + processDefaultJpaCallbacks( callbackClassInfo, callbackClassList ); + } + catch ( PersistenceException error ) { + throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName ); + } + } + } + } + + private static boolean excludeDefaultListeners(ClassInfo classInfo) { + return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_DEFAULT_LISTENERS ); + } + + private static boolean excludeSuperClassListeners(ClassInfo classInfo) { + return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ); + } + + private static boolean isNotRootObject(DotName name) { + return name != null && !JandexHelper.OBJECT.equals( name ); + } + + private void processDefaultJpaCallbacks( + final ClassInfo callbackClassInfo, + final List jpaCallbackClassList) { + if ( excludeDefaultListeners( callbackClassInfo ) ) { + return; + } + // Process superclass first if available and not excluded + if ( !excludeSuperClassListeners( callbackClassInfo ) ) { + DotName superName = callbackClassInfo.superName(); + if ( isNotRootObject( superName ) ) { + processDefaultJpaCallbacks( findClassInfoByName( superName.toString() ), jpaCallbackClassList ); + } + } + internalProcessCallbacks( callbackClassInfo, jpaCallbackClassList, true, true, null ); + } + + private ClassInfo findClassInfoByName(String name) { + ClassInfo classInfo = context.getClassInfo( name ); + if ( classInfo == null ) { + JandexHelper.throwNotIndexException( name ); + } + return classInfo; + } + + private void internalProcessCallbacks( + final ClassInfo callbackClassInfo, + final List callbackClassList, + final boolean isListener, + final boolean isDefault, + final Map overrideMethodCheck) { + final Map, String> callbacksByType = new HashMap, String>( 7 ); + createCallback( + PrePersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PreRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PreUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PostLoad.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PostPersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PostRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + createCallback( + PostUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck + ); + if ( !callbacksByType.isEmpty() ) { + final String name = callbackClassInfo.name().toString(); + final JpaCallbackSource callbackSource = new JpaCallbackSourceImpl( name, callbacksByType, isListener ); + callbackClassList.add( 0, callbackSource ); + } + } + + + /** + * @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist}, + * {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad}, + * {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}. + * @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name. + * @param callbackClassInfo Jandex ClassInfo of callback method's container, should be either entity/mapped superclass or entity listener class. + * @param isListener Is this callback method defined in an entity listener class or not. + */ + private void createCallback( + final Class callbackTypeClass, + final Map, String> callbacksByClass, + final ClassInfo callbackClassInfo, + final boolean isListener, + final boolean isDefault, + final Map overrideMethodCheck) { + + final Collection annotationInstances; + if ( isDefault ) { + annotationInstances = context.getIndex().getAnnotations( EVENT_TYPE.get( callbackTypeClass ) ); + } + else { + List temp = callbackClassInfo.annotations().get( EVENT_TYPE.get( callbackTypeClass ) ); + annotationInstances = temp != null ? temp : Collections.EMPTY_LIST; + } + + //there should be only one callback method per callbackType, isn't it? + //so only one callbackAnnotation? + for ( AnnotationInstance callbackAnnotation : annotationInstances ) { + MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target(); + validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener ); + final String name = methodInfo.name(); + if ( overrideMethodCheck != null && overrideMethodCheck.containsKey( name ) ) { + continue; + } + else if ( overrideMethodCheck != null ) { + overrideMethodCheck.put( name, null ); + } + if ( !isDefault ) { + callbacksByClass.put( callbackTypeClass, name ); + } + else if ( methodInfo.declaringClass().name().equals( callbackClassInfo.name() ) ) { + if ( methodInfo.args().length != 1 ) { + throw new PersistenceException( + String.format( + "Callback method %s must have exactly one argument defined as either Object or %s in ", + name, + entityClass.getName() + ) + ); + } + callbacksByClass.put( callbackTypeClass, name ); + } + } + } + + + /** + * Applying JPA Spec rules to validate listener callback method mapping. + * + * @param methodInfo The lifecycle callback method. + * @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist}, + * {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad}, + * {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}. + * @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name. + * @param isListener Is this callback method defined in an entity listener class or not. + */ + private void validateMethod( + MethodInfo methodInfo, + Class callbackTypeClass, + Map, String> callbacksByClass, + boolean isListener) { + final String name = methodInfo.name(); + + if ( methodInfo.returnType().kind() != Type.Kind.VOID ) { + throw new PersistenceException( "Callback method " + name + " must have a void return type in " ); + } + if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) { + throw new PersistenceException( "Callback method " + name + " must not be static or final in " ); + } + Type[] argTypes = methodInfo.args(); + + if ( isListener ) { + if ( argTypes.length != 1 ) { + throw new PersistenceException( "Callback method " + name + " must have exactly one argument in " ); + } + String argTypeName = argTypes[0].name().toString(); + if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( entityClass.getName() ) ) { + Class typeClass = entityClass.getLocalBindingContext().locateClassByName( argTypeName ); + if ( !typeClass.isAssignableFrom( entityClass.getConfiguredClass() ) ) { + throw new PersistenceException( + "The argument for callback method " + name + + " must be defined as either Object or " + entityClass.getName() + " in " + ); + } + } + } + else if ( argTypes.length != 0 ) { + throw new PersistenceException( "Callback method " + name + " must have no arguments in " ); + } + if ( callbacksByClass.containsKey( callbackTypeClass ) ) { + throw new PersistenceException( + "Only one method may be annotated as a " + callbackTypeClass.getSimpleName() + + " callback method in " + ); + } + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelper.java similarity index 57% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelper.java index 0a7270300d..f3aae7d1fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelper.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,29 +21,36 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.internal.source.annotations.util; import java.beans.Introspector; +import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Array; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; +import org.hibernate.MappingException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.util.type.PrimitiveWrapperHelper; - +import org.hibernate.service.ServiceRegistry; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.jboss.jandex.Indexer; import org.jboss.jandex.MethodInfo; import org.jboss.jandex.Type; @@ -52,10 +59,11 @@ import org.jboss.jandex.Type; * Utility methods for working with the jandex annotation index. * * @author Hardy Ferentschik + * @author Brett Meyer */ public class JandexHelper { private static final Map DEFAULT_VALUES_BY_ELEMENT = new HashMap(); - + public static final DotName OBJECT = DotName.createSimple( Object.class.getName() ); private JandexHelper() { } @@ -81,6 +89,7 @@ public class JandexHelper { *
        1. Boolean
        2. *
        3. String
        4. *
        5. AnnotationInstance
        6. + * @param classLoaderService ClassLoaderService * * @return the value if not {@code null}, else the default value if not * {@code null}, else {@code null}. @@ -89,44 +98,6 @@ public class JandexHelper { * when retrieving the value. */ @SuppressWarnings("unchecked") - public static T getValue(AnnotationInstance annotation, String element, Class type) throws AssertionFailure { - if ( Class.class.equals( type ) ) { - throw new AssertionFailure( - "Annotation parameters of type Class should be retrieved as strings (fully qualified class names)" - ); - } - - if ( type.isPrimitive() ) { - type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass(); - } - - // try getting the untyped value from Jandex - AnnotationValue annotationValue = annotation.value( element ); - - try { - if ( annotationValue != null ) { - return explicitAnnotationParameter( annotationValue, type ); - } - else { - return defaultAnnotationParameter( getDefaultValue( annotation, element ), type ); - } - } - catch ( ClassCastException e ) { - throw new AssertionFailure( - String.format( - "the annotation property %s of annotation %s is not of type %s", - element, - annotation.name(), - type.getName() - ), - e - ); - } - } - - // THIS IS FOR 4.3.x AND SHOULD BE CONSIDERED TEMPORARY. HHH-8118 corrected CL use in JandexHelper by adding - // CLS as method arguments. But that was done in the metamodel branch only before I knew that master added a few - // uses. HHH-8316 needs it for 4.3. DO NOT LET THIS GET MERGED INTO METAMODEL! public static T getValue(AnnotationInstance annotation, String element, Class type, ClassLoaderService classLoaderService) throws AssertionFailure { if ( Class.class.equals( type ) ) { @@ -153,12 +124,11 @@ public class JandexHelper { catch ( ClassCastException e ) { throw new AssertionFailure( String.format( - "the annotation property %s of annotation %s is not of type %s", + "the annotation property [%s] of annotation [@%s] is not of type %s", element, annotation.name(), type.getName() - ), - e + ) ); } } @@ -171,6 +141,7 @@ public class JandexHelper { * @param annotation the annotation containing the enumerated element with the supplied name * @param element the name of the enumerated element value to be retrieve * @param type the type to which to convert the value before being returned + * @param classLoaderService ClassLoaderService * * @return the value converted to the supplied enumerated type if the value is not null, else the default value if * not null, else null. @@ -178,10 +149,11 @@ public class JandexHelper { * @see #getValue(AnnotationInstance, String, Class) */ @SuppressWarnings("unchecked") - public static > T getEnumValue(AnnotationInstance annotation, String element, Class type) { + public static > T getEnumValue(AnnotationInstance annotation, String element, Class type, + ClassLoaderService classLoaderService) { AnnotationValue val = annotation.value( element ); if ( val == null ) { - return (T) getDefaultValue( annotation, element ); + return (T) getDefaultValue( annotation, element, classLoaderService ); } return Enum.valueOf( type, val.asEnum() ); } @@ -220,6 +192,88 @@ public class JandexHelper { return propertyName; } } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to retrieve from the class info + * + * @return the list of annotations specified in the class + */ + public static List getAnnotations( + ClassInfo classInfo, DotName annotationName ) { + if ( classInfo.annotations().containsKey( annotationName ) ) { + return classInfo.annotations().get( annotationName ); + } else { + return Collections.emptyList(); + } + } + + + + public static Collection getAnnotations( + final IndexView indexView, + final DotName singularDotName, + final DotName pluralDotName, + final ClassLoaderService classLoaderService + ) { + List annotationInstances = new ArrayList(); + annotationInstances.addAll( indexView.getAnnotations( singularDotName ) ); + + Collection pluralAnnotations = indexView.getAnnotations( pluralDotName ); + for ( AnnotationInstance ann : pluralAnnotations ) { + AnnotationInstance[] typeDefAnnotations = getValue( + ann, + "value", + AnnotationInstance[].class, + classLoaderService + ); + annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) ); + } + return annotationInstances; + } + + public static Collection getAnnotations( + final Map> annotations, + final DotName singularDotName, + final DotName pluralDotName, + final ClassLoaderService classLoaderService) { + return getAnnotations( annotations, singularDotName, pluralDotName, false, classLoaderService ); + } + + public static Collection getAnnotations( + final Map> annotations, + final DotName singularDotName, + final DotName pluralDotName, + final boolean checkSingle, + final ClassLoaderService classLoaderService) { + List annotationInstances = new ArrayList(); + + List list = annotations.get( singularDotName ); + if ( list != null ) { + if ( checkSingle ) { + assertSingularAnnotationInstances( list ); + } + annotationInstances.addAll( list ); + } + Collection pluralAnnotations = annotations.get( pluralDotName ); + if ( pluralAnnotations != null ) { + if ( checkSingle ) { + assertSingularAnnotationInstances( pluralAnnotations ); + } + for ( AnnotationInstance ann : pluralAnnotations ) { + AnnotationInstance[] typeDefAnnotations = getValue( + ann, + "value", + AnnotationInstance[].class, + classLoaderService + ); + annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) ); + } + } + + + return annotationInstances; + } /** * @param classInfo the class info from which to retrieve the annotation instance @@ -234,6 +288,49 @@ public class JandexHelper { return getSingleAnnotation( classInfo.annotations(), annotationName ); } + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to retrieve from the class info + * @param target the annotation target + * + * @return the single annotation defined on the class with the supplied target or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation( + ClassInfo classInfo, + DotName annotationName, + Class< ? extends AnnotationTarget > target ) { + List annotationList = classInfo.annotations().get( annotationName ); + if ( annotationList == null ) { + return null; + } + annotationList = new ArrayList< AnnotationInstance >( annotationList ); + for ( Iterator< AnnotationInstance > iter = annotationList.iterator(); iter.hasNext(); ) { + if ( !target.isInstance( iter.next().target() ) ) { + iter.remove(); + } + } + if ( annotationList.isEmpty() ) { + return null; + } + if ( annotationList.size() == 1 ) { + return annotationList.get( 0 ); + } + assertSingularAnnotationInstances( annotationList ); + return null;//only here to make compiler happy + } + + private static void assertSingularAnnotationInstances(Collection annotationInstances) { + if ( annotationInstances.size() > 1 ) { + throw new AssertionFailure( + "Found more than one instance of the annotation " + + annotationInstances.iterator().next().name().toString() + + ". Expected was one." + ); + } + } + /** * @param annotations List of annotation instances keyed against their dot name. * @param annotationName the annotation to retrieve from map @@ -244,20 +341,69 @@ public class JandexHelper { */ public static AnnotationInstance getSingleAnnotation(Map> annotations, DotName annotationName) throws AssertionFailure { + return getSingleAnnotation( annotations, annotationName, null ); + } + + /** + * Similar to {@link #getSingleAnnotation(Map, DotName)}, but searches for + * the single annotation on the given target. Useful for annotations that + * can appear both on a Class and Method/Field level. Ex: custom SQL annotations. + * + * @param annotations List of annotation instances keyed against their dot name. + * @param annotationName the annotation to retrieve from map + * @param target the annotation target + * + * @return the single annotation of the specified dot name or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation(Map> annotations, + DotName annotationName, AnnotationTarget target) throws AssertionFailure { List annotationList = annotations.get( annotationName ); if ( annotationList == null ) { return null; } - else if ( annotationList.size() == 1 ) { - return annotationList.get( 0 ); + final List targetedAnnotationList; + if ( target != null ) { + targetedAnnotationList = new ArrayList(); + for ( AnnotationInstance annotation : annotationList ) { + if ( getTargetName( annotation.target() ).equals( getTargetName( target ) ) ) { + targetedAnnotationList.add( annotation ); + } + } } else { - throw new AssertionFailure( - "Found more than one instance of the annotation " - + annotationList.get( 0 ).name().toString() - + ". Expected was one." - ); + targetedAnnotationList = annotationList; } + if ( targetedAnnotationList.size() == 0 ) { + return null; + } + else if ( targetedAnnotationList.size() == 1 ) { + return targetedAnnotationList.get( 0 ); + } + else { + throw new AssertionFailure( "Found more than one instance of the annotation " + + targetedAnnotationList.get( 0 ).name().toString() + ". Expected was one." ); + } + } + + public static void throwNotIndexException(String className){ + throw new MappingException( "Class " + className +" is not indexed, probably means this class should be explicitly added" + + "into MatadataSources" ); + + } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to check + * + * @return returns {@code true} if the annotations contains only a single instance of specified annotation or {@code false} + * otherwise. + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static boolean containsSingleAnnotation( ClassInfo classInfo, DotName annotationName ) { + return containsSingleAnnotation( classInfo.annotations(), annotationName ); } /** @@ -268,8 +414,7 @@ public class JandexHelper { * * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. */ - public static boolean containsSingleAnnotations(Map> annotations, DotName annotationName) - throws AssertionFailure { + public static boolean containsSingleAnnotation( Map> annotations, DotName annotationName ) { return getSingleAnnotation( annotations, annotationName ) != null; } @@ -281,7 +426,7 @@ public class JandexHelper { * * @return an annotation repository w/ all the annotation discovered in the specified classes */ - public static Index indexForClass(ClassLoaderService classLoaderService, Class... classes) { + public static IndexView indexForClass(ClassLoaderService classLoaderService, Class... classes) { Indexer indexer = new Indexer(); for ( Class clazz : classes ) { InputStream stream = classLoaderService.locateResourceStream( @@ -308,7 +453,8 @@ public class JandexHelper { return indexer.complete(); } - public static Map> getMemberAnnotations(ClassInfo classInfo, String name) { + public static Map> getMemberAnnotations( + ClassInfo classInfo, String name, ServiceRegistry serviceRegistry ) { if ( classInfo == null ) { throw new IllegalArgumentException( "classInfo cannot be null" ); } @@ -316,18 +462,29 @@ public class JandexHelper { if ( name == null ) { throw new IllegalArgumentException( "name cannot be null" ); } - + + // Allow a property name to be used even if the entity uses method access. + // TODO: Is this reliable? Is there a better way to do it? + String getterName = ""; + try { + Class beanClass = serviceRegistry.getService( + ClassLoaderService.class ).classForName( + classInfo.name().toString() ); + Method getter = new PropertyDescriptor(name, beanClass) + .getReadMethod(); + if ( getter != null ) { + getterName = getter.getName(); + } + } catch ( Exception e ) { + // do nothing + } + Map> annotations = new HashMap>(); for ( List annotationList : classInfo.annotations().values() ) { for ( AnnotationInstance instance : annotationList ) { - String targetName = null; - if ( instance.target() instanceof FieldInfo ) { - targetName = ( (FieldInfo) instance.target() ).name(); - } - else if ( instance.target() instanceof MethodInfo ) { - targetName = ( (MethodInfo) instance.target() ).name(); - } - if ( targetName != null && name.equals( targetName ) ) { + String targetName = getTargetName( instance.target() ); + if ( targetName != null && ( name.equals( targetName ) + || getterName.equals( targetName ) ) ) { addAnnotationToMap( instance, annotations ); } } @@ -348,34 +505,7 @@ public class JandexHelper { list.add( instance ); } - private static Object getDefaultValue(AnnotationInstance annotation, String element) { - String name = annotation.name().toString(); - String fqElement = name + '.' + element; - Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement ); - if ( val != null ) { - return val; - } - try { - val = Index.class.getClassLoader().loadClass( name ).getMethod( element ).getDefaultValue(); - DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val ); - return val == null ? null : val; - } - catch ( RuntimeException error ) { - throw error; - } - catch ( Exception error ) { - throw new AssertionFailure( - String.format( "The annotation %s does not define a parameter '%s'", name, element ), - error - ); - } - } - - // THIS IS FOR 4.3.x AND SHOULD BE CONSIDERED TEMPORARY. HHH-8118 corrected CL use in JandexHelper by adding - // CLS as method arguments. But that was done in the metamodel branch only before I knew that master added a few - // uses. HHH-8316 needs it for 4.3. DO NOT LET THIS GET MERGED INTO METAMODEL! - private static Object getDefaultValue(AnnotationInstance annotation, String element, - ClassLoaderService classLoaderService) { + private static Object getDefaultValue(AnnotationInstance annotation, String element, ClassLoaderService classLoaderService) { String name = annotation.name().toString(); String fqElement = name + '.' + element; Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement ); @@ -413,7 +543,7 @@ public class JandexHelper { if ( defaultValue.getClass().isArray() && defaultValue.getClass().getComponentType().isAnnotation() ) { returnValue = new AnnotationInstance[0]; } - return type.cast( returnValue ); + return type.cast( nullIfUndefined( returnValue, type ) ); } private static T explicitAnnotationParameter(AnnotationValue annotationValue, Class type) { @@ -435,7 +565,44 @@ public class JandexHelper { } returnValue = arr; } + return type.cast( nullIfUndefined( returnValue, type ) ); + } - return type.cast( returnValue ); + /** + * Swaps type-specific undefined values with {@code null}. + * + * @param value The value + * @param type The target type + * + * @return {@code null} if value is deemed to UNDEFINED; value itself otherwise. + */ + private static Object nullIfUndefined(Object value, Class type) { + if ( value instanceof Type ) { + value = ( (Type) value ).name().toString(); + if ( void.class.getName().equals( value ) ) { + value = null; + } + } + + if ( String.class.equals( type ) ) { + if ( "".equals( type.cast( value ) ) ) { + value = null; + } + } + return value; + } + + private static String getTargetName(AnnotationTarget target) { + String targetName = null; + if ( target instanceof FieldInfo ) { + targetName = ( (FieldInfo) target ).name(); + } + else if ( target instanceof MethodInfo ) { + targetName = ( (MethodInfo) target ).name(); + } + else if ( target instanceof ClassInfo ) { + targetName = ( (ClassInfo) target ).name().toString(); + } + return targetName; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/MappingAssertion.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/MappingAssertion.java new file mode 100644 index 0000000000..8363960517 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/MappingAssertion.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; + +import org.hibernate.AnnotationException; + +/** + * Utility class that applying some mapping assertion. + * + * @author Strong Liu + */ +public class MappingAssertion { + /** + * Check if a class is wrongly placed both {@link javax.persistence.Entity @Entity} and {@link javax.persistence.MappedSuperclass @MappedSuperclass} annotations. + * + * @param jpaEntityAnnotation The {@link javax.persistence.Entity @Entity} annotation instance. + * @param mappedSuperClassAnnotation The {@link javax.persistence.MappedSuperclass @MappedSuperclass} annotation instance. + * @param className Class name that being asserted. + */ + static void assertNotEntityAndMappedSuperClass( + AnnotationInstance jpaEntityAnnotation, + AnnotationInstance mappedSuperClassAnnotation, + String className) { + if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) { + throw new AnnotationException( + "An entity cannot be annotated with both @Entity and @MappedSuperclass. " + className + " has both annotations." + ); + } + } + + /** + * Check if a class is wrongly placed both {@link javax.persistence.Entity @Entity} and {@link javax.persistence.Embeddable @Embeddable} annotations. + * + * @param jpaEntityAnnotation The {@link javax.persistence.Entity @Entity} annotation instance. + * @param embeddableAnnotation The {@link javax.persistence.Embeddable @Embeddable} annotation instance. + * @param className Class name that being asserted. + */ + static void assertNotEntityAndEmbeddable(AnnotationInstance jpaEntityAnnotation, AnnotationInstance embeddableAnnotation, String className) { + if ( jpaEntityAnnotation != null && embeddableAnnotation != null ) { + throw new AnnotationException( + "An entity cannot be annotated with both @Entity and @Embeddable. " + className + " has both annotations." + ); + } + } + + + /** + * Check if the sub-entity has {@link javax.persistence.Embeddable @Embeddable} or {@link javax.persistence.MappedSuperclass @MappedSuperclass}. + * + * From the JPA Spec, a sub entity class can not has such annotation. + * + * @param subClassInfo The sub entity {@link ClassInfo class}. + */ + static void assertSubEntityIsNotEmbeddableNorMappedSuperclass(ClassInfo subClassInfo) { + if ( JandexHelper.containsSingleAnnotation( subClassInfo, JPADotNames.EMBEDDABLE ) ) { + throw new AnnotationException( "An embeddable cannot extend an entity: " + subClassInfo ); + } + if ( JandexHelper.containsSingleAnnotation( subClassInfo, JPADotNames.MAPPED_SUPERCLASS ) ) { + throw new AnnotationException( "A mapped superclass cannot extend an entity: " + subClassInfo ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/package.html new file mode 100755 index 0000000000..2e9418fc1c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/package.html @@ -0,0 +1,33 @@ + + + + + +

          + Utility classes for processing the annotation configuration. +

          + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/PseudoJpaDotNames.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/PseudoJpaDotNames.java index de9a703dba..f2de81d23a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/PseudoJpaDotNames.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; import org.jboss.jandex.DotName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/AbstractAnnotationFilter.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/AbstractAnnotationFilter.java index ff1530e03a..75f2c19e71 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/AbstractAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.internal.source.annotations.xml.filter; import java.util.Arrays; import java.util.HashSet; @@ -29,11 +29,11 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.IndexBuilder; + /** * @author Strong Liu */ @@ -76,4 +76,4 @@ abstract class AbstractAnnotationFilter implements IndexedAnnotationFilter { protected DotName[] targetAnnotation() { return EMPTY_DOTNAME_ARRAY; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/ExclusiveAnnotationFilter.java similarity index 91% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/ExclusiveAnnotationFilter.java index a666ffadc2..bc0510b717 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/ExclusiveAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.internal.source.annotations.xml.filter; import java.util.ArrayList; import java.util.Collections; @@ -31,23 +31,24 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.metamodel.source.annotations.xml.mocker.MockHelper; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.MockHelper; + /** * @author Strong Liu */ class ExclusiveAnnotationFilter extends AbstractAnnotationFilter { public static ExclusiveAnnotationFilter INSTANCE = new ExclusiveAnnotationFilter(); - private DotName[] targetNames; - private List exclusiveGroupList; + private final DotName[] targetNames; + private final List exclusiveGroupList; private ExclusiveAnnotationFilter() { - this.exclusiveGroupList = getExclusiveGroupList(); + this.exclusiveGroupList = new ArrayList(); + fillExclusiveGroupList(); Set names = new HashSet(); for ( ExclusiveGroup group : exclusiveGroupList ) { names.addAll( group.getNames() ); @@ -55,9 +56,7 @@ class ExclusiveAnnotationFilter extends AbstractAnnotationFilter { targetNames = names.toArray( new DotName[names.size()] ); } - private List getExclusiveGroupList() { - if ( exclusiveGroupList == null ) { - exclusiveGroupList = new ArrayList(); + private void fillExclusiveGroupList() { ExclusiveGroup group = new ExclusiveGroup(); group.add( ENTITY ); group.add( MAPPED_SUPERCLASS ); @@ -113,8 +112,6 @@ class ExclusiveAnnotationFilter extends AbstractAnnotationFilter { group.scope = Scope.ATTRIBUTE; exclusiveGroupList.add( group ); - } - return exclusiveGroupList; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/IndexedAnnotationFilter.java similarity index 86% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/IndexedAnnotationFilter.java index 9a2aaeac52..203fc03415 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/IndexedAnnotationFilter.java @@ -21,14 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; - -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder; +package org.hibernate.metamodel.internal.source.annotations.xml.filter; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.IndexBuilder; + /** * @author Strong Liu */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameAnnotationFilter.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameAnnotationFilter.java index 5635134bca..fad2c811be 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.internal.source.annotations.xml.filter; import java.util.List; @@ -39,20 +39,20 @@ class NameAnnotationFilter extends AbstractAnnotationFilter { indexedAnnotationInstanceList.clear(); } - public static NameTargetAnnotationFilter INSTANCE = new NameTargetAnnotationFilter(); - + public static NameAnnotationFilter INSTANCE = new NameAnnotationFilter(); + private static final DotName[] TARGET_ANNOTATIONS = new DotName[] { + CACHEABLE, + TABLE, + EXCLUDE_DEFAULT_LISTENERS, + EXCLUDE_SUPERCLASS_LISTENERS, + ID_CLASS, + INHERITANCE, + DISCRIMINATOR_VALUE, + DISCRIMINATOR_COLUMN, + ENTITY_LISTENERS + }; @Override protected DotName[] targetAnnotation() { - return new DotName[] { - CACHEABLE, - TABLE, - EXCLUDE_DEFAULT_LISTENERS, - EXCLUDE_SUPERCLASS_LISTENERS, - ID_CLASS, - INHERITANCE, - DISCRIMINATOR_VALUE, - DISCRIMINATOR_COLUMN, - ENTITY_LISTENERS - }; + return TARGET_ANNOTATIONS; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameTargetAnnotationFilter.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameTargetAnnotationFilter.java index 4df19be708..0124f96810 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/filter/NameTargetAnnotationFilter.java @@ -21,17 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.internal.source.annotations.xml.filter; import java.util.Iterator; import java.util.List; -import org.hibernate.metamodel.source.annotations.xml.mocker.MockHelper; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.xml.mocker.MockHelper; + /** * @author Strong Liu */ @@ -49,46 +50,46 @@ class NameTargetAnnotationFilter extends AbstractAnnotationFilter { } public static NameTargetAnnotationFilter INSTANCE = new NameTargetAnnotationFilter(); - + private static final DotName[] TARGET_ANNOTATIONS = new DotName[] { + JPADotNames.LOB, + JPADotNames.ID, + JPADotNames.BASIC, + JPADotNames.GENERATED_VALUE, + JPADotNames.VERSION, + JPADotNames.TRANSIENT, + JPADotNames.ACCESS, + JPADotNames.POST_LOAD, + JPADotNames.POST_PERSIST, + JPADotNames.POST_REMOVE, + JPADotNames.POST_UPDATE, + JPADotNames.PRE_PERSIST, + JPADotNames.PRE_REMOVE, + JPADotNames.PRE_UPDATE, + JPADotNames.EMBEDDED_ID, + JPADotNames.EMBEDDED, + JPADotNames.MANY_TO_ONE, + JPADotNames.MANY_TO_MANY, + JPADotNames.ONE_TO_ONE, + JPADotNames.ONE_TO_MANY, + JPADotNames.ELEMENT_COLLECTION, + JPADotNames.COLLECTION_TABLE, + JPADotNames.COLUMN, + JPADotNames.ENUMERATED, + JPADotNames.JOIN_TABLE, + JPADotNames.TEMPORAL, + JPADotNames.ORDER_BY, + JPADotNames.ORDER_COLUMN, + JPADotNames.JOIN_COLUMN, + JPADotNames.JOIN_COLUMNS, + JPADotNames.MAPS_ID, + JPADotNames.MAP_KEY_TEMPORAL, + JPADotNames.MAP_KEY, + JPADotNames.MAP_KEY_CLASS, + JPADotNames.MAP_KEY_COLUMN, + JPADotNames.MAP_KEY_ENUMERATED + }; @Override protected DotName[] targetAnnotation() { - return new DotName[] { - LOB, - ID, - BASIC, - GENERATED_VALUE, - VERSION, - TRANSIENT, - ACCESS, - POST_LOAD, - POST_PERSIST, - POST_REMOVE, - POST_UPDATE, - PRE_PERSIST, - PRE_REMOVE, - PRE_UPDATE, - EMBEDDED_ID, - EMBEDDED, - MANY_TO_ONE, - MANY_TO_MANY, - ONE_TO_ONE, - ONE_TO_MANY, - ELEMENT_COLLECTION, - COLLECTION_TABLE, - COLUMN, - ENUMERATED, - JOIN_TABLE, - TEMPORAL, - ORDER_BY, - ORDER_COLUMN, - JOIN_COLUMN, - JOIN_COLUMNS, - MAPS_ID, - MAP_KEY_TEMPORAL, - MAP_KEY, - MAP_KEY_CLASS, - MAP_KEY_COLUMN, - MAP_KEY_ENUMERATED - }; + return TARGET_ANNOTATIONS; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractAttributesBuilder.java similarity index 61% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractAttributesBuilder.java index 425b308b01..fcf3f8bbbc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractAttributesBuilder.java @@ -21,27 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbBasic; +import org.hibernate.jaxb.spi.orm.JaxbElementCollection; +import org.hibernate.jaxb.spi.orm.JaxbEmbedded; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddedId; +import org.hibernate.jaxb.spi.orm.JaxbId; +import org.hibernate.jaxb.spi.orm.JaxbManyToMany; +import org.hibernate.jaxb.spi.orm.JaxbManyToOne; +import org.hibernate.jaxb.spi.orm.JaxbOneToMany; +import org.hibernate.jaxb.spi.orm.JaxbOneToOne; +import org.hibernate.jaxb.spi.orm.JaxbTransient; +import org.hibernate.jaxb.spi.orm.JaxbVersion; + /** - * Abstract Parser to handle {@link org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes JaxbAttributes} - * and {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddableAttributes JaxbEmbeddableAttributes}. + * Abstract parse to handle {@link org.hibernate.jaxb.spi.orm.JaxbAttributes JaxbAttributes} + * and {@link org.hibernate.jaxb.spi.orm.JaxbEmbeddableAttributes JaxbEmbeddableAttributes}. * * It would be really helpful if these two classes can implement an interface with those abstract methods in this class. * @@ -59,41 +59,41 @@ abstract class AbstractAttributesBuilder { this.defaults = defaults; } - final void parser() { + final void parse() { for ( JaxbId id : getId() ) { new IdMocker( indexBuilder, classInfo, defaults, id ).process(); } - for ( JaxbTransient transientObj : getTransient() ) { + for ( JaxbTransient transientObj : getAttributesContainer().getTransient() ) { new TransientMocker( indexBuilder, classInfo, defaults, transientObj ).process(); } for ( JaxbVersion version : getVersion() ) { new VersionMocker( indexBuilder, classInfo, defaults, version ).process(); } - for ( JaxbBasic basic : getBasic() ) { + for ( JaxbBasic basic : getAttributesContainer().getBasic() ) { new BasicMocker( indexBuilder, classInfo, defaults, basic ).process(); } - for ( JaxbElementCollection elementCollection : getElementCollection() ) { + for ( JaxbElementCollection elementCollection : getAttributesContainer().getElementCollection() ) { new ElementCollectionMocker( indexBuilder, classInfo, defaults, elementCollection ).process(); } - for ( JaxbEmbedded embedded : getEmbedded() ) { + for ( JaxbEmbedded embedded : getAttributesContainer().getEmbedded() ) { new EmbeddedMocker( indexBuilder, classInfo, defaults, embedded ).process(); } - for ( JaxbManyToMany manyToMany : getManyToMany() ) { + for ( JaxbManyToMany manyToMany : getAttributesContainer().getManyToMany() ) { new ManyToManyMocker( indexBuilder, classInfo, defaults, manyToMany ).process(); } - for ( JaxbManyToOne manyToOne : getManyToOne() ) { + for ( JaxbManyToOne manyToOne : getAttributesContainer().getManyToOne() ) { new ManyToOneMocker( indexBuilder, classInfo, defaults, manyToOne ).process(); } - for ( JaxbOneToMany oneToMany : getOneToMany() ) { + for ( JaxbOneToMany oneToMany : getAttributesContainer().getOneToMany() ) { new OneToManyMocker( indexBuilder, classInfo, defaults, oneToMany ).process(); } - for ( JaxbOneToOne oneToOne : getOneToOne() ) { + for ( JaxbOneToOne oneToOne : getAttributesContainer().getOneToOne() ) { new OneToOneMocker( indexBuilder, classInfo, defaults, oneToOne ).process(); } if ( getEmbeddedId() != null ) { @@ -104,24 +104,7 @@ abstract class AbstractAttributesBuilder { } abstract List getId(); - - abstract List getTransient(); - abstract List getVersion(); - - abstract List getBasic(); - - abstract List getElementCollection(); - - abstract List getEmbedded(); - - abstract List getManyToMany(); - - abstract List getManyToOne(); - - abstract List getOneToMany(); - - abstract List getOneToOne(); - abstract JaxbEmbeddedId getEmbeddedId(); -} + abstract protected AttributesContainer getAttributesContainer(); +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractEntityObjectMocker.java similarity index 64% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractEntityObjectMocker.java index 8248e3e6a5..cb21b1e3be 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractEntityObjectMocker.java @@ -21,31 +21,31 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; +import org.hibernate.AssertionFailure; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEntityListeners; +import org.hibernate.jaxb.spi.orm.JaxbIdClass; +import org.hibernate.jaxb.spi.orm.JaxbPostLoad; +import org.hibernate.jaxb.spi.orm.JaxbPostPersist; +import org.hibernate.jaxb.spi.orm.JaxbPostRemove; +import org.hibernate.jaxb.spi.orm.JaxbPostUpdate; +import org.hibernate.jaxb.spi.orm.JaxbPrePersist; +import org.hibernate.jaxb.spi.orm.JaxbPreRemove; +import org.hibernate.jaxb.spi.orm.JaxbPreUpdate; + /** * @author Strong Liu */ abstract class AbstractEntityObjectMocker extends AnnotationMocker { - private ListenerMocker listenerParser; + private ListenerMocker listenerparse; protected AbstractAttributesBuilder attributesBuilder; protected ClassInfo classInfo; @@ -59,13 +59,13 @@ abstract class AbstractEntityObjectMocker extends AnnotationMocker { * Pre-process Entity Objects to find the default {@link javax.persistence.Access} for later attributes processing. */ final void preProcess() { - applyDefaults(); - classInfo = indexBuilder.createClassInfo( getClassName() ); + DefaultConfigurationHelper.INSTANCE.applyDefaults( getEntityElement(), getDefaults() ); + classInfo = indexBuilder.createClassInfo( getEntityElement().getClazz() ); DotName classDotName = classInfo.name(); - if ( isMetadataComplete() ) { + if ( getEntityElement().isMetadataComplete() != null && getEntityElement().isMetadataComplete() ) { indexBuilder.metadataComplete( classDotName ); } - parserAccessType( getAccessType(), getTarget() ); + parseAccessType( getEntityElement().getAccess(), getTarget() ); isPreProcessCalled = true; } @@ -73,12 +73,12 @@ abstract class AbstractEntityObjectMocker extends AnnotationMocker { if ( !isPreProcessCalled ) { throw new AssertionFailure( "preProcess should be called before process" ); } - if ( getAccessType() == null ) { + if ( getEntityElement().getAccess() == null ) { JaxbAccessType accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); if ( accessType == null ) { accessType = getDefaults().getAccess(); } - parserAccessType( accessType, getTarget() ); + parseAccessType( accessType, getTarget() ); } processExtra(); if ( isExcludeDefaultListeners() ) { @@ -87,36 +87,28 @@ abstract class AbstractEntityObjectMocker extends AnnotationMocker { if ( isExcludeSuperclassListeners() ) { create( EXCLUDE_SUPERCLASS_LISTENERS ); } - parserIdClass( getIdClass() ); + parseIdClass( getIdClass() ); if ( getAttributes() != null ) { - getAttributesBuilder().parser(); + getAttributesBuilder().parse(); } if ( getEntityListeners() != null ) { - getListenerParser().parser( getEntityListeners() ); + getListenerparse().parse( getEntityListeners() ); } - getListenerParser().parser( getPrePersist() ); - getListenerParser().parser( getPreRemove() ); - getListenerParser().parser( getPreUpdate() ); - getListenerParser().parser( getPostPersist() ); - getListenerParser().parser( getPostUpdate() ); - getListenerParser().parser( getPostRemove() ); - getListenerParser().parser( getPostLoad() ); + getListenerparse().parse( getPrePersist(), PRE_PERSIST ); + getListenerparse().parse( getPreRemove(), PRE_REMOVE ); + getListenerparse().parse( getPreUpdate(), PRE_UPDATE ); + getListenerparse().parse( getPostPersist(), POST_PERSIST ); + getListenerparse().parse( getPostUpdate(), POST_UPDATE ); + getListenerparse().parse( getPostRemove(), POST_REMOVE ); + getListenerparse().parse( getPostLoad(), POST_LOAD ); indexBuilder.finishEntityObject( getTargetName(), getDefaults() ); } - + abstract protected EntityElement getEntityElement(); abstract protected void processExtra(); - - /** - * give a chance to the sub-classes to override defaults configuration - */ - abstract protected void applyDefaults(); - - abstract protected boolean isMetadataComplete(); - abstract protected boolean isExcludeDefaultListeners(); abstract protected boolean isExcludeSuperclassListeners(); @@ -124,11 +116,6 @@ abstract class AbstractEntityObjectMocker extends AnnotationMocker { abstract protected JaxbIdClass getIdClass(); abstract protected JaxbEntityListeners getEntityListeners(); - - abstract protected JaxbAccessType getAccessType(); - - abstract protected String getClassName(); - abstract protected JaxbPrePersist getPrePersist(); abstract protected JaxbPreRemove getPreRemove(); @@ -145,23 +132,23 @@ abstract class AbstractEntityObjectMocker extends AnnotationMocker { abstract protected JaxbAttributes getAttributes(); - protected ListenerMocker getListenerParser() { - if ( listenerParser == null ) { - listenerParser = new ListenerMocker( indexBuilder, classInfo ); + protected ListenerMocker getListenerparse() { + if ( listenerparse == null ) { + listenerparse = new ListenerMocker( indexBuilder, classInfo ); } - return listenerParser; + return listenerparse; } protected AbstractAttributesBuilder getAttributesBuilder() { if ( attributesBuilder == null ) { attributesBuilder = new AttributesBuilder( - indexBuilder, classInfo, getAccessType(), getDefaults(), getAttributes() + indexBuilder, classInfo, getEntityElement().getAccess(), getDefaults(), getAttributes() ); } return attributesBuilder; } - protected AnnotationInstance parserIdClass(JaxbIdClass idClass) { + protected AnnotationInstance parseIdClass(JaxbIdClass idClass) { if ( idClass == null ) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMocker.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMocker.java index d5cfb09c4f..7c91c44df0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMocker.java @@ -21,15 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbUniqueConstraint; -import org.hibernate.metamodel.source.annotations.JPADotNames; - +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbIndex; +import org.hibernate.jaxb.spi.orm.JaxbUniqueConstraint; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; @@ -68,7 +69,7 @@ abstract class AbstractMocker implements JPADotNames { } - protected AnnotationInstance parserAccessType(JaxbAccessType accessType, AnnotationTarget target) { + protected AnnotationInstance parseAccessType(JaxbAccessType accessType, AnnotationTarget target) { if ( accessType == null ) { return null; } @@ -76,32 +77,50 @@ abstract class AbstractMocker implements JPADotNames { } protected void nestedUniqueConstraintList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { AnnotationValue[] values = new AnnotationValue[constraints.size()]; for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserUniqueConstraint( constraints.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); + AnnotationInstance annotationInstance = parseUniqueConstraint( constraints.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); + MockHelper.addToCollectionIfNotNull( annotationValueList, AnnotationValue.createArrayValue( name, values ) ); } } - //@UniqueConstraint - protected AnnotationInstance parserUniqueConstraint(JaxbUniqueConstraint uniqueConstraint, AnnotationTarget target) { + // @UniqueConstraint + protected AnnotationInstance parseUniqueConstraint(JaxbUniqueConstraint uniqueConstraint, AnnotationTarget target) { if ( uniqueConstraint == null ) { return null; } List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", uniqueConstraint.getName(), annotationValueList ); MockHelper.stringArrayValue( "columnNames", uniqueConstraint.getColumnName(), annotationValueList ); - return - create( UNIQUE_CONSTRAINT, target, - annotationValueList ); + return create( UNIQUE_CONSTRAINT, target, annotationValueList ); + } + + protected void nestedIndexConstraintList(String name, List constraints, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { + AnnotationValue[] values = new AnnotationValue[constraints.size()]; + for ( int i = 0; i < constraints.size(); i++ ) { + AnnotationInstance annotationInstance = parseIndexConstraint( constraints.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); + } + MockHelper.addToCollectionIfNotNull( annotationValueList, AnnotationValue.createArrayValue( name, values ) ); + } + + } + + // @Index + protected AnnotationInstance parseIndexConstraint(JaxbIndex index, AnnotationTarget target) { + if ( index == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", index.getName(), annotationValueList ); + MockHelper.stringValue( "columnList", index.getColumnList(), annotationValueList ); + MockHelper.booleanValue( "unique", index.isUnique(), annotationValueList ); + return create( INDEX, target, annotationValueList ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AccessHelper.java similarity index 85% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AccessHelper.java index 1ba239c296..5ed99c12bc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AccessHelper.java @@ -21,19 +21,20 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.List; import java.util.Map; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; - +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.ClassInfo; @@ -59,7 +60,8 @@ class AccessHelper implements JPADotNames { return null; } else { - return JandexHelper.getEnumValue( annotationInstance, "value", JaxbAccessType.class ); + return JandexHelper.getEnumValue( annotationInstance, "value", JaxbAccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) ); } } @@ -91,7 +93,7 @@ class AccessHelper implements JPADotNames { return null; } List idAnnotationInstances = annotations.get( ID ); - if ( MockHelper.isNotEmpty( idAnnotationInstances ) ) { + if ( CollectionHelper.isNotEmpty( idAnnotationInstances ) ) { return processIdAnnotations( idAnnotationInstances ); } return null; @@ -123,9 +125,9 @@ class AccessHelper implements JPADotNames { static JaxbAccessType getEntityAccess(DotName className, IndexBuilder indexBuilder) { Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); Map> ormAnnotations = indexBuilder.getClassInfoAnnotationsMap( className ); - JaxbAccessType accessType = getAccess( ormAnnotations ); + JaxbAccessType accessType = getAccess( ormAnnotations, indexBuilder ); if ( accessType == null ) { - accessType = getAccess( indexedAnnotations ); + accessType = getAccess( indexedAnnotations, indexBuilder ); } if ( accessType == null ) { ClassInfo parent = indexBuilder.getClassInfo( className ); @@ -141,18 +143,19 @@ class AccessHelper implements JPADotNames { } - private static JaxbAccessType getAccess(Map> annotations) { + private static JaxbAccessType getAccess(Map> annotations, IndexBuilder indexBuilder) { if ( annotations == null || annotations.isEmpty() || !isEntityObject( annotations ) ) { return null; } List accessAnnotationInstances = annotations.get( JPADotNames.ACCESS ); - if ( MockHelper.isNotEmpty( accessAnnotationInstances ) ) { + if ( CollectionHelper.isNotEmpty( accessAnnotationInstances ) ) { for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { return JandexHelper.getEnumValue( annotationInstance, "value", - JaxbAccessType.class + JaxbAccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) ); } } @@ -172,7 +175,7 @@ class AccessHelper implements JPADotNames { Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); if ( indexedAnnotations != null && indexedAnnotations.containsKey( ACCESS ) ) { List annotationInstances = indexedAnnotations.get( ACCESS ); - if ( MockHelper.isNotEmpty( annotationInstances ) ) { + if ( CollectionHelper.isNotEmpty( annotationInstances ) ) { for ( AnnotationInstance annotationInstance : annotationInstances ) { AnnotationTarget indexedPropertyTarget = annotationInstance.target(); if ( indexedPropertyTarget == null ) { @@ -182,7 +185,8 @@ class AccessHelper implements JPADotNames { JaxbAccessType accessType = JandexHelper.getEnumValue( annotationInstance, "value", - JaxbAccessType.class + JaxbAccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) ); /** * here we ignore @Access(FIELD) on property (getter) and @Access(PROPERTY) on field diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AnnotationMocker.java similarity index 80% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AnnotationMocker.java index 08f9ba63ea..410c7e486d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AnnotationMocker.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.HashSet; @@ -29,24 +29,25 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.AssertionFailure; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAssociationOverride; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributeOverride; -import org.hibernate.internal.jaxb.mapping.orm.JaxbCollectionTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEnumType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbLob; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOrderColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrimaryKeyJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTemporalType; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; +import org.hibernate.AssertionFailure; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAssociationOverride; +import org.hibernate.jaxb.spi.orm.JaxbAttributeOverride; +import org.hibernate.jaxb.spi.orm.JaxbCollectionTable; +import org.hibernate.jaxb.spi.orm.JaxbColumn; +import org.hibernate.jaxb.spi.orm.JaxbEnumType; +import org.hibernate.jaxb.spi.orm.JaxbJoinColumn; +import org.hibernate.jaxb.spi.orm.JaxbJoinTable; +import org.hibernate.jaxb.spi.orm.JaxbLob; +import org.hibernate.jaxb.spi.orm.JaxbOrderColumn; +import org.hibernate.jaxb.spi.orm.JaxbPrimaryKeyJoinColumn; +import org.hibernate.jaxb.spi.orm.JaxbTemporalType; + /** * @author Strong Liu */ @@ -69,30 +70,24 @@ abstract class AnnotationMocker extends AbstractMocker { } //@JoinTable - protected AnnotationInstance parserJoinTable(JaxbJoinTable joinTable, AnnotationTarget target) { + protected AnnotationInstance parseJoinTable(JaxbJoinTable joinTable, AnnotationTarget target) { if ( joinTable == null ) { return null; } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.JoinTableSchemaAware( joinTable ), - getDefaults() - ); + DefaultConfigurationHelper.INSTANCE.applyDefaults(joinTable,getDefaults()); List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", joinTable.getName(), annotationValueList ); MockHelper.stringValue( "catalog", joinTable.getCatalog(), annotationValueList ); MockHelper.stringValue( "schema", joinTable.getSchema(), annotationValueList ); nestedJoinColumnList( "joinColumns", joinTable.getJoinColumn(), annotationValueList ); - nestedJoinColumnList( - "inverseJoinColumns", joinTable.getInverseJoinColumn(), annotationValueList - ); - nestedUniqueConstraintList( - "uniqueConstraints", joinTable.getUniqueConstraint(), annotationValueList - ); + nestedJoinColumnList( "inverseJoinColumns", joinTable.getInverseJoinColumn(), annotationValueList ); + nestedUniqueConstraintList( "uniqueConstraints", joinTable.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", joinTable.getIndex(), annotationValueList ); return create( JOIN_TABLE, target, annotationValueList ); } //@AssociationOverride - private AnnotationInstance parserAssociationOverride(JaxbAssociationOverride associationOverride, AnnotationTarget target) { + private AnnotationInstance parseAssociationOverride(JaxbAssociationOverride associationOverride, AnnotationTarget target) { if ( associationOverride == null ) { return null; } @@ -108,17 +103,17 @@ abstract class AnnotationMocker extends AbstractMocker { "joinColumns", associationOverride.getJoinColumn(), annotationValueList ); MockHelper.nestedAnnotationValue( - "joinTable", parserJoinTable( associationOverride.getJoinTable(), null ), annotationValueList + "joinTable", parseJoinTable( associationOverride.getJoinTable(), null ), annotationValueList ); } return create( ASSOCIATION_OVERRIDE, target, annotationValueList ); } private AnnotationValue[] nestedJoinColumnList(String name, List columns, List annotationValueList) { - if ( MockHelper.isNotEmpty( columns ) ) { + if ( CollectionHelper.isNotEmpty( columns ) ) { AnnotationValue[] values = new AnnotationValue[columns.size()]; for ( int i = 0; i < columns.size(); i++ ) { - AnnotationInstance annotationInstance = parserJoinColumn( columns.get( i ), null ); + AnnotationInstance annotationInstance = parseJoinColumn( columns.get( i ), null ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -133,7 +128,7 @@ abstract class AnnotationMocker extends AbstractMocker { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //@Column - protected AnnotationInstance parserColumn(JaxbColumn column, AnnotationTarget target) { + protected AnnotationInstance parseColumn(JaxbColumn column, AnnotationTarget target) { if ( column == null ) { return null; } @@ -152,7 +147,7 @@ abstract class AnnotationMocker extends AbstractMocker { } //@AttributeOverride - private AnnotationInstance parserAttributeOverride(JaxbAttributeOverride attributeOverride, AnnotationTarget target) { + private AnnotationInstance parseAttributeOverride(JaxbAttributeOverride attributeOverride, AnnotationTarget target) { if ( attributeOverride == null ) { return null; } @@ -164,7 +159,7 @@ abstract class AnnotationMocker extends AbstractMocker { } else { MockHelper.nestedAnnotationValue( - "column", parserColumn( attributeOverride.getColumn(), null ), annotationValueList + "column", parseColumn( attributeOverride.getColumn(), null ), annotationValueList ); } return @@ -175,7 +170,7 @@ abstract class AnnotationMocker extends AbstractMocker { } - protected AnnotationInstance parserOrderColumn(JaxbOrderColumn orderColumn, AnnotationTarget target) { + protected AnnotationInstance parseOrderColumn(JaxbOrderColumn orderColumn, AnnotationTarget target) { if ( orderColumn == null ) { return null; } @@ -189,7 +184,7 @@ abstract class AnnotationMocker extends AbstractMocker { } //@JoinColumn - protected AnnotationInstance parserJoinColumn(JaxbJoinColumn column, AnnotationTarget target) { + protected AnnotationInstance parseJoinColumn(JaxbJoinColumn column, AnnotationTarget target) { if ( column == null ) { return null; } @@ -207,21 +202,21 @@ abstract class AnnotationMocker extends AbstractMocker { return create( JOIN_COLUMN, target, annotationValueList ); } - protected AnnotationInstance parserLob(JaxbLob lob, AnnotationTarget target) { + protected AnnotationInstance parseLob(JaxbLob lob, AnnotationTarget target) { if ( lob == null ) { return null; } return create( LOB, target ); } - protected AnnotationInstance parserTemporalType(JaxbTemporalType temporalType, AnnotationTarget target) { + protected AnnotationInstance parseTemporalType(JaxbTemporalType temporalType, AnnotationTarget target) { if ( temporalType == null ) { return null; } return create( TEMPORAL, target, MockHelper.enumValueArray( "value", TEMPORAL_TYPE, temporalType ) ); } - protected AnnotationInstance parserEnumType(JaxbEnumType enumerated, AnnotationTarget target) { + protected AnnotationInstance parseEnumType(JaxbEnumType enumerated, AnnotationTarget target) { if ( enumerated == null ) { return null; } @@ -229,7 +224,7 @@ abstract class AnnotationMocker extends AbstractMocker { } - protected AnnotationInstance parserPrimaryKeyJoinColumn(JaxbPrimaryKeyJoinColumn primaryKeyJoinColumn, AnnotationTarget target) { + protected AnnotationInstance parsePrimaryKeyJoinColumn(JaxbPrimaryKeyJoinColumn primaryKeyJoinColumn, AnnotationTarget target) { if ( primaryKeyJoinColumn == null ) { return null; } @@ -248,10 +243,10 @@ abstract class AnnotationMocker extends AbstractMocker { ); } - protected AnnotationInstance parserPrimaryKeyJoinColumnList(List primaryKeyJoinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { + protected AnnotationInstance parsePrimaryKeyJoinColumnList(List primaryKeyJoinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { if ( primaryKeyJoinColumnList.size() == 1 ) { - return parserPrimaryKeyJoinColumn( primaryKeyJoinColumnList.get( 0 ), target ); + return parsePrimaryKeyJoinColumn( primaryKeyJoinColumnList.get( 0 ), target ); } else { return create( @@ -267,10 +262,10 @@ abstract class AnnotationMocker extends AbstractMocker { } protected AnnotationValue[] nestedPrimaryKeyJoinColumnList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { AnnotationValue[] values = new AnnotationValue[constraints.size()]; for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserPrimaryKeyJoinColumn( constraints.get( i ), null ); + AnnotationInstance annotationInstance = parsePrimaryKeyJoinColumn( constraints.get( i ), null ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -290,7 +285,7 @@ abstract class AnnotationMocker extends AbstractMocker { return; } List annotationInstanceList = annotatedMap.get( annName ); - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { + if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) { for ( AnnotationInstance annotationInstance : annotationInstanceList ) { AnnotationTarget annotationTarget = annotationInstance.target(); if ( MockHelper.targetEquals( target, annotationTarget ) ) { @@ -303,7 +298,7 @@ abstract class AnnotationMocker extends AbstractMocker { } - protected AnnotationInstance parserAttributeOverrides(List attributeOverrides, AnnotationTarget target) { + protected AnnotationInstance parseAttributeOverrides(List attributeOverrides, AnnotationTarget target) { if ( target == null ) { throw new AssertionFailure( "target can not be null" ); } @@ -322,13 +317,13 @@ abstract class AnnotationMocker extends AbstractMocker { ATTRIBUTE_OVERRIDE, target, operation ); if ( attributeOverrides.size() == 1 ) { - return parserAttributeOverride( attributeOverrides.get( 0 ), target ); + return parseAttributeOverride( attributeOverrides.get( 0 ), target ); } else { AnnotationValue[] values = new AnnotationValue[attributeOverrides.size()]; for ( int i = 0; i < values.length; i++ ) { values[i] = MockHelper.nestedAnnotationValue( - "", parserAttributeOverride( attributeOverrides.get( i ), null ) + "", parseAttributeOverride( attributeOverrides.get( i ), null ) ); } return create( @@ -339,7 +334,7 @@ abstract class AnnotationMocker extends AbstractMocker { } } - protected AnnotationInstance parserAssociationOverrides(List associationOverrides, AnnotationTarget target) { + protected AnnotationInstance parseAssociationOverrides(List associationOverrides, AnnotationTarget target) { if ( target == null ) { throw new AssertionFailure( "target can not be null" ); } @@ -361,13 +356,13 @@ abstract class AnnotationMocker extends AbstractMocker { if ( associationOverrides.size() == 1 ) { - return parserAssociationOverride( associationOverrides.get( 0 ), target ); + return parseAssociationOverride( associationOverrides.get( 0 ), target ); } else { AnnotationValue[] values = new AnnotationValue[associationOverrides.size()]; for ( int i = 0; i < values.length; i++ ) { values[i] = MockHelper.nestedAnnotationValue( - "", parserAssociationOverride( associationOverrides.get( i ), null ) + "", parseAssociationOverride( associationOverrides.get( i ), null ) ); } return create( @@ -379,28 +374,26 @@ abstract class AnnotationMocker extends AbstractMocker { } - protected AnnotationInstance parserCollectionTable(JaxbCollectionTable collectionTable, AnnotationTarget target) { + protected AnnotationInstance parseCollectionTable(JaxbCollectionTable collectionTable, AnnotationTarget target) { if ( collectionTable == null ) { return null; } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.CollectionTableSchemaAware( collectionTable ), - getDefaults() - ); + DefaultConfigurationHelper.INSTANCE.applyDefaults(collectionTable,getDefaults()); List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", collectionTable.getName(), annotationValueList ); MockHelper.stringValue( "catalog", collectionTable.getCatalog(), annotationValueList ); MockHelper.stringValue( "schema", collectionTable.getSchema(), annotationValueList ); nestedJoinColumnList( "joinColumns", collectionTable.getJoinColumn(), annotationValueList ); nestedUniqueConstraintList( "uniqueConstraints", collectionTable.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", collectionTable.getIndex(), annotationValueList ); return create( COLLECTION_TABLE, target, annotationValueList ); } - protected AnnotationInstance parserJoinColumnList(List joinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( joinColumnList ) ) { + protected AnnotationInstance parseJoinColumnList(List joinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( joinColumnList ) ) { if ( joinColumnList.size() == 1 ) { - return parserJoinColumn( joinColumnList.get( 0 ), target ); + return parseJoinColumn( joinColumnList.get( 0 ), target ); } else { AnnotationValue[] values = nestedJoinColumnList( "value", joinColumnList, null ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesBuilder.java new file mode 100644 index 0000000000..dd320c1365 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesBuilder.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import java.util.List; + +import org.jboss.jandex.ClassInfo; + +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddedId; +import org.hibernate.jaxb.spi.orm.JaxbId; +import org.hibernate.jaxb.spi.orm.JaxbVersion; + +/** + * @author Strong Liu + */ +class AttributesBuilder extends AbstractAttributesBuilder { + private final JaxbAttributes attributes; + + AttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbAttributes attributes) { + super( indexBuilder, classInfo, defaults ); + this.attributes = attributes; + } + + @Override + protected AttributesContainer getAttributesContainer() { + return attributes; + } + + @Override + List getId() { + return attributes.getId(); + } + + @Override + List getVersion() { + return attributes.getVersion(); + } + + @Override + JaxbEmbeddedId getEmbeddedId() { + return attributes.getEmbeddedId(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesContainer.java new file mode 100644 index 0000000000..d8626f0e06 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributesContainer.java @@ -0,0 +1,35 @@ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import java.util.List; + +import org.hibernate.jaxb.spi.orm.JaxbBasic; +import org.hibernate.jaxb.spi.orm.JaxbElementCollection; +import org.hibernate.jaxb.spi.orm.JaxbEmbedded; +import org.hibernate.jaxb.spi.orm.JaxbManyToMany; +import org.hibernate.jaxb.spi.orm.JaxbManyToOne; +import org.hibernate.jaxb.spi.orm.JaxbOneToMany; +import org.hibernate.jaxb.spi.orm.JaxbOneToOne; +import org.hibernate.jaxb.spi.orm.JaxbTransient; + +/** + * @author Strong Liu + */ +public interface AttributesContainer { + + List getTransient(); + + List getBasic(); + + List getElementCollection(); + + List getEmbedded(); + + List getManyToMany(); + + List getManyToOne(); + + List getOneToMany(); + + List getOneToOne(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMocker.java similarity index 72% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMocker.java index ff46073ede..daa283365b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMocker.java @@ -21,22 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbBasic; + /** * @author Strong Liu */ class BasicMocker extends PropertyMocker { - private JaxbBasic basic; + private final JaxbBasic basic; BasicMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbBasic basic) { super( indexBuilder, classInfo, defaults ); @@ -44,31 +43,19 @@ class BasicMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return basic.getName(); + protected PropertyElement getPropertyElement() { + return basic; } - @Override protected void processExtra() { List annotationValueList = new ArrayList(); MockHelper.booleanValue( "optional", basic.isOptional(), annotationValueList ); MockHelper.enumValue( "fetch", FETCH_TYPE, basic.getFetch(), annotationValueList ); create( BASIC, annotationValueList ); - parserColumn( basic.getColumn(), getTarget() ); - parserEnumType( basic.getEnumerated(), getTarget() ); - parserLob( basic.getLob(), getTarget() ); - parserTemporalType( basic.getTemporal(), getTarget() ); + parseColumn( basic.getColumn(), getTarget() ); + parseEnumType( basic.getEnumerated(), getTarget() ); + parseLob( basic.getLob(), getTarget() ); + parseTemporalType( basic.getTemporal(), getTarget() ); } - - - @Override - protected JaxbAccessType getAccessType() { - return basic.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - basic.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelper.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelper.java index 47eac0c95f..5f0ec033e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelper.java @@ -21,27 +21,25 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.xml.filter.IndexedAnnotationFilter; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; import org.jboss.logging.Logger; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.jaxb.spi.orm.JaxbTable; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.filter.IndexedAnnotationFilter; + /** * @author Strong Liu */ @@ -100,20 +98,23 @@ class DefaultConfigurationHelper { } } - void applyDefaults(JaxbMappedSuperclass mappedSuperclass, EntityMappingsMocker.Default defaults) { - applyDefaultsToEntityObject( new MappedSuperClassEntityObject( mappedSuperclass ), defaults ); + void applyDefaults(EntityElement entityElement, EntityMappingsMocker.Default defaults) { + if(JaxbEntity.class.isInstance( entityElement )) + mockTableIfNonExist( JaxbEntity.class.cast( entityElement ), defaults ); + applyDefaultsToEntityObject( entityElement , defaults ); } - void applyDefaults(JaxbEmbeddable embeddable, EntityMappingsMocker.Default defaults) { - applyDefaultsToEntityObject( new EmbeddableEntityObject( embeddable ), defaults ); + private void mockTableIfNonExist(JaxbEntity entity, EntityMappingsMocker.Default defaults) { + if ( hasSchemaOrCatalogDefined( defaults ) ) { + JaxbTable table = entity.getTable(); + if ( table == null ) { + table = new JaxbTable(); + entity.setTable( table ); + } + } } - void applyDefaults(JaxbEntity entity, EntityMappingsMocker.Default defaults) { - mockTableIfNonExist( entity, defaults ); - applyDefaultsToEntityObject( new EntityEntityObject( entity ), defaults ); - } - - private void applyDefaultsToEntityObject(EntityObject entityObject, EntityMappingsMocker.Default defaults) { + private void applyDefaultsToEntityObject(EntityElement entityObject, EntityMappingsMocker.Default defaults) { if ( defaults == null ) { return; } @@ -162,16 +163,6 @@ class DefaultConfigurationHelper { } } - private void mockTableIfNonExist(JaxbEntity entity, EntityMappingsMocker.Default defaults) { - if ( hasSchemaOrCatalogDefined( defaults ) ) { - JaxbTable table = entity.getTable(); - if ( table == null ) { - table = new JaxbTable(); - entity.setTable( table ); - } - } - } - private void addCascadePersistIfNotExist(DotName annName, Map> indexedAnnotationMap) { List annotationInstanceList = indexedAnnotationMap.get( annName ); if ( annotationInstanceList == null || annotationInstanceList.isEmpty() ) { @@ -292,98 +283,6 @@ class DefaultConfigurationHelper { ); } - private static interface EntityObject { - String getClazz(); - void setClazz(String className); - - Boolean isMetadataComplete(); - - void setMetadataComplete(Boolean isMetadataComplete); - } - - private static class EntityEntityObject implements EntityObject { - private JaxbEntity entity; - - private EntityEntityObject(JaxbEntity entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } - - private static class EmbeddableEntityObject implements EntityObject { - private JaxbEmbeddable entity; - - private EmbeddableEntityObject(JaxbEmbeddable entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } - - private static class MappedSuperClassEntityObject implements EntityObject { - private JaxbMappedSuperclass entity; - - private MappedSuperClassEntityObject(JaxbMappedSuperclass entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ElementCollectionMocker.java similarity index 56% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ElementCollectionMocker.java index e58cee635f..5bb203255d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ElementCollectionMocker.java @@ -21,28 +21,32 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbElementCollection; + /** * @author Strong Liu */ class ElementCollectionMocker extends PropertyMocker { - private JaxbElementCollection elementCollection; + private final JaxbElementCollection elementCollection; ElementCollectionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbElementCollection elementCollection) { super( indexBuilder, classInfo, defaults ); this.elementCollection = elementCollection; } + @Override + protected PropertyElement getPropertyElement() { + return elementCollection; + } + @Override protected void processExtra() { List annotationValueList = new ArrayList(); @@ -54,37 +58,22 @@ class ElementCollectionMocker extends PropertyMocker { ); MockHelper.enumValue( "fetch", FETCH_TYPE, elementCollection.getFetch(), annotationValueList ); create( ELEMENT_COLLECTION, annotationValueList ); - parserLob( elementCollection.getLob(), getTarget() ); - parserEnumType( elementCollection.getEnumerated(), getTarget() ); - parserColumn( elementCollection.getColumn(), getTarget() ); - parserTemporalType( elementCollection.getTemporal(), getTarget() ); - parserCollectionTable( elementCollection.getCollectionTable(), getTarget() ); - parserAssociationOverrides( elementCollection.getAssociationOverride(), getTarget() ); - parserAttributeOverrides( elementCollection.getAttributeOverride(), getTarget() ); + parseLob( elementCollection.getLob(), getTarget() ); + parseEnumType( elementCollection.getEnumerated(), getTarget() ); + parseColumn( elementCollection.getColumn(), getTarget() ); + parseTemporalType( elementCollection.getTemporal(), getTarget() ); + parseCollectionTable( elementCollection.getCollectionTable(), getTarget() ); + parseAssociationOverrides( elementCollection.getAssociationOverride(), getTarget() ); + parseAttributeOverrides( elementCollection.getAttributeOverride(), getTarget() ); if ( elementCollection.getOrderBy() != null ) { create( ORDER_BY, MockHelper.stringValueArray( "value", elementCollection.getOrderBy() ) ); } - parserAttributeOverrides( elementCollection.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( elementCollection.getMapKeyJoinColumn(), getTarget() ); - parserMapKey( elementCollection.getMapKey(), getTarget() ); - parserMapKeyColumn( elementCollection.getMapKeyColumn(), getTarget() ); - parserMapKeyClass( elementCollection.getMapKeyClass(), getTarget() ); - parserMapKeyEnumerated( elementCollection.getMapKeyEnumerated(), getTarget() ); - parserMapKeyTemporal( elementCollection.getMapKeyTemporal(), getTarget() ); - } - - @Override - protected String getFieldName() { - return elementCollection.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return elementCollection.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - elementCollection.setAccess( accessType ); + parseAttributeOverrides( elementCollection.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( elementCollection.getMapKeyJoinColumn(), getTarget() ); + parseMapKey( elementCollection.getMapKey(), getTarget() ); + parseMapKeyColumn( elementCollection.getMapKeyColumn(), getTarget() ); + parseMapKeyClass( elementCollection.getMapKeyClass(), getTarget() ); + parseMapKeyEnumerated( elementCollection.getMapKeyEnumerated(), getTarget() ); + parseMapKeyTemporal( elementCollection.getMapKeyTemporal(), getTarget() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java new file mode 100644 index 0000000000..772967e406 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import java.util.Collections; +import java.util.List; + +import org.jboss.jandex.ClassInfo; + +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddableAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddedId; +import org.hibernate.jaxb.spi.orm.JaxbId; +import org.hibernate.jaxb.spi.orm.JaxbVersion; + +/** + * @author Strong Liu + */ +class EmbeddableAttributesBuilder extends AbstractAttributesBuilder { + private final JaxbEmbeddableAttributes attributes; + + EmbeddableAttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbEmbeddableAttributes embeddableAttributes) { + super( indexBuilder, classInfo, defaults ); + this.attributes = embeddableAttributes; + } + + @Override + protected AttributesContainer getAttributesContainer() { + return attributes; + } + @Override + List getId() { + return Collections.emptyList(); + } + + @Override + List getVersion() { + return Collections.emptyList(); + } + @Override + JaxbEmbeddedId getEmbeddedId() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableMocker.java similarity index 61% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableMocker.java index cda89b1c59..5e68f0cbc7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddableMocker.java @@ -21,23 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - -import org.jboss.logging.Logger; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddable; +import org.hibernate.jaxb.spi.orm.JaxbEntityListeners; +import org.hibernate.jaxb.spi.orm.JaxbIdClass; +import org.hibernate.jaxb.spi.orm.JaxbPostLoad; +import org.hibernate.jaxb.spi.orm.JaxbPostPersist; +import org.hibernate.jaxb.spi.orm.JaxbPostRemove; +import org.hibernate.jaxb.spi.orm.JaxbPostUpdate; +import org.hibernate.jaxb.spi.orm.JaxbPrePersist; +import org.hibernate.jaxb.spi.orm.JaxbPreRemove; +import org.hibernate.jaxb.spi.orm.JaxbPreUpdate; /** * Mock to {@link javax.persistence.Embeddable @Embeddable} @@ -45,11 +41,7 @@ import org.jboss.logging.Logger; * @author Strong Liu */ class EmbeddableMocker extends AbstractEntityObjectMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - EmbeddableMocker.class.getName() - ); - private JaxbEmbeddable embeddable; + private final JaxbEmbeddable embeddable; EmbeddableMocker(IndexBuilder indexBuilder, JaxbEmbeddable embeddable, EntityMappingsMocker.Default defaults) { super( indexBuilder, defaults ); @@ -60,27 +52,22 @@ class EmbeddableMocker extends AbstractEntityObjectMocker { protected AbstractAttributesBuilder getAttributesBuilder() { if ( attributesBuilder == null ) { attributesBuilder = new EmbeddableAttributesBuilder( - indexBuilder, classInfo, getAccessType(), getDefaults(), embeddable.getAttributes() + indexBuilder, classInfo, embeddable.getAccess(), getDefaults(), embeddable.getAttributes() ); } return attributesBuilder; } + @Override + protected EntityElement getEntityElement() { + return embeddable; + } + @Override protected void processExtra() { create( EMBEDDABLE ); } - @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( embeddable, getDefaults() ); - } - - @Override - protected boolean isMetadataComplete() { - return embeddable.isMetadataComplete() != null && embeddable.isMetadataComplete(); - } - @Override protected boolean isExcludeDefaultListeners() { return false; @@ -101,16 +88,6 @@ class EmbeddableMocker extends AbstractEntityObjectMocker { return null; } - @Override - protected JaxbAccessType getAccessType() { - return embeddable.getAccess(); - } - - @Override - protected String getClassName() { - return embeddable.getClazz(); - } - @Override protected JaxbPrePersist getPrePersist() { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedIdMocker.java similarity index 74% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedIdMocker.java index 44f585005b..f333b8c0be 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedIdMocker.java @@ -21,18 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddedId; + /** * @author Strong Liu */ class EmbeddedIdMocker extends PropertyMocker { - private JaxbEmbeddedId embeddedId; + private final JaxbEmbeddedId embeddedId; EmbeddedIdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbeddedId embeddedId) { super( indexBuilder, classInfo, defaults ); @@ -40,22 +39,12 @@ class EmbeddedIdMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return embeddedId.getName(); + protected PropertyElement getPropertyElement() { + return embeddedId; } @Override protected void processExtra() { create( EMBEDDED_ID ); } - - @Override - protected JaxbAccessType getAccessType() { - return embeddedId.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - embeddedId.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedMocker.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedMocker.java index f75a268c41..80312e3003 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EmbeddedMocker.java @@ -21,18 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbEmbedded; + /** * @author Strong Liu */ class EmbeddedMocker extends PropertyMocker { - private JaxbEmbedded embedded; + private final JaxbEmbedded embedded; EmbeddedMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbedded embedded) { super( indexBuilder, classInfo, defaults ); @@ -42,23 +41,13 @@ class EmbeddedMocker extends PropertyMocker { @Override protected void processExtra() { create( EMBEDDED ); - parserAttributeOverrides( embedded.getAttributeOverride(), getTarget() ); - parserAssociationOverrides( embedded.getAssociationOverride(), getTarget() ); + parseAttributeOverrides( embedded.getAttributeOverride(), getTarget() ); + parseAssociationOverrides( embedded.getAssociationOverride(), getTarget() ); } @Override - protected String getFieldName() { - return embedded.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return embedded.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - embedded.setAccess( accessType ); + protected PropertyElement getPropertyElement() { + return embedded; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityElement.java new file mode 100644 index 0000000000..7501d3b0e5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityElement.java @@ -0,0 +1,17 @@ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import org.hibernate.jaxb.spi.orm.JaxbAccessType; + +/** + * @author Strong Liu + */ +public interface EntityElement { + String getClazz(); + + void setClazz(String className); + + Boolean isMetadataComplete(); + + void setMetadataComplete(Boolean isMetadataComplete); + public JaxbAccessType getAccess(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMappingsMocker.java similarity index 90% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMappingsMocker.java index 0f518669cc..d312410f79 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMappingsMocker.java @@ -21,27 +21,28 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitDefaults; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitMetadata; -import org.hibernate.service.ServiceRegistry; - import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.jboss.logging.Logger; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbEmbeddable; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.jaxb.spi.orm.JaxbEntityMappings; +import org.hibernate.jaxb.spi.orm.JaxbMappedSuperclass; +import org.hibernate.jaxb.spi.orm.JaxbPersistenceUnitDefaults; +import org.hibernate.jaxb.spi.orm.JaxbPersistenceUnitMetadata; +import org.hibernate.service.ServiceRegistry; + /** - * Parse all {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings} generated from orm.xml. + * Parse all {@link org.hibernate.jaxb.spi.orm.JaxbEntityMappings} generated from orm.xml. * * @author Strong Liu */ @@ -58,14 +59,15 @@ public class EntityMappingsMocker { private final IndexBuilder indexBuilder; private final GlobalAnnotations globalAnnotations; - public EntityMappingsMocker(List entityMappingsList, Index index, ServiceRegistry serviceRegistry) { + public EntityMappingsMocker(List entityMappingsList, IndexView index, ServiceRegistry serviceRegistry) { this.entityMappingsList = entityMappingsList; this.indexBuilder = new IndexBuilder( index, serviceRegistry ); this.globalAnnotations = new GlobalAnnotations(); } /** - * Create new {@link Index} with mocking JPA annotations from {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings} and merge them with existing {@link Index} + * Create new {@link Index} with mocking JPA annotations from {@link org.hibernate.jaxb.spi.orm.JaxbEntityMappings} + * and merge them with existing {@link Index} * * @return new {@link Index} */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMocker.java similarity index 65% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMocker.java index 8ee892122e..c1346c35c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityMocker.java @@ -21,38 +21,36 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.persistence.AccessType; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbDiscriminatorColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbInheritance; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSecondaryTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; -import org.hibernate.internal.util.StringHelper; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; -import org.jboss.logging.Logger; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbDiscriminatorColumn; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.jaxb.spi.orm.JaxbEntityListeners; +import org.hibernate.jaxb.spi.orm.JaxbIdClass; +import org.hibernate.jaxb.spi.orm.JaxbInheritance; +import org.hibernate.jaxb.spi.orm.JaxbPostLoad; +import org.hibernate.jaxb.spi.orm.JaxbPostPersist; +import org.hibernate.jaxb.spi.orm.JaxbPostRemove; +import org.hibernate.jaxb.spi.orm.JaxbPostUpdate; +import org.hibernate.jaxb.spi.orm.JaxbPrePersist; +import org.hibernate.jaxb.spi.orm.JaxbPreRemove; +import org.hibernate.jaxb.spi.orm.JaxbPreUpdate; +import org.hibernate.jaxb.spi.orm.JaxbSecondaryTable; +import org.hibernate.jaxb.spi.orm.JaxbTable; /** * Mock to {@link javax.persistence.Entity @Entity} @@ -60,22 +58,13 @@ import org.jboss.logging.Logger; * @author Strong Liu */ class EntityMocker extends AbstractEntityObjectMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - EntityMocker.class.getName() - ); - private JaxbEntity entity; + private final JaxbEntity entity; EntityMocker(IndexBuilder indexBuilder, JaxbEntity entity, EntityMappingsMocker.Default defaults) { super( indexBuilder, defaults ); this.entity = entity; } - @Override - protected String getClassName() { - return entity.getClazz(); - } - @Override protected void processExtra() { //@Entity @@ -99,30 +88,28 @@ class EntityMocker extends AbstractEntityObjectMocker { ); } //@Table - parserTable( entity.getTable() ); - parserInheritance( entity.getInheritance() ); - parserDiscriminatorColumn( entity.getDiscriminatorColumn() ); - parserAttributeOverrides( entity.getAttributeOverride(), getTarget() ); - parserAssociationOverrides( entity.getAssociationOverride(), getTarget() ); - parserPrimaryKeyJoinColumnList( entity.getPrimaryKeyJoinColumn(), getTarget() ); - parserSecondaryTableList( entity.getSecondaryTable(), getTarget() ); + parseTable( entity.getTable() ); + parseInheritance( entity.getInheritance() ); + parseDiscriminatorColumn( entity.getDiscriminatorColumn() ); + parseAttributeOverrides( entity.getAttributeOverride(), getTarget() ); + parseAssociationOverrides( entity.getAssociationOverride(), getTarget() ); + parsePrimaryKeyJoinColumnList( entity.getPrimaryKeyJoinColumn(), getTarget() ); + parseSecondaryTableList( entity.getSecondaryTable(), getTarget() ); } //@Table (entity only) - private AnnotationInstance parserTable(JaxbTable table) { + private AnnotationInstance parseTable(JaxbTable table) { if ( table == null ) { return null; } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.TableSchemaAware( table ), - getDefaults() - ); + DefaultConfigurationHelper.INSTANCE.applyDefaults(table,getDefaults()); List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", table.getName(), annotationValueList ); MockHelper.stringValue( "catalog", table.getCatalog(), annotationValueList ); MockHelper.stringValue( "schema", table.getSchema(), annotationValueList ); nestedUniqueConstraintList( "uniqueConstraints", table.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", table.getIndex(), annotationValueList ); return create( TABLE, annotationValueList ); } @@ -137,7 +124,7 @@ class EntityMocker extends AbstractEntityObjectMocker { protected AccessType getAccessFromIndex(DotName className) { Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); List accessAnnotationInstances = indexedAnnotations.get( ACCESS ); - if ( MockHelper.isNotEmpty( accessAnnotationInstances ) ) { + if ( CollectionHelper.isNotEmpty( accessAnnotationInstances ) ) { for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { ClassInfo ci = (ClassInfo) ( annotationInstance.target() ); @@ -152,8 +139,8 @@ class EntityMocker extends AbstractEntityObjectMocker { } @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( entity, getDefaults() ); + protected EntityElement getEntityElement() { + return entity; } @Override @@ -196,10 +183,6 @@ class EntityMocker extends AbstractEntityObjectMocker { return entity.getAttributes(); } - @Override - protected boolean isMetadataComplete() { - return entity.isMetadataComplete() != null && entity.isMetadataComplete(); - } @Override protected boolean isExcludeDefaultListeners() { @@ -221,13 +204,8 @@ class EntityMocker extends AbstractEntityObjectMocker { return entity.getEntityListeners(); } - @Override - protected JaxbAccessType getAccessType() { - return entity.getAccess(); - } - //@Inheritance - protected AnnotationInstance parserInheritance(JaxbInheritance inheritance) { + protected AnnotationInstance parseInheritance(JaxbInheritance inheritance) { if ( inheritance == null ) { return null; } @@ -240,7 +218,7 @@ class EntityMocker extends AbstractEntityObjectMocker { } //@DiscriminatorColumn - protected AnnotationInstance parserDiscriminatorColumn(JaxbDiscriminatorColumn discriminatorColumn) { + protected AnnotationInstance parseDiscriminatorColumn(JaxbDiscriminatorColumn discriminatorColumn) { if ( discriminatorColumn == null ) { return null; } @@ -253,44 +231,31 @@ class EntityMocker extends AbstractEntityObjectMocker { MockHelper.enumValue( "discriminatorType", DISCRIMINATOR_TYPE, discriminatorColumn.getDiscriminatorType(), annotationValueList ); - return - create( - DISCRIMINATOR_COLUMN, annotationValueList - - ); + return create(DISCRIMINATOR_COLUMN, annotationValueList); } //@SecondaryTable - protected AnnotationInstance parserSecondaryTable(JaxbSecondaryTable secondaryTable, AnnotationTarget target) { + protected AnnotationInstance parseSecondaryTable(JaxbSecondaryTable secondaryTable, AnnotationTarget target) { if ( secondaryTable == null ) { return null; } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.SecondaryTableSchemaAware( secondaryTable ), - getDefaults() - ); + DefaultConfigurationHelper.INSTANCE.applyDefaults(secondaryTable,getDefaults()); List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", secondaryTable.getName(), annotationValueList ); MockHelper.stringValue( "catalog", secondaryTable.getCatalog(), annotationValueList ); MockHelper.stringValue( "schema", secondaryTable.getSchema(), annotationValueList ); - nestedPrimaryKeyJoinColumnList( - "pkJoinColumns", secondaryTable.getPrimaryKeyJoinColumn(), annotationValueList - ); - nestedUniqueConstraintList( - "uniqueConstraints", secondaryTable.getUniqueConstraint(), annotationValueList - ); - return - create( - SECONDARY_TABLE, target, annotationValueList - ); + nestedPrimaryKeyJoinColumnList("pkJoinColumns", secondaryTable.getPrimaryKeyJoinColumn(), annotationValueList); + nestedUniqueConstraintList("uniqueConstraints", secondaryTable.getUniqueConstraint(), annotationValueList); + nestedIndexConstraintList( "indexes", secondaryTable.getIndex(), annotationValueList ); + return create( SECONDARY_TABLE, target, annotationValueList ); } - protected AnnotationInstance parserSecondaryTableList(List primaryKeyJoinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { + protected AnnotationInstance parseSecondaryTableList(List primaryKeyJoinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { if ( primaryKeyJoinColumnList.size() == 1 ) { - return parserSecondaryTable( primaryKeyJoinColumnList.get( 0 ), target ); + return parseSecondaryTable( primaryKeyJoinColumnList.get( 0 ), target ); } else { return create( @@ -305,10 +270,10 @@ class EntityMocker extends AbstractEntityObjectMocker { } protected AnnotationValue[] nestedSecondaryTableList(String name, List secondaryTableList, List annotationValueList) { - if ( MockHelper.isNotEmpty( secondaryTableList ) ) { + if ( CollectionHelper.isNotEmpty( secondaryTableList ) ) { AnnotationValue[] values = new AnnotationValue[secondaryTableList.size()]; for ( int i = 0; i < secondaryTableList.size(); i++ ) { - AnnotationInstance annotationInstance = parserSecondaryTable( secondaryTableList.get( i ), null ); + AnnotationInstance annotationInstance = parseSecondaryTable( secondaryTableList.get( i ), null ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotationMocker.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotationMocker.java index b7ed83fa68..9d7ece7bb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotationMocker.java @@ -21,26 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbColumnResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbFieldResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedNativeQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbQueryHint; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSequenceGenerator; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSqlResultSetMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTableGenerator; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbColumnResult; +import org.hibernate.jaxb.spi.orm.JaxbEntityResult; +import org.hibernate.jaxb.spi.orm.JaxbFieldResult; +import org.hibernate.jaxb.spi.orm.JaxbNamedNativeQuery; +import org.hibernate.jaxb.spi.orm.JaxbNamedQuery; +import org.hibernate.jaxb.spi.orm.JaxbQueryHint; +import org.hibernate.jaxb.spi.orm.JaxbSequenceGenerator; +import org.hibernate.jaxb.spi.orm.JaxbSqlResultSetMapping; +import org.hibernate.jaxb.spi.orm.JaxbTableGenerator; + /** * @author Strong Liu */ @@ -56,57 +57,57 @@ class GlobalAnnotationMocker extends AbstractMocker { void process() { if ( !globalAnnotations.getTableGeneratorMap().isEmpty() ) { for ( JaxbTableGenerator generator : globalAnnotations.getTableGeneratorMap().values() ) { - parserTableGenerator( generator ); + parseTableGenerator( generator ); } } if ( !globalAnnotations.getSequenceGeneratorMap().isEmpty() ) { for ( JaxbSequenceGenerator generator : globalAnnotations.getSequenceGeneratorMap().values() ) { - parserSequenceGenerator( generator ); + parseSequenceGenerator( generator ); } } if ( !globalAnnotations.getNamedQueryMap().isEmpty() ) { Collection namedQueries = globalAnnotations.getNamedQueryMap().values(); if ( namedQueries.size() > 1 ) { - parserNamedQueries( namedQueries ); + parseNamedQueries( namedQueries ); } else { - parserNamedQuery( namedQueries.iterator().next() ); + parseNamedQuery( namedQueries.iterator().next() ); } } if ( !globalAnnotations.getNamedNativeQueryMap().isEmpty() ) { Collection namedQueries = globalAnnotations.getNamedNativeQueryMap().values(); if ( namedQueries.size() > 1 ) { - parserNamedNativeQueries( namedQueries ); + parseNamedNativeQueries( namedQueries ); } else { - parserNamedNativeQuery( namedQueries.iterator().next() ); + parseNamedNativeQuery( namedQueries.iterator().next() ); } } if ( !globalAnnotations.getSqlResultSetMappingMap().isEmpty() ) { - parserSqlResultSetMappings( globalAnnotations.getSqlResultSetMappingMap().values() ); + parseSqlResultSetMappings( globalAnnotations.getSqlResultSetMappingMap().values() ); } indexBuilder.finishGlobalConfigurationMocking( globalAnnotations ); } - private AnnotationInstance parserSqlResultSetMappings(Collection namedQueries) { + private AnnotationInstance parseSqlResultSetMappings(Collection namedQueries) { AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; int i = 0; for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserSqlResultSetMapping( iterator.next() ); + AnnotationInstance annotationInstance = parseSqlResultSetMapping( iterator.next() ); values[i++] = MockHelper.nestedAnnotationValue( "", annotationInstance ); } return create( SQL_RESULT_SET_MAPPINGS, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } ); } //@SqlResultSetMapping - private AnnotationInstance parserSqlResultSetMapping(JaxbSqlResultSetMapping mapping) { + private AnnotationInstance parseSqlResultSetMapping(JaxbSqlResultSetMapping mapping) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", mapping.getName(), annotationValueList ); @@ -121,7 +122,7 @@ class GlobalAnnotationMocker extends AbstractMocker { //@EntityResult - private AnnotationInstance parserEntityResult(JaxbEntityResult result) { + private AnnotationInstance parseEntityResult(JaxbEntityResult result) { List annotationValueList = new ArrayList(); MockHelper.stringValue( @@ -139,10 +140,10 @@ class GlobalAnnotationMocker extends AbstractMocker { } private void nestedEntityResultList(String name, List entityResults, List annotationValueList) { - if ( MockHelper.isNotEmpty( entityResults ) ) { + if ( CollectionHelper.isNotEmpty( entityResults ) ) { AnnotationValue[] values = new AnnotationValue[entityResults.size()]; for ( int i = 0; i < entityResults.size(); i++ ) { - AnnotationInstance annotationInstance = parserEntityResult( entityResults.get( i ) ); + AnnotationInstance annotationInstance = parseEntityResult( entityResults.get( i ) ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -154,15 +155,15 @@ class GlobalAnnotationMocker extends AbstractMocker { } //@ColumnResult - private AnnotationInstance parserColumnResult(JaxbColumnResult result) { + private AnnotationInstance parseColumnResult(JaxbColumnResult result) { return create( COLUMN_RESULT, null, MockHelper.stringValueArray( "name", result.getName() ) ); } private void nestedColumnResultList(String name, List columnResults, List annotationValueList) { - if ( MockHelper.isNotEmpty( columnResults ) ) { + if ( CollectionHelper.isNotEmpty( columnResults ) ) { AnnotationValue[] values = new AnnotationValue[columnResults.size()]; for ( int i = 0; i < columnResults.size(); i++ ) { - AnnotationInstance annotationInstance = parserColumnResult( columnResults.get( i ) ); + AnnotationInstance annotationInstance = parseColumnResult( columnResults.get( i ) ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -174,7 +175,7 @@ class GlobalAnnotationMocker extends AbstractMocker { } //@FieldResult - private AnnotationInstance parserFieldResult(JaxbFieldResult result) { + private AnnotationInstance parseFieldResult(JaxbFieldResult result) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", result.getName(), annotationValueList ); MockHelper.stringValue( "column", result.getColumn(), annotationValueList ); @@ -183,10 +184,10 @@ class GlobalAnnotationMocker extends AbstractMocker { private void nestedFieldResultList(String name, List fieldResultList, List annotationValueList) { - if ( MockHelper.isNotEmpty( fieldResultList ) ) { + if ( CollectionHelper.isNotEmpty( fieldResultList ) ) { AnnotationValue[] values = new AnnotationValue[fieldResultList.size()]; for ( int i = 0; i < fieldResultList.size(); i++ ) { - AnnotationInstance annotationInstance = parserFieldResult( fieldResultList.get( i ) ); + AnnotationInstance annotationInstance = parseFieldResult( fieldResultList.get( i ) ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -197,24 +198,24 @@ class GlobalAnnotationMocker extends AbstractMocker { } } - private AnnotationInstance parserNamedNativeQueries(Collection namedQueries) { + private AnnotationInstance parseNamedNativeQueries(Collection namedQueries) { AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; int i = 0; for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserNamedNativeQuery( iterator.next() ); + AnnotationInstance annotationInstance = parseNamedNativeQuery( iterator.next() ); values[i++] = MockHelper.nestedAnnotationValue( "", annotationInstance ); } return create( NAMED_NATIVE_QUERIES, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } ); } //@NamedNativeQuery - private AnnotationInstance parserNamedNativeQuery(JaxbNamedNativeQuery namedNativeQuery) { + private AnnotationInstance parseNamedNativeQuery(JaxbNamedNativeQuery namedNativeQuery) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", namedNativeQuery.getName(), annotationValueList ); MockHelper.stringValue( "query", namedNativeQuery.getQuery(), annotationValueList ); @@ -233,25 +234,25 @@ class GlobalAnnotationMocker extends AbstractMocker { } - private AnnotationInstance parserNamedQueries(Collection namedQueries) { + private AnnotationInstance parseNamedQueries(Collection namedQueries) { AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; int i = 0; for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserNamedQuery( iterator.next() ); + AnnotationInstance annotationInstance = parseNamedQuery( iterator.next() ); values[i++] = MockHelper.nestedAnnotationValue( "", annotationInstance ); } return create( NAMED_QUERIES, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } ); } //@NamedQuery - private AnnotationInstance parserNamedQuery(JaxbNamedQuery namedQuery) { + private AnnotationInstance parseNamedQuery(JaxbNamedQuery namedQuery) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", namedQuery.getName(), annotationValueList ); MockHelper.stringValue( "query", namedQuery.getQuery(), annotationValueList ); @@ -261,7 +262,7 @@ class GlobalAnnotationMocker extends AbstractMocker { } //@QueryHint - private AnnotationInstance parserQueryHint(JaxbQueryHint queryHint) { + private AnnotationInstance parseQueryHint(JaxbQueryHint queryHint) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", queryHint.getName(), annotationValueList ); MockHelper.stringValue( "value", queryHint.getValue(), annotationValueList ); @@ -270,10 +271,10 @@ class GlobalAnnotationMocker extends AbstractMocker { } private void nestedQueryHintList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { AnnotationValue[] values = new AnnotationValue[constraints.size()]; for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserQueryHint( constraints.get( i ) ); + AnnotationInstance annotationInstance = parseQueryHint( constraints.get( i ) ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -286,7 +287,7 @@ class GlobalAnnotationMocker extends AbstractMocker { //@SequenceGenerator - private AnnotationInstance parserSequenceGenerator(JaxbSequenceGenerator generator) { + private AnnotationInstance parseSequenceGenerator(JaxbSequenceGenerator generator) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", generator.getName(), annotationValueList ); MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); @@ -302,7 +303,7 @@ class GlobalAnnotationMocker extends AbstractMocker { } //@TableGenerator - private AnnotationInstance parserTableGenerator(JaxbTableGenerator generator) { + private AnnotationInstance parseTableGenerator(JaxbTableGenerator generator) { List annotationValueList = new ArrayList(); MockHelper.stringValue( "name", generator.getName(), annotationValueList ); MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); @@ -314,6 +315,7 @@ class GlobalAnnotationMocker extends AbstractMocker { MockHelper.integerValue( "initialValue", generator.getInitialValue(), annotationValueList ); MockHelper.integerValue( "allocationSize", generator.getAllocationSize(), annotationValueList ); nestedUniqueConstraintList( "uniqueConstraints", generator.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", generator.getIndex(), annotationValueList ); return create( TABLE_GENERATOR, null, annotationValueList diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotations.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotations.java index efba9e67e6..1098efdc37 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/GlobalAnnotations.java @@ -21,34 +21,36 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedNativeQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSequenceGenerator; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSqlResultSetMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTableGenerator; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.JPADotNames; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; import org.jboss.logging.Logger; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.jaxb.spi.orm.JaxbEntityMappings; +import org.hibernate.jaxb.spi.orm.JaxbId; +import org.hibernate.jaxb.spi.orm.JaxbNamedNativeQuery; +import org.hibernate.jaxb.spi.orm.JaxbNamedQuery; +import org.hibernate.jaxb.spi.orm.JaxbSequenceGenerator; +import org.hibernate.jaxb.spi.orm.JaxbSqlResultSetMapping; +import org.hibernate.jaxb.spi.orm.JaxbTableGenerator; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.source.MappingException; + /** * @author Strong Liu */ @@ -57,18 +59,18 @@ class GlobalAnnotations implements JPADotNames { CoreMessageLogger.class, GlobalAnnotations.class.getName() ); - private Map sequenceGeneratorMap = new HashMap(); - private Map tableGeneratorMap = new HashMap(); - private Map namedQueryMap = new HashMap(); - private Map namedNativeQueryMap = new HashMap(); - private Map sqlResultSetMappingMap = new HashMap(); - private Map> annotationInstanceMap = new HashMap>(); - private List indexedAnnotationInstanceList = new ArrayList(); + private final Map sequenceGeneratorMap = new HashMap(); + private final Map tableGeneratorMap = new HashMap(); + private final Map namedQueryMap = new HashMap(); + private final Map namedNativeQueryMap = new HashMap(); + private final Map sqlResultSetMappingMap = new HashMap(); + private final Map> annotationInstanceMap = new HashMap>(); + private final List indexedAnnotationInstanceList = new ArrayList(); //--------------------------- - private Set defaultNamedNativeQueryNames = new HashSet(); - private Set defaultNamedQueryNames = new HashSet(); - private Set defaultNamedGenerators = new HashSet(); - private Set defaultSqlResultSetMappingNames = new HashSet(); + private final Set defaultNamedNativeQueryNames = new HashSet(); + private final Set defaultNamedQueryNames = new HashSet(); + private final Set defaultNamedGenerators = new HashSet(); + private final Set defaultSqlResultSetMappingNames = new HashSet(); Map> getAnnotationInstanceMap() { return annotationInstanceMap; @@ -88,8 +90,8 @@ class GlobalAnnotations implements JPADotNames { } - void addIndexedAnnotationInstance(List annotationInstanceList) { - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { + void addIndexedAnnotationInstance(Collection annotationInstanceList) { + if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) { indexedAnnotationInstanceList.addAll( annotationInstanceList ); } } @@ -98,8 +100,11 @@ class GlobalAnnotations implements JPADotNames { * do the orm xmls define global configurations? */ boolean hasGlobalConfiguration() { - return !( namedQueryMap.isEmpty() && namedNativeQueryMap.isEmpty() && sequenceGeneratorMap.isEmpty() && tableGeneratorMap - .isEmpty() && sqlResultSetMappingMap.isEmpty() ); + return !( namedQueryMap.isEmpty() + && namedNativeQueryMap.isEmpty() + && sequenceGeneratorMap.isEmpty() + && tableGeneratorMap.isEmpty() + && sqlResultSetMappingMap.isEmpty() ); } Map getNamedNativeQueryMap() { @@ -140,12 +145,14 @@ class GlobalAnnotations implements JPADotNames { } else { AnnotationValue value = annotationInstance.value( "name" ); - String name = value.asString(); - isNotExist = ( annName.equals( TABLE_GENERATOR ) && !tableGeneratorMap.containsKey( name ) ) || - ( annName.equals( SEQUENCE_GENERATOR ) && !sequenceGeneratorMap.containsKey( name ) ) || - ( annName.equals( NAMED_QUERY ) && !namedQueryMap.containsKey( name ) ) || - ( annName.equals( NAMED_NATIVE_QUERY ) && !namedNativeQueryMap.containsKey( name ) ) || - ( annName.equals( SQL_RESULT_SET_MAPPING ) && !sqlResultSetMappingMap.containsKey( name ) ); + if ( value != null ) { + String name = value.asString(); + isNotExist = ( annName.equals( TABLE_GENERATOR ) && !tableGeneratorMap.containsKey( name ) ) || + ( annName.equals( SEQUENCE_GENERATOR ) && !sequenceGeneratorMap.containsKey( name ) ) || + ( annName.equals( NAMED_QUERY ) && !namedQueryMap.containsKey( name ) ) || + ( annName.equals( NAMED_NATIVE_QUERY ) && !namedNativeQueryMap.containsKey( name ) ) || + ( annName.equals( SQL_RESULT_SET_MAPPING ) && !sqlResultSetMappingMap.containsKey( name ) ); + } } if ( isNotExist ) { push( annName, annotationInstance ); @@ -227,34 +234,13 @@ class GlobalAnnotations implements JPADotNames { /** * Override SequenceGenerator using info definded in EntityMappings/Persistence-Metadata-Unit */ - private static JaxbSequenceGenerator overrideGenerator(JaxbSequenceGenerator generator, EntityMappingsMocker.Default defaults) { + private static void overrideGenerator(SchemaAware generator, EntityMappingsMocker.Default defaults) { if ( StringHelper.isEmpty( generator.getSchema() ) && defaults != null ) { generator.setSchema( defaults.getSchema() ); } if ( StringHelper.isEmpty( generator.getCatalog() ) && defaults != null ) { generator.setCatalog( defaults.getCatalog() ); } - return generator; - } - - /** - * Override TableGenerator using info definded in EntityMappings/Persistence-Metadata-Unit - */ - private static JaxbTableGenerator overrideGenerator(JaxbTableGenerator generator, EntityMappingsMocker.Default defaults) { - if ( StringHelper.isEmpty( generator.getSchema() ) && defaults != null ) { - generator.setSchema( defaults.getSchema() ); - } - if ( StringHelper.isEmpty( generator.getCatalog() ) && defaults != null ) { - generator.setCatalog( defaults.getCatalog() ); - } - return generator; - } - - private void put(JaxbNamedNativeQuery query) { - if ( query != null ) { - checkQueryName( query.getName() ); - namedNativeQueryMap.put( query.getName(), query ); - } } private void checkQueryName(String name) { @@ -262,6 +248,11 @@ class GlobalAnnotations implements JPADotNames { throw new MappingException( "Duplicated query mapping " + name, null ); } } + private void checkDuplicated(Object old, String name){ + if ( old != null ) { + LOG.duplicateGeneratorName( name ); + } + } private void put(JaxbNamedQuery query) { if ( query != null ) { @@ -272,19 +263,23 @@ class GlobalAnnotations implements JPADotNames { private void put(JaxbSequenceGenerator generator, EntityMappingsMocker.Default defaults) { if ( generator != null ) { - Object old = sequenceGeneratorMap.put( generator.getName(), overrideGenerator( generator, defaults ) ); - if ( old != null ) { - LOG.duplicateGeneratorName( generator.getName() ); - } + overrideGenerator( generator, defaults ); + Object old = sequenceGeneratorMap.put( generator.getName(), generator ); + checkDuplicated( old, generator.getName() ); } } private void put(JaxbTableGenerator generator, EntityMappingsMocker.Default defaults) { if ( generator != null ) { - Object old = tableGeneratorMap.put( generator.getName(), overrideGenerator( generator, defaults ) ); - if ( old != null ) { - LOG.duplicateGeneratorName( generator.getName() ); - } + overrideGenerator( generator, defaults ); + Object old = tableGeneratorMap.put( generator.getName(), generator ); + checkDuplicated( old, generator.getName() ); + } + } + private void put(JaxbNamedNativeQuery query) { + if ( query != null ) { + checkQueryName( query.getName() ); + namedNativeQueryMap.put( query.getName(), query ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IdMocker.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IdMocker.java index 150b8fa011..79a8021d20 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IdMocker.java @@ -21,25 +21,24 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbGeneratedValue; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbGeneratedValue; +import org.hibernate.jaxb.spi.orm.JaxbId; + /** * @author Strong Liu */ class IdMocker extends PropertyMocker { - private JaxbId id; + private final JaxbId id; IdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbId id) { super( indexBuilder, classInfo, defaults ); @@ -47,14 +46,19 @@ class IdMocker extends PropertyMocker { } @Override - protected void processExtra() { - create( ID ); - parserColumn( id.getColumn(), getTarget() ); - parserGeneratedValue( id.getGeneratedValue(), getTarget() ); - parserTemporalType( id.getTemporal(), getTarget() ); + protected PropertyElement getPropertyElement() { + return id; } - private AnnotationInstance parserGeneratedValue(JaxbGeneratedValue generatedValue, AnnotationTarget target) { + @Override + protected void processExtra() { + create( ID ); + parseColumn( id.getColumn(), getTarget() ); + parseGeneratedValue( id.getGeneratedValue(), getTarget() ); + parseTemporalType( id.getTemporal(), getTarget() ); + } + + private AnnotationInstance parseGeneratedValue(JaxbGeneratedValue generatedValue, AnnotationTarget target) { if ( generatedValue == null ) { return null; } @@ -66,19 +70,4 @@ class IdMocker extends PropertyMocker { return create( GENERATED_VALUE, target, annotationValueList ); } - - @Override - protected String getFieldName() { - return id.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return id.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - id.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilder.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilder.java index 90e19ce82f..d67bc038d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilder.java @@ -21,27 +21,31 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.hibernate.AssertionFailure; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.xml.filter.IndexedAnnotationFilter; -import org.hibernate.service.ServiceRegistry; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.jboss.logging.Logger; +import org.hibernate.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.source.annotations.xml.filter.IndexedAnnotationFilter; +import org.hibernate.service.ServiceRegistry; + /** * @author Strong Liu */ @@ -50,16 +54,16 @@ public class IndexBuilder { CoreMessageLogger.class, IndexBuilder.class.getName() ); - private Map> annotations; - private Map> subclasses; - private Map> implementors; - private Map classes; - private Index index; - private Map>> classInfoAnnotationsMap; - private Map>> indexedClassInfoAnnotationsMap; - private ServiceRegistry serviceRegistry; + private final Map> annotations; + private final Map> subclasses; + private final Map> implementors; + private final Map classes; + private IndexView index; + private final Map>> classInfoAnnotationsMap; + private final Map>> indexedClassInfoAnnotationsMap; + private final ServiceRegistry serviceRegistry; - IndexBuilder(Index index, ServiceRegistry serviceRegistry) { + IndexBuilder(IndexView index, ServiceRegistry serviceRegistry) { this.index = index; this.serviceRegistry = serviceRegistry; this.annotations = new HashMap>(); @@ -72,7 +76,7 @@ public class IndexBuilder { /** * Build new {@link Index} with mocked annotations from orm.xml. - * This method should be only called once per {@org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder IndexBuilder} instance. + * This method should be only called once per {@link IndexBuilder} instance. * * @param globalDefaults Global defaults from , or null. * @@ -86,17 +90,19 @@ public class IndexBuilder { //this class has been overrided by orm.xml continue; } - if ( ci.annotations() != null && !ci.annotations().isEmpty() ) { + ClassInfo mockedClassInfo = createClassInfo( name.toString() ); + if ( CollectionHelper.isNotEmpty( ci.annotations() ) ) { Map> tmp = new HashMap>( ci.annotations() ); DefaultConfigurationHelper.INSTANCE.applyDefaults( tmp, globalDefaults ); mergeAnnotationMap( tmp, annotations ); - classes.put( name, ci ); - if ( ci.superName() != null ) { - addSubClasses( ci.superName(), ci ); - } - if ( ci.interfaces() != null && ci.interfaces().length > 0 ) { - addImplementors( ci.interfaces(), ci ); - } + classInfoAnnotationsMap.get( name ).putAll( tmp ); +// classes.put( name, ci ); +// if ( ci.superName() != null ) { +// addSubClasses( ci.superName(), ci ); +// } +// if ( CollectionHelper.isNotEmpty( ci.interfaces() ) ) { +// addImplementors( ci.interfaces(), ci ); +// } } } return Index.create( @@ -166,9 +172,9 @@ public class IndexBuilder { void collectGlobalConfigurationFromIndex(GlobalAnnotations globalAnnotations) { for ( DotName annName : DefaultConfigurationHelper.GLOBAL_ANNOTATIONS ) { - List annotationInstanceList = index.getAnnotations( annName ); - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { - globalAnnotations.addIndexedAnnotationInstance( annotationInstanceList ); + Collection annotationInstances = index.getAnnotations( annName ); + if ( CollectionHelper.isNotEmpty( annotationInstances ) ) { + globalAnnotations.addIndexedAnnotationInstance( annotationInstances ); } } globalAnnotations.filterIndexedAnnotations(); @@ -218,16 +224,27 @@ public class IndexBuilder { return serviceRegistry; } - ClassInfo createClassInfo(String className) { + ClassInfo createClassInfo(String className, String optionalPerfix){ if ( StringHelper.isEmpty( className ) ) { throw new AssertionFailure( "Class Name used to create ClassInfo is empty." ); } + Class clazz = null; + try { + clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( className ); + } + catch ( ClassLoadingException e ) { + if ( StringHelper.isNotEmpty( optionalPerfix ) ) { + className = StringHelper.qualify( optionalPerfix, className ); + clazz = serviceRegistry.getService( ClassLoaderService.class ) + .classForName( className ); + } + } DotName classDotName = DotName.createSimple( className ); if ( classes.containsKey( classDotName ) ) { //classInfoAnnotationsMap.put( classDotName, new HashMap>(classes.get( classDotName ).annotations()) ); return classes.get( classDotName ); } - Class clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( className ); + DotName superName = null; DotName[] interfaces = null; short access_flag; @@ -262,6 +279,10 @@ public class IndexBuilder { return classInfo; } + ClassInfo createClassInfo(String className) { + return createClassInfo( className, null ); + } + private void addSubClasses(DotName superClassDotName, ClassInfo classInfo) { if ( superClassDotName != null ) { List classInfoList = subclasses.get( superClassDotName ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Listener.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Listener.java new file mode 100644 index 0000000000..c2093d1456 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Listener.java @@ -0,0 +1,8 @@ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +/** + * @author Strong Liu + */ +public interface Listener { + public String getMethodName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ListenerMocker.java similarity index 55% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ListenerMocker.java index 58f946667a..bab3572da8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ListenerMocker.java @@ -21,26 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.MappingException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListener; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +import org.hibernate.MappingException; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.orm.JaxbEntityListener; +import org.hibernate.jaxb.spi.orm.JaxbEntityListeners; /** * {@link javax.persistence.EntityListeners @EntityListeners} mocker @@ -55,7 +50,7 @@ class ListenerMocker extends AbstractMocker { this.classInfo = classInfo; } - AnnotationInstance parser(JaxbEntityListeners entityListeners) { + AnnotationInstance parse(JaxbEntityListeners entityListeners) { if ( entityListeners.getEntityListener().isEmpty() ) { throw new MappingException( "No child element of found under ." ); } @@ -63,86 +58,40 @@ class ListenerMocker extends AbstractMocker { List clazzNameList = new ArrayList( entityListeners.getEntityListener().size() ); for ( JaxbEntityListener listener : entityListeners.getEntityListener() ) { MockHelper.addToCollectionIfNotNull( clazzNameList, listener.getClazz() ); - parserEntityListener( listener ); + parseEntityListener( listener, clazzNameList ); } MockHelper.classArrayValue( "value", clazzNameList, annotationValueList, indexBuilder.getServiceRegistry() ); return create( ENTITY_LISTENERS, classInfo, annotationValueList ); } - private void parserEntityListener(JaxbEntityListener listener) { + private void parseEntityListener(JaxbEntityListener listener, List clazzNameList) { String clazz = listener.getClazz(); - ClassInfo tempClassInfo = indexBuilder.createClassInfo( clazz ); + String defaultPackageName = classInfo!=null ? StringHelper.qualifier(classInfo.name().toString()) : null; + ClassInfo tempClassInfo = indexBuilder.createClassInfo( clazz,defaultPackageName ); + if ( !clazz.equals( tempClassInfo.name().toString() ) ) { + clazzNameList.remove( clazz ); + clazzNameList.add( tempClassInfo.name().toString() ); + } ListenerMocker mocker = createListenerMocker( indexBuilder, tempClassInfo ); - mocker.parser( listener.getPostLoad() ); - mocker.parser( listener.getPostPersist() ); - mocker.parser( listener.getPostRemove() ); - mocker.parser( listener.getPostUpdate() ); - mocker.parser( listener.getPrePersist() ); - mocker.parser( listener.getPreRemove() ); - mocker.parser( listener.getPreUpdate() ); + mocker.parse( listener.getPostLoad(), POST_LOAD ); + mocker.parse( listener.getPostPersist(), POST_PERSIST ); + mocker.parse( listener.getPostRemove(), POST_REMOVE ); + mocker.parse( listener.getPostUpdate(), POST_UPDATE ); + mocker.parse( listener.getPrePersist(), PRE_PERSIST ); + mocker.parse( listener.getPreRemove(), PRE_REMOVE ); + mocker.parse( listener.getPreUpdate(), PRE_UPDATE ); indexBuilder.finishEntityObject( tempClassInfo.name(), null ); } protected ListenerMocker createListenerMocker(IndexBuilder indexBuilder, ClassInfo classInfo) { return new ListenerMocker( indexBuilder, classInfo ); } - - //@PrePersist - AnnotationInstance parser(JaxbPrePersist callback) { + AnnotationInstance parse(Listener callback, DotName target) { if ( callback == null ) { return null; } - return create( PRE_PERSIST, getListenerTarget( callback.getMethodName() ) ); + return create( target, getListenerTarget( callback.getMethodName() ) ); } - - //@PreRemove - AnnotationInstance parser(JaxbPreRemove callback) { - if ( callback == null ) { - return null; - } - return create( PRE_REMOVE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PreUpdate - AnnotationInstance parser(JaxbPreUpdate callback) { - if ( callback == null ) { - return null; - } - return create( PRE_UPDATE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostPersist - AnnotationInstance parser(JaxbPostPersist callback) { - if ( callback == null ) { - return null; - } - return create( POST_PERSIST, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostUpdate - AnnotationInstance parser(JaxbPostUpdate callback) { - if ( callback == null ) { - return null; - } - return create( POST_UPDATE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostRemove - AnnotationInstance parser(JaxbPostRemove callback) { - if ( callback == null ) { - return null; - } - return create( POST_REMOVE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostLoad - AnnotationInstance parser(JaxbPostLoad callback) { - if ( callback == null ) { - return null; - } - return create( POST_LOAD, getListenerTarget( callback.getMethodName() ) ); - } - private AnnotationTarget getListenerTarget(String methodName) { return MockHelper.getTarget( indexBuilder.getServiceRegistry(), classInfo, methodName, MockHelper.TargetType.METHOD diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToManyMocker.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToManyMocker.java index 985892209a..abcb635f7a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToManyMocker.java @@ -21,34 +21,31 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbManyToMany; + /** * @author Strong Liu */ class ManyToManyMocker extends PropertyMocker { - private JaxbManyToMany manyToMany; + private final JaxbManyToMany manyToMany; ManyToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbManyToMany manyToMany) { super( indexBuilder, classInfo, defaults ); this.manyToMany = manyToMany; } - @Override - protected String getFieldName() { - return manyToMany.getName(); + protected PropertyElement getPropertyElement() { + return manyToMany; } - @Override protected void processExtra() { List annotationValueList = new ArrayList(); @@ -59,26 +56,16 @@ class ManyToManyMocker extends PropertyMocker { MockHelper.stringValue( "mappedBy", manyToMany.getMappedBy(), annotationValueList ); MockHelper.cascadeValue( "cascade", manyToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); create( MANY_TO_MANY, annotationValueList ); - parserMapKeyClass( manyToMany.getMapKeyClass(), getTarget() ); - parserMapKeyTemporal( manyToMany.getMapKeyTemporal(), getTarget() ); - parserMapKeyEnumerated( manyToMany.getMapKeyEnumerated(), getTarget() ); - parserMapKey( manyToMany.getMapKey(), getTarget() ); - parserAttributeOverrides( manyToMany.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( manyToMany.getMapKeyJoinColumn(), getTarget() ); - parserOrderColumn( manyToMany.getOrderColumn(), getTarget() ); - parserJoinTable( manyToMany.getJoinTable(), getTarget() ); + parseMapKeyClass( manyToMany.getMapKeyClass(), getTarget() ); + parseMapKeyTemporal( manyToMany.getMapKeyTemporal(), getTarget() ); + parseMapKeyEnumerated( manyToMany.getMapKeyEnumerated(), getTarget() ); + parseMapKey( manyToMany.getMapKey(), getTarget() ); + parseAttributeOverrides( manyToMany.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( manyToMany.getMapKeyJoinColumn(), getTarget() ); + parseOrderColumn( manyToMany.getOrderColumn(), getTarget() ); + parseJoinTable( manyToMany.getJoinTable(), getTarget() ); if ( manyToMany.getOrderBy() != null ) { create( ORDER_BY, MockHelper.stringValueArray( "value", manyToMany.getOrderBy() ) ); } } - - @Override - protected JaxbAccessType getAccessType() { - return manyToMany.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - manyToMany.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToOneMocker.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToOneMocker.java index c3dca779a1..0d6e57bf5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ManyToOneMocker.java @@ -21,22 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbManyToOne; + /** * @author Strong Liu */ class ManyToOneMocker extends PropertyMocker { - private JaxbManyToOne manyToOne; + private final JaxbManyToOne manyToOne; ManyToOneMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbManyToOne manyToOne) { super( indexBuilder, classInfo, defaults ); @@ -44,8 +43,8 @@ class ManyToOneMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return manyToOne.getName(); + protected PropertyElement getPropertyElement() { + return manyToOne; } @Override @@ -58,8 +57,8 @@ class ManyToOneMocker extends PropertyMocker { MockHelper.booleanValue( "optional", manyToOne.isOptional(), annotationValueList ); MockHelper.cascadeValue( "cascade", manyToOne.getCascade(), isDefaultCascadePersist(), annotationValueList ); create( MANY_TO_ONE, annotationValueList ); - parserJoinColumnList( manyToOne.getJoinColumn(), getTarget() ); - parserJoinTable( manyToOne.getJoinTable(), getTarget() ); + parseJoinColumnList( manyToOne.getJoinColumn(), getTarget() ); + parseJoinTable( manyToOne.getJoinTable(), getTarget() ); if ( manyToOne.getMapsId() != null ) { create( MAPS_ID, MockHelper.stringValueArray( "value", manyToOne.getMapsId() ) ); } @@ -67,14 +66,4 @@ class ManyToOneMocker extends PropertyMocker { create( ID ); } } - - @Override - protected JaxbAccessType getAccessType() { - return manyToOne.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - manyToOne.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MappedSuperclassMocker.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MappedSuperclassMocker.java index 018a1b53c0..fa305410d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MappedSuperclassMocker.java @@ -21,24 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.logging.Logger; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEntityListeners; +import org.hibernate.jaxb.spi.orm.JaxbIdClass; +import org.hibernate.jaxb.spi.orm.JaxbMappedSuperclass; +import org.hibernate.jaxb.spi.orm.JaxbPostLoad; +import org.hibernate.jaxb.spi.orm.JaxbPostPersist; +import org.hibernate.jaxb.spi.orm.JaxbPostRemove; +import org.hibernate.jaxb.spi.orm.JaxbPostUpdate; +import org.hibernate.jaxb.spi.orm.JaxbPrePersist; +import org.hibernate.jaxb.spi.orm.JaxbPreRemove; +import org.hibernate.jaxb.spi.orm.JaxbPreUpdate; + /** * Mock to {@link javax.persistence.MappedSuperclass @MappedSuperClass} * @@ -57,8 +56,8 @@ class MappedSuperclassMocker extends AbstractEntityObjectMocker { } @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( mappedSuperclass, getDefaults() ); + protected EntityElement getEntityElement() { + return mappedSuperclass; } @Override @@ -70,17 +69,6 @@ class MappedSuperclassMocker extends AbstractEntityObjectMocker { protected JaxbAttributes getAttributes() { return mappedSuperclass.getAttributes(); } - - @Override - protected JaxbAccessType getAccessType() { - return mappedSuperclass.getAccess(); - } - - @Override - protected boolean isMetadataComplete() { - return mappedSuperclass.isMetadataComplete() != null && mappedSuperclass.isMetadataComplete(); - } - @Override protected boolean isExcludeDefaultListeners() { return mappedSuperclass.getExcludeDefaultListeners() != null; @@ -101,10 +89,6 @@ class MappedSuperclassMocker extends AbstractEntityObjectMocker { return mappedSuperclass.getEntityListeners(); } - protected String getClassName() { - return mappedSuperclass.getClazz(); - } - @Override protected JaxbPrePersist getPrePersist() { return mappedSuperclass.getPrePersist(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MockHelper.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MockHelper.java index a2e71bdcc7..d2582a3e9d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/MockHelper.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.beans.Introspector; import java.lang.reflect.Field; @@ -29,13 +29,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; - -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.mapping.orm.JaxbCascadeType; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.service.ServiceRegistry; +import javax.persistence.CascadeType; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; @@ -46,12 +40,20 @@ import org.jboss.jandex.FieldInfo; import org.jboss.jandex.MethodInfo; import org.jboss.jandex.Type; +import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbCascadeType; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.service.ServiceRegistry; + /** * @author Strong Liu */ public class MockHelper { - static final AnnotationValue[] EMPTY_ANNOTATION_VALUE_ARRAY = new AnnotationValue[0]; + public static final AnnotationValue[] EMPTY_ANNOTATION_VALUE_ARRAY = new AnnotationValue[0]; static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; /** @@ -62,7 +64,7 @@ public class MockHelper { * @param annotationValueList */ static void stringArrayValue(String name, List values, List annotationValueList) { - if ( isNotEmpty( values ) ) { + if ( CollectionHelper.isNotEmpty( values ) ) { AnnotationValue[] annotationValues = new AnnotationValue[values.size()]; for ( int j = 0; j < values.size(); j++ ) { annotationValues[j] = stringValue( "", values.get( j ) ); @@ -149,13 +151,11 @@ public class MockHelper { } private static AnnotationValue[] nullSafe(AnnotationValue value) { - return value == null ? EMPTY_ANNOTATION_VALUE_ARRAY : new AnnotationValue[] { - value - }; + return value == null ? EMPTY_ANNOTATION_VALUE_ARRAY : new AnnotationValue[] {value}; } static void classArrayValue(String name, List classNameList, List list, ServiceRegistry serviceRegistry) { - if ( isNotEmpty( classNameList ) ) { + if ( CollectionHelper.isNotEmpty( classNameList ) ) { List clazzValueList = new ArrayList( classNameList.size() ); for ( String clazz : classNameList ) { @@ -172,7 +172,7 @@ public class MockHelper { public static AnnotationValue[] toArray(List list) { AnnotationValue[] values = EMPTY_ANNOTATION_VALUE_ARRAY; - if ( isNotEmpty( list ) ) { + if ( CollectionHelper.isNotEmpty( list ) ) { values = list.toArray( new AnnotationValue[list.size()] ); } return values; @@ -191,32 +191,26 @@ public class MockHelper { enumList.add( javax.persistence.CascadeType.PERSIST ); } if ( cascadeType != null ) { - if ( cascadeType.getCascadeAll() != null ) { - enumList.add( javax.persistence.CascadeType.ALL ); - } - if ( cascadeType.getCascadePersist() != null && !isCascadePersistDefault ) { - enumList.add( javax.persistence.CascadeType.PERSIST ); - } - if ( cascadeType.getCascadeMerge() != null ) { - enumList.add( javax.persistence.CascadeType.MERGE ); - } - if ( cascadeType.getCascadeRemove() != null ) { - enumList.add( javax.persistence.CascadeType.REMOVE ); - } - if ( cascadeType.getCascadeRefresh() != null ) { - enumList.add( javax.persistence.CascadeType.REFRESH ); - } - if ( cascadeType.getCascadeDetach() != null ) { - enumList.add( javax.persistence.CascadeType.DETACH ); - } + addIfNotNull( cascadeType.getCascadeAll(), enumList, CascadeType.ALL ); + addIfNotNull( cascadeType.getCascadePersist(), enumList, CascadeType.PERSIST ); + addIfNotNull( cascadeType.getCascadeMerge(), enumList, CascadeType.MERGE ); + addIfNotNull( cascadeType.getCascadeRemove(), enumList, CascadeType.REMOVE ); + addIfNotNull( cascadeType.getCascadeRefresh(), enumList, CascadeType.REFRESH ); + addIfNotNull( cascadeType.getCascadeDetach(), enumList , CascadeType.DETACH ); } if ( !enumList.isEmpty() ) { MockHelper.enumArrayValue( name, JPADotNames.CASCADE_TYPE, enumList, annotationValueList ); } } + private static void addIfNotNull(Object expect, List enumList, CascadeType value) { + if ( expect != null ) { + enumList.add( value); + } + } + static void enumArrayValue(String name, DotName typeName, List valueList, List list) { - if ( isNotEmpty( valueList ) ) { + if ( CollectionHelper.isNotEmpty( valueList ) ) { List enumValueList = new ArrayList( valueList.size() ); for ( Enum e : valueList ) { @@ -270,11 +264,6 @@ public class MockHelper { return false; } - public static boolean isNotEmpty(Collection collection) { - return collection != null && !collection.isEmpty(); - } - - static AnnotationInstance create(DotName name, AnnotationTarget target, List annotationValueList) { return create( name, target, toArray( annotationValueList ) @@ -283,7 +272,7 @@ public class MockHelper { } static String buildSafeClassName(String className, String defaultPackageName) { - if ( className.indexOf( '.' ) < 0 && StringHelper.isNotEmpty( defaultPackageName ) ) { + if ( className!= null && className.indexOf( '.' ) < 0 && StringHelper.isNotEmpty( defaultPackageName ) ) { className = StringHelper.qualify( defaultPackageName, className ); } return className; @@ -316,9 +305,9 @@ public class MockHelper { ); } - enum TargetType {METHOD, FIELD, PROPERTY} + public enum TargetType {METHOD, FIELD, PROPERTY} - static AnnotationTarget getTarget(ServiceRegistry serviceRegistry, ClassInfo classInfo, String name, TargetType type) { + public static AnnotationTarget getTarget(ServiceRegistry serviceRegistry, ClassInfo classInfo, String name, TargetType type) { Class clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( classInfo.toString() ); switch ( type ) { case FIELD: @@ -403,9 +392,9 @@ public class MockHelper { Method.setAccessible( methods, true ); for ( Method method : methods ) { // if the method has parameters, skip it - if ( method.getParameterTypes().length != 0 ) { - continue; - } +// if ( method.getParameterTypes().length != 0 ) { +// continue; +// } // if the method is a "bridge", skip it if ( method.isBridge() ) { continue; @@ -451,7 +440,7 @@ public class MockHelper { return Type.create( DotName.createSimple( clazz.getName() ), getTypeKind( clazz ) ); } - private static Type.Kind getTypeKind(Class clazz) { + public static Type.Kind getTypeKind(Class clazz) { Type.Kind kind; if ( clazz == Void.TYPE ) { kind = Type.Kind.VOID; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToManyMocker.java similarity index 63% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToManyMocker.java index ee957d0d56..cd6366b5f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToManyMocker.java @@ -21,22 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbOneToMany; + /** * @author Strong Liu */ class OneToManyMocker extends PropertyMocker { - private JaxbOneToMany oneToMany; + private final JaxbOneToMany oneToMany; OneToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbOneToMany oneToMany) { super( indexBuilder, classInfo, defaults ); @@ -44,43 +43,32 @@ class OneToManyMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return oneToMany.getName(); + protected PropertyElement getPropertyElement() { + return oneToMany; } - @Override protected void processExtra() { List annotationValueList = new ArrayList(); MockHelper.classValue( - "targetEntity", oneToMany.getTargetEntity(), annotationValueList, indexBuilder.getServiceRegistry() + "targetEntity", MockHelper.buildSafeClassName( oneToMany.getTargetEntity(), getDefaults().getPackageName() ), annotationValueList, indexBuilder.getServiceRegistry() ); MockHelper.enumValue( "fetch", FETCH_TYPE, oneToMany.getFetch(), annotationValueList ); MockHelper.stringValue( "mappedBy", oneToMany.getMappedBy(), annotationValueList ); MockHelper.booleanValue( "orphanRemoval", oneToMany.isOrphanRemoval(), annotationValueList ); MockHelper.cascadeValue( "cascade", oneToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); create( ONE_TO_MANY, getTarget(), annotationValueList ); - parserAttributeOverrides( oneToMany.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( oneToMany.getMapKeyJoinColumn(), getTarget() ); - parserMapKey( oneToMany.getMapKey(), getTarget() ); - parserMapKeyColumn( oneToMany.getMapKeyColumn(), getTarget() ); - parserMapKeyClass( oneToMany.getMapKeyClass(), getTarget() ); - parserMapKeyTemporal( oneToMany.getMapKeyTemporal(), getTarget() ); - parserMapKeyEnumerated( oneToMany.getMapKeyEnumerated(), getTarget() ); - parserJoinColumnList( oneToMany.getJoinColumn(), getTarget() ); - parserOrderColumn( oneToMany.getOrderColumn(), getTarget() ); - parserJoinTable( oneToMany.getJoinTable(), getTarget() ); + parseAttributeOverrides( oneToMany.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( oneToMany.getMapKeyJoinColumn(), getTarget() ); + parseMapKey( oneToMany.getMapKey(), getTarget() ); + parseMapKeyColumn( oneToMany.getMapKeyColumn(), getTarget() ); + parseMapKeyClass( oneToMany.getMapKeyClass(), getTarget() ); + parseMapKeyTemporal( oneToMany.getMapKeyTemporal(), getTarget() ); + parseMapKeyEnumerated( oneToMany.getMapKeyEnumerated(), getTarget() ); + parseJoinColumnList( oneToMany.getJoinColumn(), getTarget() ); + parseOrderColumn( oneToMany.getOrderColumn(), getTarget() ); + parseJoinTable( oneToMany.getJoinTable(), getTarget() ); if ( oneToMany.getOrderBy() != null ) { create( ORDER_BY, getTarget(), MockHelper.stringValueArray( "value", oneToMany.getOrderBy() ) ); } } - - @Override - protected JaxbAccessType getAccessType() { - return oneToMany.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - oneToMany.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToOneMocker.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToOneMocker.java index f99f4eaa70..d197f4a52d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OneToOneMocker.java @@ -21,17 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; - import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbOneToOne; + /** * @author Strong Liu */ @@ -44,8 +43,8 @@ class OneToOneMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return oneToOne.getName(); + protected PropertyElement getPropertyElement() { + return oneToOne; } @Override @@ -61,9 +60,9 @@ class OneToOneMocker extends PropertyMocker { MockHelper.cascadeValue( "cascade", oneToOne.getCascade(), isDefaultCascadePersist(), annotationValueList ); create( ONE_TO_ONE, annotationValueList ); - parserPrimaryKeyJoinColumnList( oneToOne.getPrimaryKeyJoinColumn(), getTarget() ); - parserJoinColumnList( oneToOne.getJoinColumn(), getTarget() ); - parserJoinTable( oneToOne.getJoinTable(), getTarget() ); + parsePrimaryKeyJoinColumnList( oneToOne.getPrimaryKeyJoinColumn(), getTarget() ); + parseJoinColumnList( oneToOne.getJoinColumn(), getTarget() ); + parseJoinTable( oneToOne.getJoinTable(), getTarget() ); if ( oneToOne.getMapsId() != null ) { create( MAPS_ID, MockHelper.stringValueArray( "value", oneToOne.getMapsId() ) ); } @@ -71,14 +70,4 @@ class OneToOneMocker extends PropertyMocker { create( ID ); } } - - @Override - protected JaxbAccessType getAccessType() { - return oneToOne.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - oneToOne.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMocker.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMocker.java index 02820e5c98..65db372dc8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMocker.java @@ -1,17 +1,17 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.HashMap; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitDefaults; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; +import org.hibernate.jaxb.spi.orm.JaxbPersistenceUnitDefaults; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; + /** * @author Strong Liu */ @@ -49,12 +49,12 @@ class PersistenceMetadataMocker extends AbstractMocker { * NOTE: These mocked annotations do not have {@link AnnotationTarget target}. */ final void process() { - parserAccessType( persistenceUnitDefaults.getAccess(), null ); + parseAccessType( persistenceUnitDefaults.getAccess(), null ); if ( persistenceUnitDefaults.getDelimitedIdentifiers() != null ) { create( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS, null ); } if ( persistenceUnitDefaults.getEntityListeners() != null ) { - new DefaultListenerMocker( indexBuilder, null ).parser( persistenceUnitDefaults.getEntityListeners() ); + new DefaultListenerMocker( indexBuilder, null ).parse( persistenceUnitDefaults.getEntityListeners() ); } indexBuilder.finishGlobalConfigurationMocking( globalAnnotations ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyElement.java new file mode 100644 index 0000000000..b3a596b9a7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyElement.java @@ -0,0 +1,14 @@ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import org.hibernate.jaxb.spi.orm.JaxbAccessType; + +/** + * @author Strong Liu + */ +public interface PropertyElement { + String getName(); + + JaxbAccessType getAccess(); + + void setAccess(JaxbAccessType accessType); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyMocker.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyMocker.java index dccdbbeb11..7455fb2de1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PropertyMocker.java @@ -21,26 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; -import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEnumType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKey; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTemporalType; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; +import org.hibernate.HibernateException; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbEnumType; +import org.hibernate.jaxb.spi.orm.JaxbMapKey; +import org.hibernate.jaxb.spi.orm.JaxbMapKeyClass; +import org.hibernate.jaxb.spi.orm.JaxbMapKeyColumn; +import org.hibernate.jaxb.spi.orm.JaxbMapKeyJoinColumn; +import org.hibernate.jaxb.spi.orm.JaxbTemporalType; + /** * @author Strong Liu */ @@ -52,15 +53,9 @@ abstract class PropertyMocker extends AnnotationMocker { super( indexBuilder, defaults ); this.classInfo = classInfo; } - + protected abstract PropertyElement getPropertyElement(); protected abstract void processExtra(); - protected abstract String getFieldName(); - - protected abstract JaxbAccessType getAccessType(); - - protected abstract void setAccessType(JaxbAccessType accessType); - @Override protected DotName getTargetName() { return classInfo.name(); @@ -68,10 +63,10 @@ abstract class PropertyMocker extends AnnotationMocker { protected void resolveTarget() { //attribute in orm.xml has access sub-element - JaxbAccessType accessType = getAccessType(); + JaxbAccessType accessType = getPropertyElement().getAccess(); if ( accessType == null ) { //attribute in the entity class has @Access - accessType = AccessHelper.getAccessFromAttributeAnnotation( getTargetName(), getFieldName(), indexBuilder ); + accessType = AccessHelper.getAccessFromAttributeAnnotation( getTargetName(), getPropertyElement().getName(), indexBuilder ); if ( accessType == null ) { accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); } @@ -86,7 +81,7 @@ abstract class PropertyMocker extends AnnotationMocker { accessType = JaxbAccessType.PROPERTY; } - setAccessType( accessType ); + getPropertyElement().setAccess( accessType ); } } @@ -94,7 +89,7 @@ abstract class PropertyMocker extends AnnotationMocker { @Override protected AnnotationTarget getTarget() { if ( target == null ) { - target = getTargetFromAttributeAccessType( getAccessType() ); + target = getTargetFromAttributeAccessType( getPropertyElement().getAccess() ); } return target; } @@ -108,14 +103,14 @@ abstract class PropertyMocker extends AnnotationMocker { return MockHelper.getTarget( indexBuilder.getServiceRegistry(), classInfo, - getFieldName(), + getPropertyElement().getName(), MockHelper.TargetType.FIELD ); case PROPERTY: return MockHelper.getTarget( indexBuilder.getServiceRegistry(), classInfo, - getFieldName(), + getPropertyElement().getName(), MockHelper.TargetType.PROPERTY ); default: @@ -130,7 +125,7 @@ abstract class PropertyMocker extends AnnotationMocker { processExtra(); } - protected AnnotationInstance parserMapKeyColumn(JaxbMapKeyColumn mapKeyColumn, AnnotationTarget target) { + protected AnnotationInstance parseMapKeyColumn(JaxbMapKeyColumn mapKeyColumn, AnnotationTarget target) { if ( mapKeyColumn == null ) { return null; } @@ -148,7 +143,7 @@ abstract class PropertyMocker extends AnnotationMocker { return create( MAP_KEY_COLUMN, target, annotationValueList ); } - protected AnnotationInstance parserMapKeyClass(JaxbMapKeyClass mapKeyClass, AnnotationTarget target) { + protected AnnotationInstance parseMapKeyClass(JaxbMapKeyClass mapKeyClass, AnnotationTarget target) { if ( mapKeyClass == null ) { return null; } @@ -159,7 +154,7 @@ abstract class PropertyMocker extends AnnotationMocker { ); } - protected AnnotationInstance parserMapKeyTemporal(JaxbTemporalType temporalType, AnnotationTarget target) { + protected AnnotationInstance parseMapKeyTemporal(JaxbTemporalType temporalType, AnnotationTarget target) { if ( temporalType == null ) { return null; } @@ -169,7 +164,7 @@ abstract class PropertyMocker extends AnnotationMocker { ); } - protected AnnotationInstance parserMapKeyEnumerated(JaxbEnumType enumType, AnnotationTarget target) { + protected AnnotationInstance parseMapKeyEnumerated(JaxbEnumType enumType, AnnotationTarget target) { if ( enumType == null ) { return null; } @@ -179,7 +174,7 @@ abstract class PropertyMocker extends AnnotationMocker { ); } - protected AnnotationInstance parserMapKey(JaxbMapKey mapKey, AnnotationTarget target) { + protected AnnotationInstance parseMapKey(JaxbMapKey mapKey, AnnotationTarget target) { if ( mapKey == null ) { return null; } @@ -187,10 +182,10 @@ abstract class PropertyMocker extends AnnotationMocker { } private AnnotationValue[] nestedMapKeyJoinColumnList(String name, List columns, List annotationValueList) { - if ( MockHelper.isNotEmpty( columns ) ) { + if ( CollectionHelper.isNotEmpty( columns ) ) { AnnotationValue[] values = new AnnotationValue[columns.size()]; for ( int i = 0; i < columns.size(); i++ ) { - AnnotationInstance annotationInstance = parserMapKeyJoinColumn( columns.get( i ), null ); + AnnotationInstance annotationInstance = parseMapKeyJoinColumn( columns.get( i ), null ); values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); @@ -203,10 +198,10 @@ abstract class PropertyMocker extends AnnotationMocker { return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; } - protected AnnotationInstance parserMapKeyJoinColumnList(List joinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( joinColumnList ) ) { + protected AnnotationInstance parseMapKeyJoinColumnList(List joinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( joinColumnList ) ) { if ( joinColumnList.size() == 1 ) { - return parserMapKeyJoinColumn( joinColumnList.get( 0 ), target ); + return parseMapKeyJoinColumn( joinColumnList.get( 0 ), target ); } else { AnnotationValue[] values = nestedMapKeyJoinColumnList( "value", joinColumnList, null ); @@ -222,7 +217,7 @@ abstract class PropertyMocker extends AnnotationMocker { } //@MapKeyJoinColumn - private AnnotationInstance parserMapKeyJoinColumn(JaxbMapKeyJoinColumn column, AnnotationTarget target) { + private AnnotationInstance parseMapKeyJoinColumn(JaxbMapKeyJoinColumn column, AnnotationTarget target) { if ( column == null ) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/SchemaAware.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/SchemaAware.java index cba0da7996..6b3be43835 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/SchemaAware.java @@ -4,7 +4,7 @@ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. + * distributed under license by Red Hat Inc.. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -21,13 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; /** - * @author Steve Ebersole + * @author Strong Liu */ -public interface Sortable { - public boolean isSorted(); - public String getComparatorName(); +public interface SchemaAware { + String getSchema(); + void setSchema(String schema); + + String getCatalog(); + + void setCatalog(String catalog); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/TransientMocker.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/TransientMocker.java index 7154dcff64..06f8d1badd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/TransientMocker.java @@ -21,22 +21,38 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbAccessType; +import org.hibernate.jaxb.spi.orm.JaxbTransient; + /** * @author Strong Liu */ class TransientMocker extends PropertyMocker { - private JaxbTransient transientObj; + private final JaxbTransient transientObj; + private final PropertyElement wrapper; - TransientMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbTransient transientObj) { + TransientMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, final JaxbTransient transientObj) { super( indexBuilder, classInfo, defaults ); this.transientObj = transientObj; + this.wrapper = new PropertyElement() { + @Override + public String getName() { + return transientObj.getName(); + } + + @Override + public JaxbAccessType getAccess() { + return JaxbAccessType.FIELD; + } + + @Override + public void setAccess(JaxbAccessType accessType) { + } + }; } @Override @@ -45,17 +61,7 @@ class TransientMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return transientObj.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return JaxbAccessType.FIELD; - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - //ignore + protected PropertyElement getPropertyElement() { + return wrapper; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/VersionMocker.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/VersionMocker.java index d54c94168e..b204da80b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/VersionMocker.java @@ -21,18 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.ClassInfo; +import org.hibernate.jaxb.spi.orm.JaxbVersion; + /** * @author Strong Liu */ class VersionMocker extends PropertyMocker { - private JaxbVersion version; + private final JaxbVersion version; VersionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbVersion version) { super( indexBuilder, classInfo, defaults ); @@ -40,24 +39,13 @@ class VersionMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return version.getName(); + protected PropertyElement getPropertyElement() { + return version; } - @Override protected void processExtra() { create( VERSION ); - parserColumn( version.getColumn(), getTarget() ); - parserTemporalType( version.getTemporal(), getTarget() ); - } - - @Override - protected JaxbAccessType getAccessType() { - return version.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - version.setAccess( accessType ); + parseColumn( version.getColumn(), getTarget() ); + parseTemporalType( version.getTemporal(), getTarget() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractComponentAttributeSourceImpl.java new file mode 100644 index 0000000000..8352e7e16b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractComponentAttributeSourceImpl.java @@ -0,0 +1,254 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; + +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.ComponentSourceElement; +import org.hibernate.jaxb.spi.hbm.JaxbAnyElement; +import org.hibernate.jaxb.spi.hbm.JaxbArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbBagElement; +import org.hibernate.jaxb.spi.hbm.JaxbComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbDynamicComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbListElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToManyElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbMapElement; +import org.hibernate.jaxb.spi.hbm.JaxbOneToManyElement; +import org.hibernate.jaxb.spi.hbm.JaxbOneToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbSetElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractComponentAttributeSourceImpl extends AbstractHbmSourceNode implements ComponentAttributeSource { + private final ComponentSourceElement componentSourceElement; + private final AttributeSourceContainer parentContainer; + private final List subAttributeSources; + private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + private final ValueHolder> componentClassReference; + private final String logicalTableName; + private final String path; + + protected AbstractComponentAttributeSourceImpl( + MappingDocument sourceMappingDocument, + ComponentSourceElement componentSourceElement, + AttributeSourceContainer parentContainer, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument ); + this.componentSourceElement = componentSourceElement; + this.parentContainer = parentContainer; + this.naturalIdMutability = naturalIdMutability; + this.componentClassReference = makeClassReference( componentSourceElement.getClazz() ); + this.logicalTableName = logicalTableName; + this.path = parentContainer.getPath() + '.' + componentSourceElement.getName(); + + this.subAttributeSources = buildAttributeSources(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + protected abstract List buildAttributeSources(); + protected SingularAttributeSource buildAttributeSource(JaxbPropertyElement attributeElement) { + return new PropertyAttributeSourceImpl( + sourceMappingDocument(), + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbComponentElement attributeElement) { + return new ComponentAttributeSourceImpl( + sourceMappingDocument(), + attributeElement, + this, + logicalTableName, + naturalIdMutability + ); + } + protected AttributeSource buildAttributeSource(JaxbDynamicComponentElement attributeElement){ + // todo : implement + throw new NotYetImplementedException(); + } + protected AttributeSource buildAttributeSource(JaxbManyToOneElement attributeElement) { + return new ManyToOneAttributeSourceImpl( + sourceMappingDocument(), + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbOneToOneElement attributeElement) { + return new OneToOneAttributeSourceImpl( + sourceMappingDocument(), + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbAnyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbOneToManyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbManyToManyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + // todo duplicated with org.hibernate.metamodel.internal.source.hbm.AbstractEntitySourceImpl + protected AttributeSource buildAttributeSource(JaxbMapElement attributeElement){ + return new MapSourceImpl( + sourceMappingDocument(), + attributeElement, + parentContainer + ); + } + protected AttributeSource buildAttributeSource(JaxbSetElement attributeElement) { + return new SetSourceImpl( + sourceMappingDocument(), + attributeElement, + parentContainer + ); + } + protected AttributeSource buildAttributeSource(JaxbListElement attributeElement) { + return new ListSourceImpl( + sourceMappingDocument(), + attributeElement, + parentContainer + ); + } + protected AttributeSource buildAttributeSource(JaxbBagElement attributeElement) { + return new BagSourceImpl( + sourceMappingDocument(), + attributeElement, + parentContainer + ); + } + protected AttributeSource buildAttributeSource(JaxbArrayElement attributeElement) { + return new ArraySourceImpl( + sourceMappingDocument(), + attributeElement, + parentContainer + ); + } + protected AttributeSource buildAttributeSource(JaxbPrimitiveArrayElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + + protected ComponentSourceElement componentSourceElement() { + return componentSourceElement; + } + + @Override + public String getClassName() { + return componentSourceElement.getClazz(); + } + + @Override + public ValueHolder> getClassReference() { + return componentClassReference; + } + + @Override + public String getPath() { + return path; + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return parentContainer.getLocalBindingContext(); + } + + @Override + public List attributeSources() { + return subAttributeSources; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public Nature getNature() { + return Nature.COMPOSITE; + } + + @Override + public HibernateTypeSource getTypeInformation() { + // does not support type information. + return null; + } + + @Override + public String getName() { + return componentSourceElement.getName(); + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public String getPropertyAccessorName() { + return componentSourceElement.getAccess(); + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public Iterable getMetaAttributeSources() { + return componentSourceElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractConstraintSource.java similarity index 50% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractConstraintSource.java index 716a483e3c..95a0923b44 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractConstraintSource.java @@ -21,41 +21,51 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.metamodel.source.binder.TableSource; +import java.util.ArrayList; +import java.util.List; -class TableSourceImpl implements TableSource { - private final String schema; - private final String catalog; - private final String tableName; - private final String logicalName; +import org.hibernate.metamodel.spi.source.ConstraintSource; - TableSourceImpl(String schema, String catalog, String tableName, String logicalName) { - this.schema = schema; - this.catalog = catalog; +/** + * @author Hardy Ferentschik + */ +class AbstractConstraintSource implements ConstraintSource { + protected final String name; + protected final String tableName; + protected final List columnNames = new ArrayList(); + protected final List orderings = new ArrayList(); + + protected AbstractConstraintSource(String name, String tableName) { + this.name = name; this.tableName = tableName; - this.logicalName = logicalName; } @Override - public String getExplicitSchemaName() { - return schema; + public String name() { + return name; } @Override - public String getExplicitCatalogName() { - return catalog; - } - - @Override - public String getExplicitTableName() { + public String getTableName() { return tableName; } @Override - public String getLogicalName() { - return logicalName; + public List columnNames() { + return columnNames; + } + + public void addColumnName( String columnName ) { + columnNames.add( columnName ); + // TODO: Can HBM have orderings? For now, just add a null -- Binder expects columnNames and + // orderings to be the same size. Find a better data representation... + orderings.add( null ); + } + + public List orderings() { + return orderings; } @Override @@ -67,15 +77,15 @@ class TableSourceImpl implements TableSource { return false; } - TableSourceImpl that = (TableSourceImpl) o; + AbstractConstraintSource that = (AbstractConstraintSource) o; - if ( catalog != null ? !catalog.equals( that.catalog ) : that.catalog != null ) { + if ( columnNames != null ? !columnNames.equals( that.columnNames ) : that.columnNames != null ) { return false; } - if ( logicalName != null ? !logicalName.equals( that.logicalName ) : that.logicalName != null ) { + if ( orderings != null ? !orderings.equals( that.orderings ) : that.orderings != null ) { return false; } - if ( schema != null ? !schema.equals( that.schema ) : that.schema != null ) { + if ( name != null ? !name.equals( that.name ) : that.name != null ) { return false; } if ( tableName != null ? !tableName.equals( that.tableName ) : that.tableName != null ) { @@ -87,24 +97,12 @@ class TableSourceImpl implements TableSource { @Override public int hashCode() { - int result = schema != null ? schema.hashCode() : 0; - result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); + int result = name != null ? name.hashCode() : 0; result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); - result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); + result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 ); + result = 31 * result + ( orderings != null ? orderings.hashCode() : 0 ); return result; } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "TableSourceImpl" ); - sb.append( "{schema='" ).append( schema ).append( '\'' ); - sb.append( ", catalog='" ).append( catalog ).append( '\'' ); - sb.append( ", tableName='" ).append( tableName ).append( '\'' ); - sb.append( ", logicalName='" ).append( logicalName ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractEntitySourceImpl.java new file mode 100644 index 0000000000..5540f16184 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractEntitySourceImpl.java @@ -0,0 +1,596 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.EntityMode; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbAnyElement; +import org.hibernate.jaxb.spi.hbm.JaxbArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbBagElement; +import org.hibernate.jaxb.spi.hbm.JaxbClassElement; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbDynamicComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbFilterElement; +import org.hibernate.jaxb.spi.hbm.JaxbIdbagElement; +import org.hibernate.jaxb.spi.hbm.JaxbJoinElement; +import org.hibernate.jaxb.spi.hbm.JaxbListElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbMapElement; +import org.hibernate.jaxb.spi.hbm.JaxbOneToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbSetElement; +import org.hibernate.jaxb.spi.hbm.JaxbTuplizerElement; +import org.hibernate.jaxb.spi.hbm.JoinElementSource; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.ConstraintSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.SecondaryTableSource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public abstract class AbstractEntitySourceImpl + extends AbstractHbmSourceNode + implements EntitySource, Helper.InLineViewNameInferrer { + + private final EntityElement entityElement; + private final String className; + private final String entityName; + private final String jpaEntityName; + + private List subclassEntitySources = new ArrayList(); + + private int inLineViewCount = 0; + + // logically final, but built during 'afterInstantiation' callback + private List attributeSources; + private Set secondaryTableSources; + private final FilterSource[] filterSources; + + private Map constraintMap = new HashMap(); + + protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { + super( sourceMappingDocument ); + this.entityElement = entityElement; + + this.className = bindingContext().qualifyClassName( entityElement.getName() ); + if ( StringHelper.isNotEmpty( entityElement.getEntityName() ) ) { + this.entityName = entityElement.getEntityName(); + this.jpaEntityName = entityElement.getEntityName(); + } + else { + this.entityName = className; + this.jpaEntityName = StringHelper.unqualify( className ); + } + this.filterSources = buildFilterSources(); + } + + private FilterSource[] buildFilterSources() { + //todo for now, i think all EntityElement should support this. + if ( JaxbClassElement.class.isInstance( entityElement() ) ) { + JaxbClassElement jaxbClassElement = JaxbClassElement.class.cast( entityElement() ); + final int size = jaxbClassElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = jaxbClassElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + } + else { + return null; + } + + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public String inferInLineViewName() { + return entityName + '#' + (++inLineViewCount); + } + + protected void afterInstantiation() { + this.attributeSources = buildAttributeSources(); + this.secondaryTableSources = buildSecondaryTables(); + } + + protected List buildAttributeSources() { + List attributeSources = new ArrayList(); + buildAttributeSources( attributeSources ); + return attributeSources; + } + + protected List buildAttributeSources(List attributeSources) { + return buildAttributeSources( entityElement, attributeSources, null, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID ); + } + protected List buildAttributeSources(EntityElement element, + List attributeSources, + String logicTalbeName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability){ + processPropertyAttributes( attributeSources, element.getProperty(), logicTalbeName, naturalIdMutability ); + processComponentAttributes( + attributeSources, + element.getComponent(), + logicTalbeName, + naturalIdMutability + ); + processDynamicComponentAttributes( + attributeSources, + element.getDynamicComponent(), + logicTalbeName, + naturalIdMutability + ); + processManyToOneAttributes( + attributeSources, + element.getManyToOne(), + logicTalbeName, + naturalIdMutability + ); + processOneToOneAttributes( + attributeSources, + element.getOneToOne(), + logicTalbeName, + naturalIdMutability + ); + processAnyAttributes( + attributeSources, + element.getAny(), + logicTalbeName, + naturalIdMutability + ); + processMapAttributes( attributeSources, element.getMap() ); + processListAttributes( attributeSources, element.getList() ); + processArrayAttributes( attributeSources, element.getArray() ); + processSetAttributes( attributeSources, element.getSet() ); + processIdBagAttributes( attributeSources, element.getIdbag() ); + processBagAttributes( attributeSources, element.getBag() ); + return attributeSources; + } + + protected void processPropertyAttributes(List results, + List propertyElements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + for ( JaxbPropertyElement element : propertyElements ) { + results.add( + new PropertyAttributeSourceImpl( + sourceMappingDocument(), + element, + logicalTableName, + naturalIdMutability + ) + ); + + // TODO: Not sure this is the right place to do this. Can index constraints be defined by anything other + // than just a property? Split off into its own process method? + for ( JaxbColumnElement column : element.getColumn() ) { + // An index constraint can happen on the column element or the surrounding property element. + if ( !StringHelper.isEmpty( column.getIndex() ) ) { + addColumnToIndexConstraint( column.getIndex(), logicalTableName, column.getName() ); + } + if ( !StringHelper.isEmpty( element.getIndex() ) ) { + addColumnToIndexConstraint( element.getIndex(), logicalTableName, column.getName() ); + } + } + } + } + + private void addColumnToIndexConstraint(String constraintName, String logicalTableName, String columnName) { + if ( !constraintMap.containsKey( constraintName ) ) { + constraintMap.put( constraintName, new IndexConstraintSourceImpl( constraintName, logicalTableName ) ); + } + ( (AbstractConstraintSource) constraintMap.get( constraintName ) ).addColumnName( columnName ); + } + + protected void processComponentAttributes(List results, + List elements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + for ( JaxbComponentElement element : elements ) { + results.add( + new ComponentAttributeSourceImpl( + sourceMappingDocument(), + element, + this, + logicalTableName, + naturalIdMutability + ) + ); + } + } + + protected void processDynamicComponentAttributes(List results, + List elements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + // todo : implement + } + + protected void processManyToOneAttributes(List results, + List elements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + for ( JaxbManyToOneElement element : elements ) { + results.add( + new ManyToOneAttributeSourceImpl( + sourceMappingDocument(), + element, + logicalTableName, + naturalIdMutability + ) + ); + } + } + protected void processOneToOneAttributes(List results, + List elements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + for ( JaxbOneToOneElement element : elements ) { + results.add( + new OneToOneAttributeSourceImpl( + sourceMappingDocument(), + element, + logicalTableName, + naturalIdMutability + ) + ); + } + } + + protected void processAnyAttributes(List results, + List elements, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + // todo : implement + } + + protected void processMapAttributes(List results, + List propertyElements){ + for ( JaxbMapElement element : propertyElements ) { + results.add( + new MapSourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processArrayAttributes(List results, + List propertyElements){ + for ( JaxbArrayElement element : propertyElements ) { + results.add( + new ArraySourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processListAttributes(List results, + List propertyElements){ + for ( JaxbListElement element : propertyElements ) { + results.add( + new ListSourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processSetAttributes(List results, + List propertyElements){ + for ( JaxbSetElement element : propertyElements ) { + results.add( + new SetSourceImpl( + sourceMappingDocument(), + element, + this + ) + ); + } + } + protected void processIdBagAttributes(List results, + List propertyElements){ + + if ( !propertyElements.isEmpty() ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + } + protected void processBagAttributes(List results, + List propertyElements) { + for ( JaxbBagElement element : propertyElements ) { + results.add( + new BagSourceImpl( + sourceMappingDocument(), + element, + this + ) + ); + } + } + + + private Set buildSecondaryTables() { + if ( ! JoinElementSource.class.isInstance( entityElement ) ) { + return Collections.emptySet(); + } + + final Set secondaryTableSources = new HashSet(); + for ( JaxbJoinElement joinElement : ( (JoinElementSource) entityElement ).getJoin() ) { + final SecondaryTableSourceImpl secondaryTableSource = new SecondaryTableSourceImpl( + sourceMappingDocument(), + joinElement, + this + ); + secondaryTableSources.add( secondaryTableSource ); + + final String logicalTableName = secondaryTableSource.getLogicalTableNameForContainedColumns(); + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + processAnyAttributes( + attributeSources, + joinElement.getAny(), + logicalTableName, + naturalIdMutability + ); + processComponentAttributes( + attributeSources, + joinElement.getComponent(), + logicalTableName, + naturalIdMutability + ); + processDynamicComponentAttributes( + attributeSources, + joinElement.getDynamicComponent(), + logicalTableName, + naturalIdMutability + ); + processManyToOneAttributes( + attributeSources, + joinElement.getManyToOne(), + logicalTableName, + naturalIdMutability + ); + processPropertyAttributes( + attributeSources, + joinElement.getProperty(), + logicalTableName, + naturalIdMutability + ); + } + return secondaryTableSources; + } + + protected EntityElement entityElement() { + return entityElement; + } + + @Override + public Origin getOrigin() { + return origin(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return bindingContext(); + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getClassName() { + return className; + } + + @Override + public String getJpaEntityName() { + return jpaEntityName; + } + + @Override + public boolean isAbstract() { + return entityElement().isAbstract(); + } + + @Override + public boolean isLazy() { + if(entityElement.isLazy()==null){ + return getLocalBindingContext().getMappingDefaults().areAssociationsLazy(); + } + return entityElement().isLazy(); + } + + @Override + public String getProxy() { + return entityElement.getProxy(); + } + + @Override + public int getBatchSize() { + return entityElement.getBatchSize(); + } + + @Override + public boolean isDynamicInsert() { + return entityElement.isDynamicInsert(); + } + + @Override + public boolean isDynamicUpdate() { + return entityElement.isDynamicUpdate(); + } + + @Override + public boolean isSelectBeforeUpdate() { + return entityElement.isSelectBeforeUpdate(); + } + + protected EntityMode determineEntityMode() { + return StringHelper.isNotEmpty( getClassName() ) ? EntityMode.POJO : EntityMode.MAP; + } + + @Override + public String getCustomTuplizerClassName() { + if ( entityElement.getTuplizer() == null ) { + return null; + } + final EntityMode entityMode = determineEntityMode(); + for ( JaxbTuplizerElement tuplizerElement : entityElement.getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public String getCustomPersisterClassName() { + return getLocalBindingContext().qualifyClassName( entityElement.getPersister() ); + } + + @Override + public String getCustomLoaderName() { + return entityElement.getLoader() != null ? entityElement.getLoader().getQueryRef() : null; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return Helper.buildCustomSql( entityElement.getSqlInsert() ); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return Helper.buildCustomSql( entityElement.getSqlUpdate() ); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return Helper.buildCustomSql( entityElement.getSqlDelete() ); + } + + @Override + public String[] getSynchronizedTableNames() { + if ( CollectionHelper.isEmpty( entityElement.getSynchronize() ) ) { + return StringHelper.EMPTY_STRINGS; + } + else { + final int size = entityElement.getSynchronize().size(); + final String[] synchronizedTableNames = new String[size]; + for ( int i = 0; i < size; i++ ) { + synchronizedTableNames[i] = entityElement.getSynchronize().get( i ).getTable(); + } + return synchronizedTableNames; + } + } + + @Override + public Iterable getMetaAttributeSources() { + return entityElement.getMeta(); + } + + @Override + public String getPath() { + return ""; + } + + @Override + public List attributeSources() { + return attributeSources; + } + + private EntityHierarchyImpl entityHierarchy; + + public void injectHierarchy(EntityHierarchyImpl entityHierarchy) { + this.entityHierarchy = entityHierarchy; + } + + @Override + public void add(SubclassEntitySource subclassEntitySource) { + add( (SubclassEntitySourceImpl) subclassEntitySource ); + } + + public void add(SubclassEntitySourceImpl subclassEntitySource) { + subclassEntitySource.injectHierarchy( entityHierarchy ); + entityHierarchy.processSubclass( subclassEntitySource ); + subclassEntitySources.add( subclassEntitySource ); + } + + @Override + public Iterable subclassEntitySources() { + return subclassEntitySources; + } + + @Override + public String getDiscriminatorMatchValue() { + return null; + } + + @Override + public Iterable getConstraints() { + return constraintMap.values(); + } + + @Override + public Set getSecondaryTables() { + return secondaryTableSources; + } + + @Override + @SuppressWarnings( {"unchecked"}) + public List getJpaCallbackClasses() { + return Collections.EMPTY_LIST; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractHbmSourceNode.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractHbmSourceNode.java new file mode 100644 index 0000000000..4d559cb14d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractHbmSourceNode.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.spi.source.MappingException; + +/** + * Base class for any and all source objects coming from {@code hbm.xml} parsing. Defines standard access + * back to the {@link MappingDocument} object and the services it provides (namely access to + * {@link HbmBindingContext}). + * + * @author Steve Ebersole + */ +public abstract class AbstractHbmSourceNode { + private final MappingDocument sourceMappingDocument; + + protected AbstractHbmSourceNode(MappingDocument sourceMappingDocument) { + this.sourceMappingDocument = sourceMappingDocument; + } + + protected MappingDocument sourceMappingDocument() { + return sourceMappingDocument; + } + + protected HbmBindingContext bindingContext() { + return sourceMappingDocument().getMappingLocalBindingContext(); + } + + protected Origin origin() { + return sourceMappingDocument().getOrigin(); + } + + protected JaxbRoot mappingRoot() { + return sourceMappingDocument().getJaxbRoot(); + } + + protected ValueHolder> makeClassReference(String className) { + return bindingContext().makeClassReference( bindingContext().qualifyClassName( className ) ); + } + + protected MappingException makeMappingException(String message) { + return bindingContext().makeMappingException( message ); + } + + protected MappingException makeMappingException(String message, Exception cause) { + return bindingContext().makeMappingException( message, cause ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAssociationElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAssociationElementSourceImpl.java new file mode 100644 index 0000000000..82c377a0ec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAssociationElementSourceImpl.java @@ -0,0 +1,72 @@ +/** + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.metamodel.spi.source.AssociationSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; + +/** + + * @author Gail Badner + + */ +public abstract class AbstractPluralAssociationElementSourceImpl + extends AbstractHbmSourceNode implements AssociationSource { + + private final PluralAttributeSource pluralAttributeSource; + private final Set ownedAssociationSources = new HashSet( ); + + public AbstractPluralAssociationElementSourceImpl( + MappingDocument mappingDocument, + PluralAttributeSource pluralAttributeSource) { + super( mappingDocument ); + this.pluralAttributeSource = pluralAttributeSource; + } + + @Override + public AttributeSource getAttributeSource() { + return pluralAttributeSource; + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAttributeSourceImpl.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAttributeSourceImpl.java index c39dfc0833..e6543fcc17 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractPluralAttributeSourceImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,53 +21,71 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.Collections; import java.util.Map; -import org.hibernate.FetchMode; -import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.AssertionFailure; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement; -import org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeKeySource; -import org.hibernate.metamodel.source.binder.PluralAttributeSource; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbFilterElement; +import org.hibernate.jaxb.spi.hbm.PluralAttributeElement; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; /** * @author Steve Ebersole + * @author Brett Meyer */ -public abstract class AbstractPluralAttributeSourceImpl implements PluralAttributeSource { +public abstract class AbstractPluralAttributeSourceImpl + extends AbstractHbmSourceNode + implements PluralAttributeSource, Helper.InLineViewNameInferrer { private final PluralAttributeElement pluralAttributeElement; private final AttributeSourceContainer container; - private final ExplicitHibernateTypeSource typeInformation; + private final HibernateTypeSource typeInformation; private final PluralAttributeKeySource keySource; private final PluralAttributeElementSource elementSource; + private final Caching caching; + private final FilterSource[] filterSources; + private ValueHolder> elementClassReference; protected AbstractPluralAttributeSourceImpl( + MappingDocument sourceMappingDocument, final PluralAttributeElement pluralAttributeElement, AttributeSourceContainer container) { + super( sourceMappingDocument ); this.pluralAttributeElement = pluralAttributeElement; this.container = container; - this.keySource = new PluralAttributeKeySourceImpl( pluralAttributeElement.getKey(), container ); + this.keySource = new PluralAttributeKeySourceImpl( + sourceMappingDocument(), + pluralAttributeElement.getKey(), + container + ); this.elementSource = interpretElementType(); - this.typeInformation = new ExplicitHibernateTypeSource() { + this.caching = Helper.createCaching( + pluralAttributeElement.getCache(), + StringHelper.qualify( container().getPath(), getName() ) + ); + + this.typeInformation = new HibernateTypeSource() { @Override public String getName() { return pluralAttributeElement.getCollectionType(); @@ -77,33 +95,72 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu public Map getParameters() { return Collections.emptyMap(); } + @Override + public Class getJavaType() { + return null; + } }; + this.filterSources = buildFilterSources(); + } + + private FilterSource[] buildFilterSources() { + final int size = pluralAttributeElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = pluralAttributeElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + } private PluralAttributeElementSource interpretElementType() { if ( pluralAttributeElement.getElement() != null ) { + // TODO: Is elementClassReference even needed in this context? + // If so, getType is currently null. +// elementClassReference = makeClassReference(pluralAttributeElement +// .getElement().getType().getName()); return new BasicPluralAttributeElementSourceImpl( - pluralAttributeElement.getElement(), container.getLocalBindingContext() + sourceMappingDocument(), + pluralAttributeElement.getElement() ); } else if ( pluralAttributeElement.getCompositeElement() != null ) { + elementClassReference = makeClassReference(pluralAttributeElement + .getCompositeElement().getClazz()); return new CompositePluralAttributeElementSourceImpl( - pluralAttributeElement.getCompositeElement(), container.getLocalBindingContext() + sourceMappingDocument(), + pluralAttributeElement.getCompositeElement(), + pluralAttributeElement.getCascade() ); } else if ( pluralAttributeElement.getOneToMany() != null ) { + elementClassReference = makeClassReference(pluralAttributeElement + .getOneToMany().getClazz()); return new OneToManyPluralAttributeElementSourceImpl( - pluralAttributeElement.getOneToMany(), container.getLocalBindingContext() + sourceMappingDocument(), + this, + pluralAttributeElement.getOneToMany(), + pluralAttributeElement.getCascade() ); } else if ( pluralAttributeElement.getManyToMany() != null ) { + elementClassReference = makeClassReference(pluralAttributeElement + .getManyToMany().getClazz()); return new ManyToManyPluralAttributeElementSourceImpl( - pluralAttributeElement.getManyToMany(), container.getLocalBindingContext() + sourceMappingDocument(), + this, + pluralAttributeElement.getManyToMany(), + pluralAttributeElement.getCascade() ); } else if ( pluralAttributeElement.getManyToAny() != null ) { throw new NotYetImplementedException( "Support for many-to-any not yet implemented" ); -// return PluralAttributeElementNature.MANY_TO_ANY; +// return Nature.MANY_TO_ANY; } else { throw new MappingException( @@ -113,6 +170,35 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu } } + @Override + public PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context) { + // elementSource is already resolved; nothing to do. + return elementSource; + } + + @Override + public boolean usesJoinTable() { + switch ( elementSource.getNature() ) { + case BASIC: + case AGGREGATE: + case ONE_TO_MANY: + return false; + case MANY_TO_MANY: + return true; + case MANY_TO_ANY: + throw new NotYetImplementedException( + String.format( "%s is not implemented yet.", elementSource.getNature() ) + ); + default: + throw new AssertionFailure( + String.format( + "Unexpected plural attribute element source nature: %s", + elementSource.getNature() + ) + ); + } + } + public PluralAttributeElement getPluralAttributeElement() { return pluralAttributeElement; } @@ -121,8 +207,9 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu return container; } - protected LocalBindingContext bindingContext() { - return container().getLocalBindingContext(); + @Override + public FilterSource[] getFilterSources() { + return filterSources; } @Override @@ -136,18 +223,35 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu } @Override - public String getExplicitSchemaName() { - return pluralAttributeElement.getSchema(); + public ValueHolder> getElementClassReference() { + return elementClassReference; } @Override - public String getExplicitCatalogName() { - return pluralAttributeElement.getCatalog(); + public boolean isMutable() { + return pluralAttributeElement.isMutable(); } @Override - public String getExplicitCollectionTableName() { - return pluralAttributeElement.getTable(); + public int getBatchSize() { + return pluralAttributeElement.getBatchSize(); + } + + @Override + public String getMappedBy() { + return null; + } + + @Override + public String inferInLineViewName() { + return container().getPath() + "." + pluralAttributeElement.getName(); + } + + @Override + public TableSpecificationSource getCollectionTableSpecificationSource() { + return pluralAttributeElement.getOneToMany() == null ? + Helper.createTableSource( sourceMappingDocument(), pluralAttributeElement, this ) : + null; } @Override @@ -162,16 +266,7 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu @Override public Caching getCaching() { - final JaxbCacheElement cache = pluralAttributeElement.getCache(); - if ( cache == null ) { - return null; - } - final String region = cache.getRegion() != null - ? cache.getRegion() - : StringHelper.qualify( container().getPath(), getName() ); - final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); - final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); - return new Caching( region, accessType, cacheLazyProps ); + return caching; } @Override @@ -190,7 +285,7 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu } @Override - public ExplicitHibernateTypeSource getTypeInformation() { + public HibernateTypeSource getTypeInformation() { return typeInformation; } @@ -242,13 +337,8 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu } @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( pluralAttributeElement.getMeta() ); - } - - @Override - public Iterable getCascadeStyles() { - return Helper.interpretCascadeStyles( pluralAttributeElement.getCascade(), bindingContext() ); + public Iterable getMetaAttributeSources() { + return pluralAttributeElement.getMeta(); } @Override @@ -264,7 +354,7 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu : null; if ( lazySelection == null ) { - if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { + if ( "join".equals( fetchSelection ) && "true".equals( outerJoinSelection ) ) { return FetchTiming.IMMEDIATE; } else if ( "false".equals( outerJoinSelection ) ) { @@ -292,7 +382,7 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu lazySelection, pluralAttributeElement.getName() ), - bindingContext().getOrigin() + origin() ); } @@ -304,7 +394,7 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu final String outerJoinSelection = pluralAttributeElement.getOuterJoin() != null ? pluralAttributeElement.getOuterJoin().value() : null; - final int batchSize = Helper.getIntValue( pluralAttributeElement.getBatchSize(), -1 ); + final int batchSize = getBatchSize(); if ( fetchSelection == null ) { if ( outerJoinSelection == null ) { @@ -330,11 +420,4 @@ public abstract class AbstractPluralAttributeSourceImpl implements PluralAttribu } } } - - @Override - public FetchMode getFetchMode() { - return pluralAttributeElement.getFetch() == null - ? FetchMode.DEFAULT - : FetchMode.valueOf( pluralAttributeElement.getFetch().value() ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractReturnBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractReturnBinder.java new file mode 100644 index 0000000000..4a613128f0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractReturnBinder.java @@ -0,0 +1,135 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.hibernate.LockMode; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbReturnPropertyElement; +import org.hibernate.jaxb.spi.hbm.ReturnElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Strong Liu + */ +abstract class AbstractReturnBinder { + protected final MetadataImplementor metadata; + protected final T element; + protected final LocalBindingContext context; + protected final String alias; + protected final LockMode lockMode; + protected List returnPropertyElements; + + AbstractReturnBinder( + final T element, final int elementIndex, final LocalBindingContext context, + final MetadataImplementor metadata) { + this.context = context; + this.metadata = metadata; + this.element = element; + this.alias = getAlias( element, elementIndex ); + this.lockMode = Helper.interpretLockMode( element.getLockMode(), context ); + this.returnPropertyElements = element.getReturnProperty(); + } + + private static String getAlias(ReturnElement element, int elementCount) { + return StringHelper.isEmpty( element.getAlias() ) ? "alias_" + elementCount : element.getAlias(); + } + + abstract NativeSQLQueryReturn process(); + + protected void processReturnProperties(ReturnPropertiesCallback callback) { + for ( JaxbReturnPropertyElement propertyElement : returnPropertyElements ) { + callback.process( propertyElement ); + } + } + + static interface ReturnPropertiesCallback { + void process(JaxbReturnPropertyElement propertyElement); + } + + static class ReturnPropertiesCallbackImpl implements ReturnPropertiesCallback { + private final LocalBindingContext bindingContext; + private final String alias; + private final Map propertyResults; + + ReturnPropertiesCallbackImpl( + final String alias, final Map propertyResults, + final LocalBindingContext bindingContext) { + this.alias = alias; + this.bindingContext = bindingContext; + this.propertyResults = propertyResults; + } + + @Override + public void process(final JaxbReturnPropertyElement propertyElement) { + final String name = propertyElement.getName(); + if ( StringHelper.isEmpty( name ) ) { + throw bindingContext.makeMappingException( "Empty return property name on alias " + alias ); + } + if ( name.contains( "." ) ) { + throw bindingContext.makeMappingException( + "dotted notation in or not yet supported" + ); + } + if ( propertyResults.containsKey( name ) ) { + throw bindingContext.makeMappingException( + "duplicate return-property for property " + name + " on alias " + alias + ); + } + final List returnColumnNames = getResultColumns( propertyElement, bindingContext ); + + if ( returnColumnNames.isEmpty() ) { + throw bindingContext.makeMappingException( + "return-property for alias " + alias + " must specify at least one column or return-column name" + ); + } + + propertyResults.put( name, returnColumnNames.toArray( new String[returnColumnNames.size()] ) ); + } + + private static List getResultColumns( + final JaxbReturnPropertyElement propertyresult, final LocalBindingContext context) { + List allResultColumns = new ArrayList(); + if ( propertyresult.getColumn() != null ) { + String column = context.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( propertyresult.getColumn() ); + allResultColumns.add( column ); + } + for ( JaxbReturnPropertyElement.JaxbReturnColumn returnColumn : propertyresult.getReturnColumn() ) { + if ( returnColumn.getName() != null ) { + String column = context.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( returnColumn.getName() ); + + allResultColumns.add( column ); + } + } + return allResultColumns; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java new file mode 100644 index 0000000000..2f293dccc2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java @@ -0,0 +1,266 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MappedByAssociationSource; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.ToOneAttributeSource; + +/** + * @author Gail Badner + */ +public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOneAttributeSource{ + private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + private final String propertyRef; + private final Set ownedAssociationSources = new HashSet( ); + + AbstractToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + String propertyRef) { + super( sourceMappingDocument ); + this.naturalIdMutability = naturalIdMutability; + this.propertyRef = propertyRef; + + } + @Override + public HibernateTypeSource getTypeInformation() { + return Helper.TO_ONE_ATTRIBUTE_TYPE_SOURCE; + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.NEVER; + } + + @Override + public boolean isNotFoundAnException() { + return true; + } + + @Override + public boolean isLazy() { + return getFetchTiming() != FetchTiming.IMMEDIATE; + } + + protected abstract boolean requiresImmediateFetch(); + protected abstract String getFetchSelectionString(); + protected abstract String getLazySelectionString(); + protected abstract String getOuterJoinSelectionString(); + + @Override + public boolean isUnWrapProxy() { + final String lazySelection = getLazySelectionString(); + return lazySelection != null && lazySelection.equals( "no-proxy" ); + } + + @Override + public FetchTiming getFetchTiming() { + final String lazySelection = getLazySelectionString(); + + if ( lazySelection == null ) { + if ( requiresImmediateFetch() ) { + return FetchTiming.IMMEDIATE; + } + else if ( "join".equals( getFetchSelectionString() ) || "true".equals( getOuterJoinSelectionString() ) ) { + return FetchTiming.IMMEDIATE; + } + else if ( "false".equals( getOuterJoinSelectionString() ) ) { + return FetchTiming.DELAYED; + } + else { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchTiming.DELAYED + : FetchTiming.IMMEDIATE; + } + } + else if ( "extra".equals( lazySelection ) ) { + // TODO: don't think "extra" is valid here + return FetchTiming.EXTRA_LAZY; + } + else if ( "true".equals( lazySelection ) || "proxy".equals( lazySelection ) || "no-proxy".equals( lazySelection ) ) { + return FetchTiming.DELAYED; + } + else if ( "false".equals( lazySelection ) ) { + return FetchTiming.IMMEDIATE; + } + + throw new MappingException( + String.format( + "Unexpected lazy selection [%s] on '%s'", + lazySelection, + getName() + ), + origin() + ); + } + + @Override + public FetchStyle getFetchStyle() { + // todo : handle batch fetches? + + if ( getFetchSelectionString() == null ) { + if ( requiresImmediateFetch() ) { + return FetchStyle.JOIN; + } + else if ( getOuterJoinSelectionString() == null ) { + return FetchStyle.SELECT; + } + else { + if ( "auto".equals( getOuterJoinSelectionString() ) ) { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchStyle.SELECT + : FetchStyle.JOIN; + } + else { + return "true".equals( getOuterJoinSelectionString() ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + } + else { + return "join".equals( getFetchSelectionString() ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + + @Override + // TODO: change to return the default name for a single column + public List getDefaultNamingStrategies( + final String entityName, + final String tableName, + final AttributeBinding referencedAttributeBinding) { + if ( CompositeAttributeBinding.class.isInstance( referencedAttributeBinding ) ) { + CompositeAttributeBinding compositeAttributeBinding = CompositeAttributeBinding.class.cast( + referencedAttributeBinding + ); + List result = new ArrayList(); + for ( final AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) { + result.addAll( getDefaultNamingStrategies( entityName, tableName, attributeBinding ) ); + } + return result; + } + else { + List result = new ArrayList( 1 ); + result.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( getName() ); + } + } + ); + return result; + } + + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + // only applies to annotations + return false; + } + + @Override + public AttributeSource getAttributeSource() { + return this; + } + + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + // nothing to do + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return propertyRef == null + ? null + : new JoinColumnResolutionDelegateImpl( propertyRef ); + } + + public static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final String propertyRef; + + public JoinColumnResolutionDelegateImpl(String propertyRef) { + this.propertyRef = propertyRef; + } + + @Override + public String getReferencedAttributeName() { + return propertyRef; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( propertyRef ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( propertyRef ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ArraySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ArraySourceImpl.java new file mode 100644 index 0000000000..f564c51f92 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ArraySourceImpl.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.AssertionFailure; +import org.hibernate.jaxb.spi.hbm.JaxbArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.SequentialPluralAttributeIndexSource; + +/** + * @author Brett Meyer + */ +public class ArraySourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + + private final SequentialPluralAttributeIndexSource indexSource; + + public ArraySourceImpl( + MappingDocument sourceMappingDocument, + JaxbArrayElement arrayElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, arrayElement, container ); + JaxbListIndexElement listIndexElement = arrayElement.getListIndex(); + if ( listIndexElement == null ) { + this.indexSource = new SequentialPluralAttributeIndexSourceImpl( sourceMappingDocument(), arrayElement.getIndex() ); + } else { + this.indexSource = new SequentialPluralAttributeIndexSourceImpl( sourceMappingDocument(), listIndexElement ); + } + } + + @Override + public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context) { + if ( indexSource == null ) { + throw new AssertionFailure( "Array index source should have been resolved already." ); + } + return indexSource; + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbArrayElement getPluralAttributeElement() { + return ( JaxbArrayElement ) super.getPluralAttributeElement(); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.source.PluralAttributeSource#getNature() + */ + @Override + public Nature getNature() { + return Nature.ARRAY; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BagSourceImpl.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BagSourceImpl.java index 4c29db82ab..9f6ffd3608 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BagSourceImpl.java @@ -21,25 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbBagElement; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.Orderable; -import org.hibernate.metamodel.source.binder.PluralAttributeNature; +import org.hibernate.jaxb.spi.hbm.JaxbBagElement; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.Orderable; /** * @author Steve Ebersole */ -public class BagAttributeSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable { - public BagAttributeSourceImpl(JaxbBagElement bagElement, AttributeSourceContainer container) { - super( bagElement, container ); +public class BagSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable { + public BagSourceImpl( + MappingDocument sourceMappingDocument, + JaxbBagElement bagElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, bagElement, container ); } @Override - public PluralAttributeNature getPluralAttributeNature() { - return PluralAttributeNature.BAG; + public Nature getNature() { + return Nature.BAG; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java similarity index 54% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java index 355117b0c5..6a8a68682d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/BasicPluralAttributeElementSourceImpl.java @@ -21,64 +21,81 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbElementElement; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.BasicPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; -import org.hibernate.metamodel.source.binder.RelationalValueSource; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbElementElement; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SizeSource; /** * @author Steve Ebersole */ -public class BasicPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource { +public class BasicPluralAttributeElementSourceImpl + extends AbstractHbmSourceNode + implements BasicPluralAttributeElementSource { private final List valueSources; - private final ExplicitHibernateTypeSource typeSource; + private final HibernateTypeSource typeSource; public BasicPluralAttributeElementSourceImpl( - final JaxbElementElement elementElement, - LocalBindingContext bindingContext) { + MappingDocument sourceMappingDocument, + final JaxbElementElement elementElement) { + super( sourceMappingDocument ); this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - @Override public boolean isIncludedInInsertByDefault() { - return true; + return BasicPluralAttributeElementSourceImpl.this.areValuesIncludedInInsertByDefault(); } @Override public boolean isIncludedInUpdateByDefault() { - return true; + return BasicPluralAttributeElementSourceImpl.this.areValuesIncludedInUpdateByDefault(); } @Override public String getColumnAttribute() { - return elementElement.getColumn(); + return elementElement.getColumnAttribute(); } @Override public String getFormulaAttribute() { + return elementElement.getFormulaAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + elementElement.getLength(), + elementElement.getPrecision(), + elementElement.getScale() + ); + } + + @Override + public List getColumn() { + return elementElement.getColumn(); + } + + @Override + public List getFormula() { return elementElement.getFormula(); } @Override - public List getColumnOrFormulaElements() { - return elementElement.getColumnOrFormula(); + public boolean isForceNotNull() { + return elementElement.isNotNull(); } - }, - bindingContext + } ); - this.typeSource = new ExplicitHibernateTypeSource() { + this.typeSource = new HibernateTypeSource() { @Override public String getName() { if ( elementElement.getTypeAttribute() != null ) { @@ -98,21 +115,40 @@ public class BasicPluralAttributeElementSourceImpl implements BasicPluralAttribu ? Helper.extractParameters( elementElement.getType().getParam() ) : java.util.Collections.emptyMap(); } + @Override + public Class getJavaType() { + return null; + } }; } @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.BASIC; + public Nature getNature() { + return Nature.BASIC; } @Override - public List getValueSources() { + public List relationalValueSources() { return valueSources; } @Override - public ExplicitHibernateTypeSource getExplicitHibernateTypeSource() { + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public HibernateTypeSource getExplicitHibernateTypeSource() { return typeSource; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java index 664215c030..39c927bf19 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java @@ -21,50 +21,68 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.SizeSource; /** -* @author Steve Ebersole -*/ -class ColumnAttributeSourceImpl implements ColumnSource { + * Implementation of a {@link ColumnSource} when the column is declared as just the name via the column XML + * attribute. For example, {@code }. + * + * @author Steve Ebersole + */ +class ColumnAttributeSourceImpl + extends AbstractHbmSourceNode + implements ColumnSource { private final String tableName; private final String columnName; - private boolean includedInInsert; - private boolean includedInUpdate; - private boolean isForceNotNull; + private final SizeSource sizeSource; + private TruthValue includedInInsert; + private TruthValue includedInUpdate; + private TruthValue nullable; ColumnAttributeSourceImpl( + MappingDocument mappingDocument, String tableName, String columnName, - boolean includedInInsert, - boolean includedInUpdate) { - this(tableName, columnName, includedInInsert, includedInUpdate, false); + SizeSource sizeSource, + TruthValue includedInInsert, + TruthValue includedInUpdate) { + this( mappingDocument, tableName, columnName, sizeSource, includedInInsert, includedInUpdate, TruthValue.UNKNOWN ); } ColumnAttributeSourceImpl( + MappingDocument mappingDocument, String tableName, String columnName, - boolean includedInInsert, - boolean includedInUpdate, - boolean isForceNotNull) { + SizeSource sizeSource, + TruthValue includedInInsert, + TruthValue includedInUpdate, + TruthValue nullable) { + super( mappingDocument ); this.tableName = tableName; this.columnName = columnName; + this.sizeSource = sizeSource; this.includedInInsert = includedInInsert; this.includedInUpdate = includedInUpdate; - this.isForceNotNull = isForceNotNull; + this.nullable = nullable; } @Override - public boolean isIncludedInInsert() { + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public TruthValue isIncludedInInsert() { return includedInInsert; } @Override - public boolean isIncludedInUpdate() { + public TruthValue isIncludedInUpdate() { return includedInUpdate; } @@ -79,8 +97,8 @@ class ColumnAttributeSourceImpl implements ColumnSource { } @Override - public boolean isNullable() { - return !isForceNotNull; + public TruthValue isNullable() { + return nullable; } @Override @@ -94,13 +112,13 @@ class ColumnAttributeSourceImpl implements ColumnSource { } @Override - public Datatype getDatatype() { + public JdbcDataType getDatatype() { return null; } @Override - public Size getSize() { - return null; + public SizeSource getSizeSource() { + return sizeSource; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java index a5cb4737ec..7a08c004e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java @@ -21,52 +21,63 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; +import org.hibernate.TruthValue; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.SizeSource; /** * @author Steve Ebersole */ -class ColumnSourceImpl implements ColumnSource { +class ColumnSourceImpl + extends AbstractHbmSourceNode + implements ColumnSource { private final String tableName; private final JaxbColumnElement columnElement; - private boolean includedInInsert; - private boolean includedInUpdate; - private final boolean isForceNotNull; + private final TruthValue includedInInsert; + private final TruthValue includedInUpdate; + private final TruthValue nullable; ColumnSourceImpl( + MappingDocument mappingDocument, String tableName, JaxbColumnElement columnElement, - boolean isIncludedInInsert, - boolean isIncludedInUpdate) { - this(tableName, columnElement, isIncludedInInsert, isIncludedInUpdate, false); + TruthValue isIncludedInInsert, + TruthValue isIncludedInUpdate) { + this( mappingDocument, tableName, columnElement, isIncludedInInsert, isIncludedInUpdate, TruthValue.UNKNOWN ); } + ColumnSourceImpl( + MappingDocument mappingDocument, String tableName, JaxbColumnElement columnElement, - boolean isIncludedInInsert, - boolean isIncludedInUpdate, - boolean isForceNotNull) { + TruthValue isIncludedInInsert, + TruthValue isIncludedInUpdate, + TruthValue nullable) { + super( mappingDocument ); this.tableName = tableName; this.columnElement = columnElement; - this.isForceNotNull = isForceNotNull; - includedInInsert = isIncludedInInsert; - includedInUpdate = isIncludedInUpdate; + this.nullable = nullable; + this.includedInInsert = isIncludedInInsert; + this.includedInUpdate = isIncludedInUpdate; } + @Override + public Nature getNature() { + return Nature.COLUMN; + } + @Override public String getName() { return columnElement.getName(); } @Override - public boolean isNullable() { - if(isForceNotNull)return false; - return ! columnElement.isNotNull(); + public TruthValue isNullable() { + return nullable; } @Override @@ -80,18 +91,13 @@ class ColumnSourceImpl implements ColumnSource { } @Override - public Datatype getDatatype() { + public JdbcDataType getDatatype() { return null; } @Override - public Size getSize() { - return new Size( - Helper.getIntValue( columnElement.getPrecision(), -1 ), - Helper.getIntValue( columnElement.getScale(), -1 ), - Helper.getLongValue( columnElement.getLength(), -1 ), - Size.LobMultiplier.NONE - ); + public SizeSource getSizeSource() { + return new SizeSourceImpl( columnElement.getPrecision(), columnElement.getScale(), columnElement.getLength() ); } @Override @@ -106,7 +112,8 @@ class ColumnSourceImpl implements ColumnSource { @Override public boolean isUnique() { - return columnElement.isUnique(); + // TODO: should TruthValue be returned instead of boolean? + return columnElement.isUnique() != null && columnElement.isUnique().booleanValue(); } @Override @@ -120,12 +127,12 @@ class ColumnSourceImpl implements ColumnSource { } @Override - public boolean isIncludedInInsert() { + public TruthValue isIncludedInInsert() { return includedInInsert; } @Override - public boolean isIncludedInUpdate() { + public TruthValue isIncludedInUpdate() { return includedInUpdate; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ComponentAttributeSourceImpl.java new file mode 100644 index 0000000000..dbaea37a7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ComponentAttributeSourceImpl.java @@ -0,0 +1,164 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.EntityMode; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbAnyElement; +import org.hibernate.jaxb.spi.hbm.JaxbArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbBagElement; +import org.hibernate.jaxb.spi.hbm.JaxbComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbDynamicComponentElement; +import org.hibernate.jaxb.spi.hbm.JaxbListElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbMapElement; +import org.hibernate.jaxb.spi.hbm.JaxbOneToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.jaxb.spi.hbm.JaxbPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbSetElement; +import org.hibernate.jaxb.spi.hbm.JaxbTuplizerElement; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Steve Ebersole + */ +class ComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl { + public ComponentAttributeSourceImpl( + MappingDocument sourceMappingDocument, + JaxbComponentElement componentElement, + AttributeSourceContainer parentContainer, + String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument, componentElement, parentContainer, logicalTableName, naturalIdMutability ); + } + + protected JaxbComponentElement componentElement() { + return (JaxbComponentElement) super.componentSourceElement(); + } + + @Override + protected List buildAttributeSources() { + List attributeSources = new ArrayList(); + for(final JaxbPropertyElement element : componentElement().getProperty()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbManyToOneElement element : componentElement().getManyToOne()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbOneToOneElement element: componentElement().getOneToOne()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbComponentElement element: componentElement().getComponent()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbDynamicComponentElement element: componentElement().getDynamicComponent()){ + attributeSources.add( buildAttributeSource(element) ); + } + for(final JaxbAnyElement element: componentElement().getAny()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbMapElement element: componentElement().getMap()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbSetElement element: componentElement().getSet()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbListElement element: componentElement().getList()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbBagElement element: componentElement().getBag()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbArrayElement element: componentElement().getArray()){ + attributeSources.add( buildAttributeSource( element ) ); + } + for(final JaxbPrimitiveArrayElement element: componentElement().getPrimitiveArray()){ + attributeSources.add( buildAttributeSource( element ) ); + } + return attributeSources; + } + + @Override + public String getParentReferenceAttributeName() { + return componentElement().getParent() == null ? null : componentElement().getParent().getName(); + } + + @Override + public String getExplicitTuplizerClassName() { + if ( componentElement().getTuplizer() == null ) { + return null; + } + final EntityMode entityMode = StringHelper.isEmpty( componentElement().getClazz() ) ? EntityMode.MAP : EntityMode.POJO; + for ( JaxbTuplizerElement tuplizerElement : componentElement().getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public PropertyGeneration getGeneration() { + // todo : is this correct here? + return null; + } + + @Override + public boolean isLazy() { + return componentElement().isLazy(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return componentElement().isOptimisticLock(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return componentElement().isInsert(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return componentElement().isUpdate(); + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public List relationalValueSources() { + // none, they are defined on the simple sub-attributes + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..3ceadfad95 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeElementSourceImpl.java @@ -0,0 +1,186 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.hibernate.EntityMode; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbAnyElement; +import org.hibernate.jaxb.spi.hbm.JaxbCompositeElementElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbNestedCompositeElementElement; +import org.hibernate.jaxb.spi.hbm.JaxbPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbTuplizerElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class CompositePluralAttributeElementSourceImpl + extends AbstractHbmSourceNode + implements CompositePluralAttributeElementSource { + + private final JaxbCompositeElementElement compositeElement; + private final Set cascadeStyles; + private final List attributeSources; + + public CompositePluralAttributeElementSourceImpl( + MappingDocument mappingDocument, + JaxbCompositeElementElement compositeElement, + String cascadeString) { + super( mappingDocument ); + this.compositeElement = compositeElement; + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); + this.attributeSources = buildAttributeSources( mappingDocument, compositeElement ); + } + + @Override + public Nature getNature() { + return Nature.AGGREGATE; + } + + @Override + public String getClassName() { + return bindingContext().qualifyClassName( compositeElement.getClazz() ); + } + + @Override + public ValueHolder> getClassReference() { + return bindingContext().makeClassReference( getClassName() ); + } + + @Override + public String getParentReferenceAttributeName() { + return compositeElement.getParent() != null + ? compositeElement.getParent().getName() + : null; + } + + @Override + public String getExplicitTuplizerClassName() { + if ( compositeElement.getTuplizer() == null ) { + return null; + } + final EntityMode entityMode = StringHelper.isEmpty( compositeElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; + for ( JaxbTuplizerElement tuplizerElement : compositeElement.getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public String getPath() { + // todo : implementing this requires passing in the collection source and being able to resolve the collection's role + return null; + } + + @Override + public List attributeSources() { + return attributeSources; + } + + private static List buildAttributeSources( + MappingDocument mappingDocument, + JaxbCompositeElementElement compositeElement) { + List attributeSources = new ArrayList(); + for( final JaxbAnyElement element : compositeElement.getAny() ) { + attributeSources.add( buildAttributeSource( mappingDocument, element ) ); + } + for( final JaxbManyToOneElement element : compositeElement.getManyToOne() ) { + attributeSources.add( buildAttributeSource( mappingDocument, element ) ); + } + for( final JaxbNestedCompositeElementElement element : compositeElement.getNestedCompositeElement() ) { + attributeSources.add( buildAttributeSource( mappingDocument, element ) ); + } + for( final JaxbPropertyElement element : compositeElement.getProperty() ) { + attributeSources.add( buildAttributeSource( mappingDocument, element ) ); + } + return attributeSources; + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return bindingContext(); + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } + + private static AttributeSource buildAttributeSource( + MappingDocument sourceMappingDocument, + JaxbAnyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + private static SingularAttributeSource buildAttributeSource( + MappingDocument sourceMappingDocument, + JaxbPropertyElement attributeElement) { + return new PropertyAttributeSourceImpl( + sourceMappingDocument, + attributeElement, + null, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID + ); + } + + private static AttributeSource buildAttributeSource( + MappingDocument sourceMappingDocument, + JaxbManyToOneElement attributeElement) { + return new ManyToOneAttributeSourceImpl( + sourceMappingDocument, + JaxbManyToOneElement.class.cast( attributeElement ), + null, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID + ); + } + + private static AttributeSource buildAttributeSource( + MappingDocument sourceMappingDocument, + JaxbNestedCompositeElementElement attributeElement) { + // todo : implement + throw new NotYetImplementedException( "Nested composite element is not supported yet."); + } + + @Override + public Iterable getMetaAttributeSources() { + return compositeElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..25d3162eb2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/CompositePluralAttributeIndexSourceImpl.java @@ -0,0 +1,180 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbCompositeIndexElement; +import org.hibernate.jaxb.spi.hbm.JaxbCompositeMapKeyElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.CompositePluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Gail Badner + */ +public class CompositePluralAttributeIndexSourceImpl + extends AbstractHbmSourceNode + implements CompositePluralAttributeIndexSource { + + private final String className; + private final List attributeSources; + + public CompositePluralAttributeIndexSourceImpl( + MappingDocument mappingDocument, + JaxbCompositeIndexElement compositeIndexElement) { + this( + mappingDocument, + compositeIndexElement.getClazz(), + compositeIndexElement.getKeyProperty(), + compositeIndexElement.getKeyManyToOne() + ); + } + + public CompositePluralAttributeIndexSourceImpl( + MappingDocument mappingDocument, + JaxbCompositeMapKeyElement compositeMapKeyElement) { + this( + mappingDocument, + compositeMapKeyElement.getClazz(), + compositeMapKeyElement.getKeyProperty(), + compositeMapKeyElement.getKeyManyToOne() + ); + } + + private CompositePluralAttributeIndexSourceImpl( + MappingDocument mappingDocument, + String className, + List keyPropertyElements, + List keyManyToOneElements) { + super( mappingDocument ); + this.className = bindingContext().qualifyClassName( className ); + this.attributeSources = buildAttributeSources( + mappingDocument, + keyPropertyElements, + keyManyToOneElements + ); + } + + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return PluralAttributeIndexBinding.Nature.AGGREGATE; + } + + @Override + public List getDefaultNamingStrategies() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public HibernateTypeSource getTypeInformation() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isReferencedEntityAttribute() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getClassName() { + return className; + } + + @Override + public ValueHolder> getClassReference() { + return bindingContext().makeClassReference( className ); + } + + @Override + public String getPath() { + // todo : implementing this requires passing in the collection source and being able to resolve the collection's role + return null; + } + + @Override + public List attributeSources() { + return attributeSources; + } + + private static List buildAttributeSources( + MappingDocument mappingDocument, + List keyPropertyElements, + List keyManyToOneElements) { + List attributeSources = new ArrayList(); + for ( JaxbKeyPropertyElement keyProperty : keyPropertyElements ){ + attributeSources.add( + new KeyAttributeSourceImpl( + mappingDocument, + keyProperty, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID + ) + ); + } + for (JaxbKeyManyToOneElement keyManyToOne :keyManyToOneElements ){ + attributeSources.add( + new KeyManyToOneSourceImpl( + mappingDocument, + keyManyToOne, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID + ) + ); + } + return attributeSources; + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return bindingContext(); + } + + @Override + public List relationalValueSources() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/EntityHierarchyImpl.java similarity index 85% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/EntityHierarchyImpl.java index c3acf22596..fb72bd06ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/EntityHierarchyImpl.java @@ -21,16 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.RootEntitySource; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.RootEntitySource; /** * @author Steve Ebersole */ -public class EntityHierarchyImpl implements org.hibernate.metamodel.source.binder.EntityHierarchy { +public class EntityHierarchyImpl implements EntityHierarchy { private final RootEntitySourceImpl rootEntitySource; private InheritanceType hierarchyInheritanceType = InheritanceType.NO_INHERITANCE; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FetchProfileSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FetchProfileSourceImpl.java new file mode 100644 index 0000000000..d00d97c4cf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FetchProfileSourceImpl.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.jaxb.spi.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.spi.source.FetchProfileSource; + +/** + * @author Steve Ebersole + */ +public class FetchProfileSourceImpl + extends AbstractHbmSourceNode + implements FetchProfileSource { + + private final String name; + private final List associationOverrideSources; + + public FetchProfileSourceImpl( + MappingDocument mappingDocument, + JaxbFetchProfileElement fetchProfileElement) { + super( mappingDocument ); + this.name = fetchProfileElement.getName(); + this.associationOverrideSources = buildAssociationOverrideSources( fetchProfileElement ); + } + + @Override + public String getName() { + return name; + } + + @Override + public Iterable getAssociationOverrides() { + return associationOverrideSources; + } + + private static List buildAssociationOverrideSources(JaxbFetchProfileElement fetchProfileElement) { + final List associationOverrideSources = new ArrayList(); + for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfileElement.getFetch() ) { + associationOverrideSources.add( new AssociationOverrideSourceImpl( fetch ) ); + } + return associationOverrideSources; + } + + private static class AssociationOverrideSourceImpl implements AssociationOverrideSource { + private final String entityName; + private final String attributeName; + private final String fetchMode; + + private AssociationOverrideSourceImpl(JaxbFetchProfileElement.JaxbFetch fetchElement) { + this.entityName = fetchElement.getEntity(); + this.attributeName = fetchElement.getAssociation(); + this.fetchMode = fetchElement.getStyle().value(); + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getAttributeName() { + return attributeName; + } + + @Override + public String getFetchModeName() { + return fetchMode; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterDefinitionSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterDefinitionSourceImpl.java new file mode 100644 index 0000000000..7ba1796021 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterDefinitionSourceImpl.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbFilterDefElement; +import org.hibernate.jaxb.spi.hbm.JaxbFilterParamElement; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.FilterParameterSource; + +/** + * @author Steve Ebersole + */ +public class FilterDefinitionSourceImpl + extends AbstractHbmSourceNode + implements FilterDefinitionSource { + private final String name; + private final String condition; + private List parameterSources; + + public FilterDefinitionSourceImpl( + MappingDocument mappingDocument, + JaxbFilterDefElement filterDefElement) { + super( mappingDocument ); + this.name = filterDefElement.getName(); + + String conditionAttribute = filterDefElement.getCondition(); + String conditionContent = null; + + final List parameterSources = new ArrayList(); + for ( Object content : filterDefElement.getContent() ) { + if ( String.class.isInstance( content ) ){ + final String str = content.toString(); + if ( !StringHelper.isEmptyOrWhiteSpace( str ) ) { + conditionContent = str.trim(); + } + } + else if ( JAXBElement.class.isInstance( content ) ) { + JAXBElement jaxbElement = JAXBElement.class.cast( content ); + if ( jaxbElement.getDeclaredType() == JaxbFilterParamElement.class ) { + parameterSources.add( + (JaxbFilterParamElement) jaxbElement.getValue() + ); + } + } + else { + parameterSources.add( + ( JaxbFilterParamElement)content + ); + } + } + + this.condition = Helper.coalesce( conditionContent, conditionAttribute ); + this.parameterSources = parameterSources; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public Iterable getParameterSources() { + return parameterSources; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterSourceImpl.java new file mode 100644 index 0000000000..55d1fd64a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FilterSourceImpl.java @@ -0,0 +1,110 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbFilterAliasMappingType; +import org.hibernate.jaxb.spi.hbm.JaxbFilterElement; +import org.hibernate.metamodel.spi.source.FilterSource; + +/** + * @author Steve Ebersole + */ +public class FilterSourceImpl + extends AbstractHbmSourceNode + implements FilterSource { + private final String name; + private final String condition; + private final boolean autoAliasInjection; + private final Map aliasTableMap = new HashMap(); + private final Map aliasEntityMap = new HashMap(); + + public FilterSourceImpl( + MappingDocument mappingDocument, + JaxbFilterElement filterElement) { + super( mappingDocument ); + this.name = filterElement.getName(); + + String explicitAutoAliasInjectionSetting = filterElement.getAutoAliasInjection(); + + String conditionAttribute = filterElement.getCondition(); + String conditionContent = null; + + for ( Serializable content : filterElement.getContent() ) { + if ( String.class.isInstance( content ) ) { + final String str = content.toString(); + if ( !StringHelper.isEmptyOrWhiteSpace( str ) ) { + conditionContent = str.trim(); + } + } + else { + final JaxbFilterAliasMappingType aliasMapping = JaxbFilterAliasMappingType.class.cast( content ); + if ( StringHelper.isNotEmpty( aliasMapping.getTable() ) ) { + aliasTableMap.put( aliasMapping.getAlias(), aliasMapping.getTable() ); + } + else if ( StringHelper.isNotEmpty( aliasMapping.getEntity() ) ) { + aliasEntityMap.put( aliasMapping.getAlias(), aliasMapping.getTable() ); + } + else { + throw mappingDocument.getMappingLocalBindingContext() + .makeMappingException( "filter alias must define either table or entity attribute" ); + } + } + } + + this.condition = Helper.coalesce( conditionContent, conditionAttribute ); + this.autoAliasInjection = StringHelper.isNotEmpty( explicitAutoAliasInjectionSetting ) + ? Boolean.valueOf( explicitAutoAliasInjectionSetting ) + : true; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public boolean shouldAutoInjectAliases() { + return autoAliasInjection; + } + + @Override + public Map getAliasToTableMap() { + return aliasTableMap; + } + + @Override + public Map getAliasToEntityMap() { + return aliasEntityMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java index f452491c0e..6f74e92dab 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java @@ -21,22 +21,30 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.metamodel.source.binder.DerivedValueSource; +import org.hibernate.metamodel.spi.source.DerivedValueSource; /** * @author Steve Ebersole */ -class FormulaImpl implements DerivedValueSource { +class FormulaImpl + extends AbstractHbmSourceNode + implements DerivedValueSource { private String tableName; private final String expression; - FormulaImpl(String tableName, String expression) { + FormulaImpl(MappingDocument mappingDocument, String tableName, String expression) { + super( mappingDocument ); this.tableName = tableName; this.expression = expression; } + @Override + public Nature getNature() { + return Nature.DERIVED; + } + @Override public String getExpression() { return expression; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmBindingContext.java similarity index 80% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmBindingContext.java index 4b756a69b7..e11f7184c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmBindingContext.java @@ -21,18 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.metamodel.source.BindingContext; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MetaAttributeContext; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** - * Defines features specific to the {@code hbm.xml} variety of a {@link BindingContext} + * Defines features specific to the {@code hbm.xml} variety of a {@link org.hibernate.metamodel.spi.source.BindingContext} * * @author Steve Ebersole */ @@ -44,4 +43,5 @@ public interface HbmBindingContext extends LocalBindingContext { public String determineEntityName(EntityElement entityElement); public void processFetchProfiles(List fetchProfiles, String containingEntityName); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmMetadataSourceProcessorImpl.java new file mode 100644 index 0000000000..623d692ddf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HbmMetadataSourceProcessorImpl.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.jboss.logging.Logger; + +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; + +import static java.util.Collections.emptyList; + +/** + * The {@link org.hibernate.metamodel.spi.MetadataSourceProcessor} implementation responsible for processing {@code hbm.xml} sources. + * + * @author Steve Ebersole + */ +public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor { + private static final CoreMessageLogger LOG = Logger + .getMessageLogger( CoreMessageLogger.class, HbmMetadataSourceProcessorImpl.class.getName() ); + private final List processors = new ArrayList(); + private final List entityHierarchies; + + public HbmMetadataSourceProcessorImpl(MetadataImplementor metadata, MetadataSources metadataSources) { + this( metadata, metadataSources.getJaxbRootList() ); + } + + public HbmMetadataSourceProcessorImpl(MetadataImplementor metadata, List jaxbRoots) { + final HierarchyBuilder hierarchyBuilder = new HierarchyBuilder( metadata ); + + for ( JaxbRoot jaxbRoot : jaxbRoots ) { + if ( ! JaxbHibernateMapping.class.isInstance( jaxbRoot.getRoot() ) ) { + continue; + } + + final MappingDocument mappingDocument = new MappingDocument( jaxbRoot, metadata ); + processors.add( new HibernateMappingProcessor( metadata, mappingDocument ) ); + + hierarchyBuilder.processMappingDocument( mappingDocument ); + } + + this.entityHierarchies = hierarchyBuilder.groupEntityHierarchies(); + } + + // todo : still need to deal with auxiliary database objects + + @Override + public Iterable extractTypeDefinitionSources() { + if( CollectionHelper.isEmpty( processors )){ + return emptyList(); + } + final List typeDescriptorSources = new ArrayList(); + for ( HibernateMappingProcessor processor : processors ) { + processor.collectTypeDescriptorSources( typeDescriptorSources ); + } + return typeDescriptorSources; + } + + @Override + public Iterable extractFilterDefinitionSources() { + if( CollectionHelper.isEmpty( processors )){ + return emptyList(); + } + final List filterDefinitionSources = new ArrayList(); + for ( HibernateMappingProcessor processor : processors ) { + processor.collectFilterDefSources( filterDefinitionSources ); + } + return filterDefinitionSources; + } + + @Override + public Iterable extractGlobalIdentifierGeneratorSources() { + return emptyList(); + } + + @Override + @SuppressWarnings( {"unchecked", "RedundantCast"}) + public Iterable extractEntityHierarchies() { + return (Iterable) entityHierarchies; + } + + @Override + public void processMappingDependentMetadata() { + for ( HibernateMappingProcessor processor : processors ) { + processor.processMappingDependentMetadata(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/Helper.java new file mode 100644 index 0000000000..afa0e735b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/Helper.java @@ -0,0 +1,525 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.LockMode; +import org.hibernate.TruthValue; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbCacheElement; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbLockModeAttribute; +import org.hibernate.jaxb.spi.hbm.JaxbNaturalIdCacheElement; +import org.hibernate.jaxb.spi.hbm.JaxbParamElement; +import org.hibernate.jaxb.spi.hbm.JaxbSqlDmlElement; +import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbUnionSubclassElement; +import org.hibernate.jaxb.spi.hbm.TableInformationSource; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.MetaAttribute; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SizeSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; + +/** + * A helper for dealing with + * @author Steve Ebersole + * @author Gail Badner + */ +public class Helper { + private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId"; + public static final HibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new HibernateTypeSource() { + @Override + public String getName() { + return null; + } + + @Override + public Map getParameters() { + return null; + } + @Override + public Class getJavaType() { + return null; + } + }; + + public static LockMode interpretLockMode(JaxbLockModeAttribute lockModeAttribute, LocalBindingContext context){ + if ( lockModeAttribute == null ) { + return LockMode.READ; + } + switch ( lockModeAttribute ) { + case NONE: + return LockMode.NONE; + case UPGRADE: + return LockMode.UPGRADE; + case UPGRADE_NOWAIT: + return LockMode.UPGRADE_NOWAIT; + case READ: + return LockMode.READ; + case WRITE: + return LockMode.WRITE; + case FORCE: + return LockMode.FORCE; + case OPTIMISTIC: + return LockMode.OPTIMISTIC; + case OPTIMISTIC_FORCE_INCREMENT: + return LockMode.OPTIMISTIC_FORCE_INCREMENT; + case PESSIMISTIC_READ: + return LockMode.PESSIMISTIC_READ; + case PESSIMISTIC_WRITE: + return LockMode.PESSIMISTIC_WRITE; + case PESSIMISTIC_FORCE_INCREMENT: + return LockMode.PESSIMISTIC_FORCE_INCREMENT; + default: + throw context.makeMappingException( "unknown lock mode: "+lockModeAttribute ); + } + } + + public static InheritanceType interpretInheritanceType(EntityElement entityElement) { + if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.SINGLE_TABLE; + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.JOINED; + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.TABLE_PER_CLASS; + } + else { + return InheritanceType.NO_INHERITANCE; + } + } + + /** + * Given a user-specified description of how to perform custom SQL, build the {@link CustomSQL} representation. + * + * @param customSqlElement User-specified description of how to perform custom SQL + * + * @return The {@link CustomSQL} representation + */ + public static CustomSQL buildCustomSql(JaxbSqlDmlElement customSqlElement) { + if ( customSqlElement == null ) { + return null; + } + final ExecuteUpdateResultCheckStyle checkStyle = customSqlElement.getCheck() == null + ? customSqlElement.isCallable() + ? ExecuteUpdateResultCheckStyle.NONE + : ExecuteUpdateResultCheckStyle.COUNT + : ExecuteUpdateResultCheckStyle.fromExternalName( customSqlElement.getCheck().value() ); + return new CustomSQL( customSqlElement.getValue(), customSqlElement.isCallable(), checkStyle ); + } + + /** + * Given the user-specified entity mapping, determine the appropriate entity name + * + * @param entityElement The user-specified entity mapping + * @param unqualifiedClassPackage The package to use for unqualified class names + * + * @return The appropriate entity name + */ + public static String determineEntityName(EntityElement entityElement, String unqualifiedClassPackage) { + return entityElement.getEntityName() != null + ? entityElement.getEntityName() + : qualifyIfNeeded( entityElement.getName(), unqualifiedClassPackage ); + } + + public static Caching createCaching(final JaxbCacheElement cacheElement, final String defaultRegionName) { + if ( cacheElement == null ) { + return null; + } + final String region = cacheElement.getRegion() != null ? cacheElement.getRegion() : defaultRegionName; + final AccessType accessType = AccessType.fromExternalName( cacheElement.getUsage().value() ); + final boolean cacheLazyProps = !"non-lazy".equals( cacheElement.getInclude() ); + return new Caching( region, accessType, cacheLazyProps ); + } + + public static ValueHolder createNaturalIdCachingHolder(final JaxbNaturalIdCacheElement cacheElement, final String entityName, final Caching entityCache) { + return new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public Caching initialize() { + if ( cacheElement == null ) { + return null; + } + final String region; + if ( StringHelper.isEmpty( cacheElement.getRegion() ) ) { + String temp = entityCache != null ? entityCache.getRegion() : entityName; + region = temp + NATURAL_ID_CACHE_SUFFIX; + } + else { + region = cacheElement.getRegion(); + } + return new Caching( region, null, false ); + } + } + ); + } + + /** + * Qualify a (supposed class) name with the unqualified-class package name if it is not already qualified + * + * @param name The name + * @param unqualifiedClassPackage The unqualified-class package name + * + * @return {@code null} if the incoming name was {@code null}; or the qualified name. + */ + public static String qualifyIfNeeded(String name, String unqualifiedClassPackage) { + if ( name == null ) { + return null; + } + if ( name.indexOf( '.' ) < 0 && unqualifiedClassPackage != null ) { + return unqualifiedClassPackage + '.' + name; + } + return name; + } + + public static String getPropertyAccessorName(String access, boolean isEmbedded, String defaultAccess) { + return getValue( access, isEmbedded ? "embedded" : defaultAccess ); + } + + public static MetaAttributeContext extractMetaAttributeContext( + List metaAttributeSourceList, + boolean onlyInheritable, + MetaAttributeContext parentContext) { + final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); + + for ( MetaAttributeSource meta : metaAttributeSourceList ) { + if ( onlyInheritable & !meta.isInheritable() ) { + continue; + } + + final String name = meta.getName(); + final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); + MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); + if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { + metaAttribute = new MetaAttribute( name ); + subContext.add( metaAttribute ); + } + metaAttribute.addValue( meta.getValue() ); + } + + return subContext; + } + + public static T getValue(T value, T defaultValue){ + return value == null ? defaultValue : value; + } + + public static Set interpretCascadeStyles(String cascades, LocalBindingContext bindingContext) { + final Set cascadeStyles = new HashSet(); + if ( StringHelper.isEmpty( cascades ) ) { + cascades = bindingContext.getMappingDefaults().getCascadeStyle(); + } + for ( String cascade : StringHelper.split( " ,", cascades ) ) { + cascadeStyles.add( CascadeStyles.getCascadeStyle( cascade ) ); + } + return cascadeStyles; + } + + public static Map extractParameters(List xmlParamElements) { + if ( xmlParamElements == null || xmlParamElements.isEmpty() ) { + return Collections.emptyMap(); + } + final HashMap params = new HashMap(); + for ( JaxbParamElement paramElement : xmlParamElements ) { + params.put( paramElement.getName(), paramElement.getValue() ); + } + return params; + } + + public static SizeSource createSizeSourceIfMapped(Integer length, Integer precision, Integer scale) { + if ( length != null || precision != null || scale != null ) { + return new SizeSourceImpl( precision, scale, length ); + } + return null; + } + + public static Schema.Name determineDatabaseSchemaName( + String explicitSchemaName, + String explicitCatalogName, + LocalBindingContext bindingContext) { + return new Schema.Name( + resolveIdentifier( + explicitCatalogName, + bindingContext.getMappingDefaults().getCatalogName(), + bindingContext.isGloballyQuotedIdentifiers() + ), resolveIdentifier( + explicitSchemaName, + bindingContext.getMappingDefaults().getSchemaName(), + bindingContext.isGloballyQuotedIdentifiers() + ) + ); + } + + public static Identifier resolveIdentifier(String explicitName, String defaultName, boolean globalQuoting) { + String name = StringHelper.isNotEmpty( explicitName ) ? explicitName : defaultName; + if ( globalQuoting ) { + name = StringHelper.quote( name ); + } + return Identifier.toIdentifier( name ); + } + + /** + * Operates like SQL coalesce expression, except empty strings are treated as null. Return the first non-empty value + * + * @param values The list of values. + * @param + * + * @return The first non-empty value, or null if all values were empty + */ + public static T coalesce(T... values) { + if ( values == null ) { + return null; + } + for ( T value : values ) { + if ( value != null ) { + if ( String.class.isInstance( value ) ) { + if ( StringHelper.isNotEmpty( (String) value ) ) { + return value; + } + } + else { + return value; + } + } + } + return null; + } + + public static interface InLineViewNameInferrer { + public String inferInLineViewName(); + } + + public static TableSpecificationSource createTableSource( + MappingDocument mappingDocument, + TableInformationSource jaxbTableSource, + InLineViewNameInferrer inLineViewNameInferrer) { + if ( jaxbTableSource.getSubselectAttribute() == null && jaxbTableSource.getSubselect() == null ) { + return new TableSourceImpl( + mappingDocument, + jaxbTableSource.getSchema(), + jaxbTableSource.getCatalog(), + jaxbTableSource.getTable() + ); + } + else { + return new InLineViewSourceImpl( + mappingDocument, + jaxbTableSource.getSchema(), + jaxbTableSource.getCatalog(), + jaxbTableSource.getSubselectAttribute() != null + ? jaxbTableSource.getSubselectAttribute() + : jaxbTableSource.getSubselect(), + jaxbTableSource.getTable() == null + ? inLineViewNameInferrer.inferInLineViewName() + : jaxbTableSource.getTable() + ); + } + + } + + /** + * For things that define one or more "value sources" there is a lot of variance in terms of how they + * look in the XML. As an example, consider {@code } which might have:
            + *
          • a {@code column} XML attribute
          • + *
          • a {@code formula} XML attribute
          • + *
          • one or more nested {@code } XML elements
          • + *
          • a {@code } XML element
          • + *
          + * as opposed to {@code } which can only have:
            + *
          • a {@code column} XML attribute
          • + *
          + *

          + * This class adapts those variances to a unified contract which is intended to be used in conjunction with + * {@link #buildValueSources}. + */ + public static class ValueSourcesAdapter { + public String getContainingTableName() { + return null; + } + + public boolean isIncludedInInsertByDefault() { + return false; + } + + public boolean isIncludedInUpdateByDefault() { + return false; + } + + public String getColumnAttribute() { + return null; + } + + public String getFormulaAttribute() { + return null; + } + + public SizeSource getSizeSource() { + return null; + } + + public List getColumn(){ + return Collections.emptyList(); + } + + public List getFormula(){ + return Collections.emptyList(); + } + + public boolean isForceNotNull() { + return false; + } + } + + private static void checkColumnOrFormulaElements(MappingDocument mappingDocument, ValueSourcesAdapter valueSourcesAdapter) { + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getColumn() ) || CollectionHelper.isNotEmpty( + valueSourcesAdapter.getFormula() + ) ) { + throw mappingDocument.getMappingLocalBindingContext().makeMappingException( + "column/formula/size attribute may not be used together with / subelement" + ); + } + } + + /** + * Given a {@link ValueSourcesAdapter}, build the corresponding list of {@link RelationalValueSource} + * + * @param mappingDocument the mapping document + * @param valueSourcesAdapter the adapter describing the value sources. + * + * @return The corresponding list. + */ + public static List buildValueSources( + MappingDocument mappingDocument, + ValueSourcesAdapter valueSourcesAdapter) { + List result = new ArrayList(); + + if ( StringHelper.isNotEmpty( valueSourcesAdapter.getColumnAttribute() ) ) { + // we have the XML defining a column attribute. + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements(mappingDocument, valueSourcesAdapter); + // it is also illegal for there to also be a formula attribute + if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { + throw mappingDocument.getMappingLocalBindingContext().makeMappingException( + "column and formula attributes may not be used together" + ); + } + + result.add( + new ColumnAttributeSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getColumnAttribute(), + valueSourcesAdapter.getSizeSource(), + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.UNKNOWN + ) + ); + } + else if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { + // we have the XML defining a formula attribute (and not a column attribute) + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements( mappingDocument, valueSourcesAdapter ); + // column/formula attribute combo checked already + + result.add( + new FormulaImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getFormulaAttribute() + ) + ); + } + else if ( valueSourcesAdapter.getSizeSource() != null ) { + // we have XML defining a length, precision, and/or scale attribute with neither + // a column nor formula attribute; assume this is a column. + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements(mappingDocument, valueSourcesAdapter); + result.add( + new ColumnAttributeSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getColumnAttribute(), + valueSourcesAdapter.getSizeSource(), + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.UNKNOWN + ) + ); + + } + // we have the XML defining nested formula or column elements (and not column attribute nor formula attribute) + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getColumn() ) ) { + for ( JaxbColumnElement column : valueSourcesAdapter.getColumn() ) { + result.add( + new ColumnSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + column, + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.TRUE + ) + ); + } + } + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getFormula() ) ) { + for ( String formula : valueSourcesAdapter.getFormula() ) { + result.add( + new FormulaImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + formula + ) + ); + } + } + return result; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HibernateMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HibernateMappingProcessor.java new file mode 100644 index 0000000000..ae4f6be1a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HibernateMappingProcessor.java @@ -0,0 +1,333 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jboss.logging.Logger; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbClassElement; +import org.hibernate.jaxb.spi.hbm.JaxbDatabaseObjectElement; +import org.hibernate.jaxb.spi.hbm.JaxbDialectScopeElement; +import org.hibernate.jaxb.spi.hbm.JaxbFetchProfileElement; +import org.hibernate.jaxb.spi.hbm.JaxbFilterDefElement; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.jaxb.spi.hbm.JaxbIdentifierGeneratorElement; +import org.hibernate.jaxb.spi.hbm.JaxbImportElement; +import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbResultsetElement; +import org.hibernate.jaxb.spi.hbm.JaxbSqlQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbTypedefElement; +import org.hibernate.jaxb.spi.hbm.JaxbUnionSubclassElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.BasicAuxiliaryDatabaseObjectImpl; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; + +/** + * Responsible for processing a {@code } element. Allows processing to be coordinated across + * all hbm files in an ordered fashion. The order is essentially the same as defined in + * {@link org.hibernate.metamodel.spi.MetadataSourceProcessor} + * + * @author Steve Ebersole + * @author Strong Liu + */ +public class HibernateMappingProcessor { + private static final CoreMessageLogger LOG = Logger + .getMessageLogger( CoreMessageLogger.class, HibernateMappingProcessor.class.getName() ); + + private final MetadataImplementor metadata; + private final MappingDocument mappingDocument; + + private final ValueHolder classLoaderService = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public ClassLoaderService initialize() { + return metadata.getServiceRegistry().getService( ClassLoaderService.class ); + } + } + ); + + public HibernateMappingProcessor(MetadataImplementor metadata, MappingDocument mappingDocument) { + this.metadata = metadata; + this.mappingDocument = mappingDocument; + processDatabaseObjectDefinitions(); + processIdentifierGenerators(); + } + + private JaxbHibernateMapping mappingRoot() { + return mappingDocument.getMappingRoot(); + } + + private HbmBindingContext bindingContext() { + return mappingDocument.getMappingLocalBindingContext(); + } + + private Class classForName(String name) { + return classLoaderService.getValue().classForName( bindingContext().qualifyClassName( name ) ); + } + + private void processDatabaseObjectDefinitions() { + if ( mappingRoot().getDatabaseObject() == null ) { + return; + } + + for ( JaxbDatabaseObjectElement databaseObjectElement : mappingRoot().getDatabaseObject() ) { + final AuxiliaryDatabaseObject auxiliaryDatabaseObject; + if ( databaseObjectElement.getDefinition() != null ) { + final String className = databaseObjectElement.getDefinition().getClazz(); + try { + auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classForName( className ).newInstance(); + } + catch ( ClassLoadingException e ) { + throw e; + } + catch ( Exception e ) { + throw bindingContext().makeMappingException( "could not instantiate custom database object class [" + className + "]" ); + } + } + else { + Set dialectScopes = new HashSet(); + if ( databaseObjectElement.getDialectScope() != null ) { + for ( JaxbDialectScopeElement dialectScope : databaseObjectElement.getDialectScope() ) { + dialectScopes.add( dialectScope.getName() ); + } + } + auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl( + metadata.getDatabase().getDefaultSchema(), + databaseObjectElement.getCreate(), + databaseObjectElement.getDrop(), + dialectScopes + ); + } + metadata.getDatabase().addAuxiliaryDatabaseObject( auxiliaryDatabaseObject ); + } + } + + public void collectTypeDescriptorSources(List typeDescriptorSources) { + if ( mappingRoot().getTypedef() == null ) { + return; + } + + for ( JaxbTypedefElement typeDefElement : mappingRoot().getTypedef() ) { + typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDefElement ) ); + } + } + + public void collectFilterDefSources(List filterDefinitionSources) { + if ( mappingRoot().getFilterDef() == null ) { + return; + } + + for ( JaxbFilterDefElement filterDefElement : mappingRoot().getFilterDef() ) { + filterDefinitionSources.add( new FilterDefinitionSourceImpl( mappingDocument, filterDefElement ) ); + } + } + + + private void processIdentifierGenerators() { + if ( mappingRoot().getIdentifierGenerator() == null ) { + return; + } + + for ( JaxbIdentifierGeneratorElement identifierGeneratorElement : mappingRoot().getIdentifierGenerator() ) { + metadata.registerIdentifierGenerator( + identifierGeneratorElement.getName(), + identifierGeneratorElement.getClazz() + ); + } + } + + public void processMappingDependentMetadata() { + processFetchProfiles(); + processImports(); + processResultSetMappings(); + processNamedQueries(); + } + + private void processFetchProfiles() { + processFetchProfiles( mappingRoot().getFetchProfile(), null ); + for ( JaxbClassElement classElement : mappingRoot().getClazz() ) { + processFetchProfile( classElement ); + + // processing fetch profiles defined in the + processFetchProfilesInJoinedSubclass( classElement.getJoinedSubclass() ); + // + processFetchProfilesInUnionSubclass( classElement.getUnionSubclass() ); + // + processFetchProfilesInSubclass( classElement.getSubclass() ); + } + } + + private void processFetchProfilesInSubclass(List subclass) { + for ( JaxbSubclassElement subclassElement : subclass ) { + processFetchProfile( subclassElement ); + processFetchProfilesInSubclass( subclassElement.getSubclass() ); + } + } + + private void processFetchProfile(final EntityElement entityElement){ + processFetchProfiles( + entityElement.getFetchProfile(), + bindingContext().qualifyClassName( entityElement.getName() ) + ); + } + + private void processFetchProfilesInUnionSubclass(List unionSubclass) { + for ( JaxbUnionSubclassElement subclassElement : unionSubclass ) { + processFetchProfile( subclassElement ); + processFetchProfilesInUnionSubclass( subclassElement.getUnionSubclass() ); + } + } + + private void processFetchProfilesInJoinedSubclass(List joinedSubclassElements) { + for ( JaxbJoinedSubclassElement subclassElement : joinedSubclassElements ) { + processFetchProfile( subclassElement ); + processFetchProfilesInJoinedSubclass( subclassElement.getJoinedSubclass() ); + } + } + + public void processFetchProfiles(List fetchProfiles, String containingEntityName) { + for ( JaxbFetchProfileElement fetchProfile : fetchProfiles ) { + String profileName = fetchProfile.getName(); + Set fetches = new HashSet(); + for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfile.getFetch() ) { + String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity(); + if ( entityName == null ) { + throw bindingContext().makeMappingException( "could not determine entity for fetch-profile fetch [" + profileName + "]:[" + + fetch.getAssociation() + "]" ); + } + fetches.add( new FetchProfile.Fetch( entityName, fetch.getAssociation(), fetch.getStyle().value() ) ); + } + metadata.addFetchProfile( new FetchProfile( profileName, fetches ) ); + } + } + + private void processImports() { + JaxbHibernateMapping root = mappingRoot(); + for ( JaxbImportElement importValue : root.getImport() ) { + String className = bindingContext().qualifyClassName( importValue.getClazz() ); + String rename = importValue.getRename(); + rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename; + metadata.addImport( rename, className ); + } + if ( root.isAutoImport() ) { + processEntityElementsImport( root.getClazz() ); + processEntityElementsImport( root.getJoinedSubclass() ); + processEntityElementsImport( root.getUnionSubclass() ); + processEntityElementsImport( root.getSubclass() ); + } + } + + private void processEntityElementsImport(List entityElements) { + for ( final EntityElement element : entityElements ) { + processEntityElementImport( element ); + } + } + + private void processEntityElementImport(EntityElement entityElement) { + final String qualifiedName = bindingContext().determineEntityName( entityElement ); + final String importName = entityElement.getEntityName() == null + ? entityElement.getName() + : entityElement.getEntityName(); + metadata.addImport( importName, qualifiedName ); + metadata.addImport( StringHelper.unqualify(importName ), qualifiedName ); + + if ( JaxbClassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getSubclass() ); + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getJoinedSubclass() ); + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getUnionSubclass() ); + } + else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbSubclassElement) entityElement ).getSubclass() ); + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbJoinedSubclassElement) entityElement ).getJoinedSubclass() ); + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbUnionSubclassElement) entityElement ).getUnionSubclass() ); + } + } + + private void processResultSetMappings() { + List resultsetElements = new ArrayList(); + + addAllIfNotEmpty( resultsetElements, mappingRoot().getResultset() ); + findResultSets( resultsetElements, mappingRoot().getClazz() ); + findResultSets( resultsetElements, mappingRoot().getJoinedSubclass() ); + findResultSets( resultsetElements, mappingRoot().getUnionSubclass() ); + findResultSets( resultsetElements, mappingRoot().getSubclass() ); + if ( resultsetElements.isEmpty() ) { + return; + } + for ( final JaxbResultsetElement element : resultsetElements ) { + metadata.addResultSetMapping( + ResultSetMappingBinder.buildResultSetMappingDefinitions( + element, bindingContext(), metadata + ) + ); + } + + } + + private static void findResultSets(List resultsetElements, List entityElements) { + for ( final EntityElement element : entityElements ) { + addAllIfNotEmpty( resultsetElements, element.getResultset() ); + } + } + + private static void addAllIfNotEmpty(List target, List values) { + if ( CollectionHelper.isNotEmpty( values ) ) { + target.addAll( values ); + } + } + + private void processNamedQueries() { + for ( final JaxbQueryElement element : mappingRoot().getQuery() ) { + NamedQueryBindingHelper.bindNamedQuery( element, metadata ); + } + for ( final JaxbSqlQueryElement element : mappingRoot().getSqlQuery() ) { + NamedQueryBindingHelper.bindNamedSQLQuery( + element, + bindingContext(), + metadata + ); + } + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HierarchyBuilder.java new file mode 100644 index 0000000000..f2b87e6798 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/HierarchyBuilder.java @@ -0,0 +1,228 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.MappingException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbClassElement; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbSqlQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbUnionSubclassElement; +import org.hibernate.jaxb.spi.hbm.SubEntityElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntityContainer; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; + +/** + * @author Steve Ebersole + */ +public class HierarchyBuilder { + private static final CoreMessageLogger LOG = Logger + .getMessageLogger( CoreMessageLogger.class, HierarchyBuilder.class.getName() ); + private final MetadataImplementor metadata; + + private final List entityHierarchies = new ArrayList(); + + // process state + private final Map subEntityContainerMap = new HashMap(); + private final List extendsQueue = new ArrayList(); + + // mapping file specific state + private MappingDocument currentMappingDocument; + + public HierarchyBuilder( MetadataImplementor metadata ) { + this.metadata = metadata; + } + + public void processMappingDocument(MappingDocument mappingDocument) { + this.currentMappingDocument = mappingDocument; + try { + LOG.tracef( "Processing mapping document: %s ", mappingDocument.getOrigin() ); + processCurrentMappingDocument(); + } + finally { + this.currentMappingDocument = null; + } + } + + private void processCurrentMappingDocument() { + final JaxbHibernateMapping root = currentMappingDocument.getMappingRoot(); + for ( final JaxbClassElement jaxbClass : root.getClazz() ) { + // we can immediately handle elements in terms of creating the hierarchy entry + final RootEntitySourceImpl rootEntitySource = new RootEntitySourceImpl( + currentMappingDocument, + jaxbClass + ); + final EntityHierarchyImpl hierarchy = new EntityHierarchyImpl( rootEntitySource ); + entityHierarchies.add( hierarchy ); + subEntityContainerMap.put( rootEntitySource.getEntityName(), rootEntitySource ); + processSubElements( jaxbClass, rootEntitySource ); + } + List subEntityElements = new ArrayList( root.getJoinedSubclass() ); + subEntityElements.addAll( root.getUnionSubclass() ); + subEntityElements.addAll( root.getSubclass() ); + + for ( final SubEntityElement element : subEntityElements ) { + processSubclassElement( element ); + } + + } + + private void processSubclassElement(SubEntityElement element) { + // we have to see if this things super-type has been found yet, and if not add it to the + // extends queue + final String entityItExtends = currentMappingDocument.getMappingLocalBindingContext() + .qualifyClassName( element.getExtends() ); + final SubclassEntityContainer container = subEntityContainerMap.get( entityItExtends ); + final SubclassEntitySourceImpl subClassEntitySource = createSubClassEntitySource( element, (EntitySource) container ); + final String entityName = subClassEntitySource.getEntityName(); + subEntityContainerMap.put( entityName, subClassEntitySource ); + processSubElements( element, subClassEntitySource ); + if ( container != null ) { + // we already have this entity's super, attach it and continue + container.add( subClassEntitySource ); + } + else { + // we do not yet have the super and have to wait, so add it fto the extends queue + extendsQueue.add( new ExtendsQueueEntry( subClassEntitySource, entityItExtends ) ); + } + } + + public List groupEntityHierarchies() { + while ( ! extendsQueue.isEmpty() ) { + // set up a pass over the queue + int numberOfMappingsProcessed = 0; + Iterator iterator = extendsQueue.iterator(); + while ( iterator.hasNext() ) { + final ExtendsQueueEntry entry = iterator.next(); + final SubclassEntityContainer container = subEntityContainerMap.get( entry.entityItExtends ); + if ( container != null ) { + // we now have this entity's super, attach it and remove entry from extends queue + container.add( entry.subClassEntitySource ); + iterator.remove(); + numberOfMappingsProcessed++; + } + } + + if ( numberOfMappingsProcessed == 0 ) { + + // todo : we could log the waiting dependencies... + throw currentMappingDocument.getMappingLocalBindingContext().makeMappingException( "Unable to process extends dependencies in hbm files" ); + } + } + + return entityHierarchies; + } + + private void processSubElements(EntityElement entityElement, SubclassEntityContainer container) { + if ( JaxbClassElement.class.isInstance( entityElement ) ) { + final JaxbClassElement jaxbClass = (JaxbClassElement) entityElement; + processElements( jaxbClass.getJoinedSubclass(), container ); + processElements( jaxbClass.getSubclass(), container ); + processElements( jaxbClass.getUnionSubclass(), container ); + } + else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + final JaxbSubclassElement jaxbSubclass = (JaxbSubclassElement) entityElement; + processElements( jaxbSubclass.getSubclass(), container ); + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + final JaxbJoinedSubclassElement jaxbJoinedSubclass = (JaxbJoinedSubclassElement) entityElement; + processElements( jaxbJoinedSubclass.getJoinedSubclass(), container ); + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + final JaxbUnionSubclassElement jaxbUnionSubclass = (JaxbUnionSubclassElement) entityElement; + processElements( jaxbUnionSubclass.getUnionSubclass(), container ); + } + processNamedQueries( entityElement ); + } + + private void processElements(List subElements, SubclassEntityContainer container) { + for ( final SubEntityElement subElement : subElements ) { + final SubclassEntitySourceImpl subclassEntitySource = createSubClassEntitySource( subElement, ( EntitySource ) container ); + container.add( subclassEntitySource ); + final String subEntityName = subclassEntitySource.getEntityName(); + subEntityContainerMap.put( subEntityName, subclassEntitySource ); + + // Re-run the sub element to handle, as an example, subclasses + // within a subclass. + processSubElements(subElement, subclassEntitySource); + } + } + + private SubclassEntitySourceImpl createSubClassEntitySource(SubEntityElement subEntityElement, EntitySource entitySource) { + if ( JaxbJoinedSubclassElement.class.isInstance( subEntityElement ) ) { + return new JoinedSubclassEntitySourceImpl( + currentMappingDocument, + JaxbJoinedSubclassElement.class.cast( subEntityElement ), + entitySource + ); + } + else { + return new SubclassEntitySourceImpl( currentMappingDocument, subEntityElement, entitySource ); + } + } + + private void processNamedQueries( EntityElement entityElement ) { + // For backward compatibility, store named queries prefixed with + // the class name. + String queryNamePrefix = entityElement.getEntityName(); + queryNamePrefix = StringHelper.isNotEmpty( queryNamePrefix ) ? queryNamePrefix : currentMappingDocument.getMappingLocalBindingContext().qualifyClassName( entityElement.getName() ); + for ( final JaxbQueryElement element : entityElement.getQuery() ) { + element.setName( queryNamePrefix + "." + element.getName() ); + NamedQueryBindingHelper.bindNamedQuery( element, metadata ); + } + for ( final JaxbSqlQueryElement element : entityElement.getSqlQuery() ) { + element.setName( queryNamePrefix + "." + element.getName() ); + NamedQueryBindingHelper.bindNamedSQLQuery( + element, + currentMappingDocument.getMappingLocalBindingContext(), + metadata + ); + } + } + + private static class ExtendsQueueEntry { + private final SubclassEntitySource subClassEntitySource; + private final String entityItExtends; + + private ExtendsQueueEntry(SubclassEntitySource subClassEntitySource, String entityItExtends) { + this.subClassEntitySource = subClassEntitySource; + this.entityItExtends = entityItExtends; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyAttributeSourceImpl.java new file mode 100644 index 0000000000..1ef6986a3f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyAttributeSourceImpl.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +/** + * @author Gail Badner + */ +public class IdentifierKeyAttributeSourceImpl extends KeyAttributeSourceImpl { + + public IdentifierKeyAttributeSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyPropertyElement keyPropertyElement) { + super( mappingDocument, keyPropertyElement, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java new file mode 100644 index 0000000000..2a942ebb50 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +/** + * @author Gail Badner + */ +public class IdentifierKeyManyToOneSourceImpl extends KeyManyToOneSourceImpl { + + public IdentifierKeyManyToOneSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyManyToOneElement keyManyToOneElement) { + super( mappingDocument, keyManyToOneElement, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/InLineViewSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/InLineViewSourceImpl.java new file mode 100644 index 0000000000..479077ddf6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/InLineViewSourceImpl.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.metamodel.spi.source.InLineViewSource; + +/** + * @author Steve Ebersole + */ +public class InLineViewSourceImpl + extends AbstractHbmSourceNode + implements InLineViewSource { + private final String schemaName; + private final String catalogName; + private final String selectStatement; + private final String logicalName; + + public InLineViewSourceImpl( + MappingDocument mappingDocument, + String schemaName, + String catalogName, + String selectStatement, String logicalName) { + super( mappingDocument ); + this.schemaName = schemaName; + this.catalogName = catalogName; + this.selectStatement = selectStatement; + this.logicalName = logicalName; + } + + @Override + public String getExplicitSchemaName() { + return schemaName; + } + + @Override + public String getExplicitCatalogName() { + return catalogName; + } + + @Override + public String getSelectStatement() { + return selectStatement; + } + + @Override + public String getLogicalName() { + return logicalName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IndexConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IndexConstraintSourceImpl.java new file mode 100644 index 0000000000..d9fc845142 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IndexConstraintSourceImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; + +import org.hibernate.metamodel.spi.source.IndexConstraintSource; + +/** + * @author Brett Meyer + */ +class IndexConstraintSourceImpl extends AbstractConstraintSource implements IndexConstraintSource { + + public IndexConstraintSourceImpl( String name, String tableName ) { + super( name, tableName ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "IndexConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java new file mode 100644 index 0000000000..80552ea985 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java @@ -0,0 +1,124 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyElement; +import org.hibernate.jaxb.spi.hbm.JaxbOnDeleteAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.JoinedSubclassEntitySource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Strong Liu + */ +public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl implements JoinedSubclassEntitySource { + private final JaxbKeyElement key; + private final List primaryKeyJoinColumnSources; + + public JoinedSubclassEntitySourceImpl(MappingDocument sourceMappingDocument, JaxbJoinedSubclassElement entityElement, EntitySource container) { + super( sourceMappingDocument, entityElement, container ); + this.key = entityElement.getKey(); + List valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return Helper.getValue( key.isUpdate(), true ); + } + + @Override + public String getColumnAttribute() { + return key.getColumnAttribute(); + } + + @Override + public List getColumn() { + return key.getColumn(); + } + + @Override + public boolean isForceNotNull() { + return Helper.getValue( key.isNotNull(), false ); + } + + + } + ); + this.primaryKeyJoinColumnSources = new ArrayList( valueSources.size() ); + for ( final RelationalValueSource valueSource : valueSources ) { + primaryKeyJoinColumnSources.add( ColumnSource.class.cast( valueSource ) ) ; + } + } + + @Override + public boolean isCascadeDeleteEnabled() { + return key.getOnDelete() == JaxbOnDeleteAttribute.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return key.getForeignKey(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return key.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegate() { + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( key.getPropertyRef() ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( key.getPropertyRef() ); + } + + @Override + public String getReferencedAttributeName() { + return key.getPropertyRef(); + } + }; + } + + + @Override + public List getPrimaryKeyColumnSources() { + return primaryKeyJoinColumnSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java new file mode 100644 index 0000000000..7186ceecb0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java @@ -0,0 +1,198 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; +import java.util.Map; + +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class KeyAttributeSourceImpl + extends AbstractHbmSourceNode + implements SingularAttributeSource { + private final JaxbKeyPropertyElement keyPropertyElement; + private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + private final HibernateTypeSource typeSource; + private final List valueSources; + + public KeyAttributeSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyPropertyElement keyPropertyElement, + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( mappingDocument ); + this.keyPropertyElement = keyPropertyElement; + this.naturalIdMutability = naturalIdMutability; + this.typeSource = new HibernateTypeSource() { + private final String name = keyPropertyElement.getTypeAttribute() != null + ? keyPropertyElement.getTypeAttribute() + : keyPropertyElement.getType() != null + ? keyPropertyElement.getType().getName() + : null; + private final Map parameters = ( keyPropertyElement.getType() != null ) + ? Helper.extractParameters( keyPropertyElement.getType().getParam() ) + : null; + + @Override + public String getName() { + return name; + } + + @Override + public Map getParameters() { + return parameters; + } + @Override + public Class getJavaType() { + return null; + } + }; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return keyPropertyElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + keyPropertyElement.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return keyPropertyElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + } + + @Override + public String getName() { + return keyPropertyElement.getName(); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return keyPropertyElement.getAccess(); + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.NEVER; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public Nature getNature() { + return Nature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Iterable getMetaAttributeSources() { + return keyPropertyElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java new file mode 100644 index 0000000000..1d31da7aaf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java @@ -0,0 +1,200 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class KeyManyToOneSourceImpl + extends AbstractToOneAttributeSourceImpl + implements SingularAttributeSource { + private final JaxbKeyManyToOneElement keyManyToOneElement; + private final List valueSources; + + public KeyManyToOneSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyManyToOneElement keyManyToOneElement, + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( mappingDocument, naturalIdMutability, null ); + this.keyManyToOneElement = keyManyToOneElement; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return keyManyToOneElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return null; + } + + @Override + public List getColumn() { + return keyManyToOneElement.getColumn(); + } + + @Override + public List getFormula() { + return Collections.emptyList(); + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return false; + } + } + ); + } + + @Override + public String getName() { + return keyManyToOneElement.getName(); + } + + @Override + public String getPropertyAccessorName() { + return keyManyToOneElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_ONE; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + protected boolean requiresImmediateFetch() { + return false; + } + + @Override + protected String getFetchSelectionString() { + return null; + } + + @Override + protected String getLazySelectionString() { + return keyManyToOneElement.getLazy() != null ? + keyManyToOneElement.getLazy().value() : + null; + } + + @Override + protected String getOuterJoinSelectionString() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Iterable getMetaAttributeSources() { + return keyManyToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return keyManyToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return false; + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return ForeignKeyDirection.TO_PARENT; + } + + @Override + public Set getCascadeStyles() { + return Collections.singleton( CascadeStyles.NONE ); + } + + @Override + public String getExplicitForeignKeyName() { + return keyManyToOneElement.getForeignKey(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ListSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ListSourceImpl.java new file mode 100644 index 0000000000..8ad480dc28 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ListSourceImpl.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.AssertionFailure; +import org.hibernate.jaxb.spi.hbm.JaxbListElement; +import org.hibernate.jaxb.spi.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.SequentialPluralAttributeIndexSource; + +/** + * + */ +public class ListSourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + + private final SequentialPluralAttributeIndexSource indexSource; + + /** + * @param sourceMappingDocument + * @param listElement + * @param container + */ + public ListSourceImpl( + MappingDocument sourceMappingDocument, + JaxbListElement listElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, listElement, container ); + JaxbListIndexElement listIndexElement = listElement.getListIndex(); + if ( listIndexElement == null ) { + this.indexSource = new SequentialPluralAttributeIndexSourceImpl( sourceMappingDocument(), listElement.getIndex() ); + } else { + this.indexSource = new SequentialPluralAttributeIndexSourceImpl( sourceMappingDocument(), listIndexElement ); + } + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbListElement getPluralAttributeElement() { + return ( JaxbListElement ) super.getPluralAttributeElement(); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.source.PluralAttributeSource#getNature() + */ + @Override + public Nature getNature() { + return Nature.LIST; + } + + @Override + public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context) { + if ( indexSource == null ) { + throw new AssertionFailure( "Array index source should have been resolved already." ); + } + return indexSource; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/LoadCollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/LoadCollectionBinder.java new file mode 100644 index 0000000000..21db8f9d62 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/LoadCollectionBinder.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.cfg.HbmBinder; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryCollectionReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.jaxb.spi.hbm.JaxbLoadCollectionElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Strong Liu + */ +class LoadCollectionBinder extends AbstractReturnBinder { + LoadCollectionBinder( + final JaxbLoadCollectionElement element, final int elementIndex, final LocalBindingContext context, + final MetadataImplementor metadata) { + super( element, elementIndex, context, metadata ); + } + + @Override + NativeSQLQueryReturn process() { + final String collectionAttribute = element.getRole(); + int dot = collectionAttribute.lastIndexOf( '.' ); + if ( dot == -1 ) { + throw context.makeMappingException( + "Collection attribute for sql query return [alias=" + alias + "] not formatted correctly {OwnerClassName.propertyName}" + ); + } + final String ownerClassName = HbmBinder.getClassName( + collectionAttribute.substring( 0, dot ), context.getMappingDefaults().getPackageName() + ); + final String ownerPropertyName = collectionAttribute.substring( dot + 1 ); + final Map propertyResults = new HashMap(); + processReturnProperties( new ReturnPropertiesCallbackImpl( alias, propertyResults, context ) ); + return new NativeSQLQueryCollectionReturn( + alias, ownerClassName, ownerPropertyName, propertyResults, lockMode + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java new file mode 100644 index 0000000000..18ab297d3f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java @@ -0,0 +1,256 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbFilterElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToManyElement; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.FilterSource; +import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class ManyToManyPluralAttributeElementSourceImpl + extends AbstractPluralAssociationElementSourceImpl + implements ManyToManyPluralAttributeElementSource { + private final JaxbManyToManyElement manyToManyElement; + private final Set cascadeStyles; + + private final List valueSources; + private final FilterSource[] filterSources; + public ManyToManyPluralAttributeElementSourceImpl( + MappingDocument mappingDocument, + final PluralAttributeSource pluralAttributeSource, + final JaxbManyToManyElement manyToManyElement, + String cascadeString) { + super( mappingDocument, pluralAttributeSource ); + this.manyToManyElement = manyToManyElement; + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); + + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return true; + } + + @Override + public String getColumnAttribute() { + return manyToManyElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return manyToManyElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return manyToManyElement.getColumn(); + } + + @Override + public List getFormula() { + return manyToManyElement.getFormula(); + } + } + ); + this.filterSources = buildFilterSources(); + } + + private FilterSource[] buildFilterSources() { + final int size = manyToManyElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = manyToManyElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_MANY; + } + + @Override + public String getReferencedEntityName() { + return StringHelper.isNotEmpty( manyToManyElement.getEntityName() ) + ? manyToManyElement.getEntityName() + : bindingContext().qualifyClassName( manyToManyElement.getClazz() ); + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public String getReferencedEntityAttributeName() { + return manyToManyElement.getPropertyRef(); + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isNotFoundAnException() { + return manyToManyElement.getNotFound() == null || !"ignore".equals( manyToManyElement.getNotFound().value() ); + } + + @Override + public String getExplicitForeignKeyName() { + return manyToManyElement.getForeignKey(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return manyToManyElement.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegateImpl(); + } + + @Override + public boolean isUnique() { + return manyToManyElement.isUnique(); + } + + @Override + public String getWhere() { + return manyToManyElement.getWhere(); + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } + + @Override + public FetchTiming getFetchTiming() { + final String fetchSelection = manyToManyElement.getFetch() != null ? + manyToManyElement.getFetch().value() : + null; + final String lazySelection = manyToManyElement.getLazy() != null + ? manyToManyElement.getLazy().value() + : null; + final String outerJoinSelection = manyToManyElement.getOuterJoin() != null + ? manyToManyElement.getOuterJoin().value() + : null; + + if ( lazySelection == null ) { + if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { + return FetchTiming.IMMEDIATE; + } + else if ( "false".equals( outerJoinSelection ) ) { + return FetchTiming.DELAYED; + } + else { + // default is FetchTiming.IMMEDIATE. + return FetchTiming.IMMEDIATE; + } + } + else if ( "true".equals( lazySelection ) ) { + return FetchTiming.DELAYED; + } + else if ( "false".equals( lazySelection ) ) { + return FetchTiming.IMMEDIATE; + } + // TODO: improve this method to say attribute name. + throw new MappingException( + String.format( + "Unexpected lazy selection [%s] on many-to-many element", + lazySelection + ), + origin() + ); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getOrder() { + return manyToManyElement.getOrderBy(); + } + + public class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + @Override + public String getReferencedAttributeName() { + return manyToManyElement.getPropertyRef(); + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( manyToManyElement.getPropertyRef() ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( manyToManyElement.getPropertyRef() ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java new file mode 100644 index 0000000000..4b22da025d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java @@ -0,0 +1,204 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { + private final JaxbManyToOneElement manyToOneElement; + private final String containingTableName; + private final List valueSources; + + ManyToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbManyToOneElement manyToOneElement, + final String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument, naturalIdMutability, manyToOneElement.getPropertyRef() ); + this.manyToOneElement = manyToOneElement; + this.containingTableName = logicalTableName; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return manyToOneElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return manyToOneElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return manyToOneElement.getColumn(); + } + + @Override + public List getFormula() { + return manyToOneElement.getFormula(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return manyToOneElement.isInsert(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return manyToOneElement.isUpdate(); + } + } + ); + } + + @Override + public String getName() { + return manyToOneElement.getName(); + } + + @Override + public String getPropertyAccessorName() { + return manyToOneElement.getAccess(); + } + + @Override + public boolean isNotFoundAnException() { + return manyToOneElement.getNotFound() == null || !"ignore".equals( manyToOneElement.getNotFound().value() ); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return manyToOneElement.isOptimisticLock(); + } + + @Override + public Set getCascadeStyles() { + return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext() ); + } + + @Override + protected boolean requiresImmediateFetch() { + return false; + } + + @Override + protected String getFetchSelectionString() { + return manyToOneElement.getFetch() != null ? + manyToOneElement.getFetch().value() : + null; + } + + @Override + protected String getLazySelectionString() { + return manyToOneElement.getLazy() != null ? + manyToOneElement.getLazy().value() : + null; + } + + @Override + protected String getOuterJoinSelectionString() { + return manyToOneElement.getOuterJoin() != null ? + manyToOneElement.getOuterJoin().value() : + null; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_ONE; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return manyToOneElement.isInsert(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return manyToOneElement.isUpdate(); + } + + @Override + public boolean areValuesNullableByDefault() { + return ! Helper.getValue( manyToOneElement.isNotNull(), false ); + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Iterable getMetaAttributeSources() { + return manyToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return manyToOneElement.getClazz() != null + ? bindingContext().qualifyClassName( manyToOneElement.getClazz() ) + : manyToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return manyToOneElement.isUnique(); + } + + @Override + public String getExplicitForeignKeyName() { + return manyToOneElement.getForeignKey(); + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return ForeignKeyDirection.TO_PARENT; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapKeySourceImpl.java new file mode 100644 index 0000000000..9d292cab03 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapKeySourceImpl.java @@ -0,0 +1,225 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbIndexElement; +import org.hibernate.jaxb.spi.hbm.JaxbMapKeyElement; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.source.BasicPluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * + */ +public class MapKeySourceImpl extends AbstractHbmSourceNode implements BasicPluralAttributeIndexSource { + private final PluralAttributeIndexBinding.Nature nature; + private final List valueSources; + private final HibernateTypeSource typeSource; + + public MapKeySourceImpl(MappingDocument sourceMappingDocument, final JaxbMapKeyElement mapKey) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return mapKey.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + mapKey.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return mapKey.getColumn(); + } + + @Override + public List getFormula() { + return mapKey.getFormula(); + } + + @Override + public String getFormulaAttribute() { + return mapKey.getFormulaAttribute(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } + ); + this.typeSource = new HibernateTypeSource() { + @Override + public String getName() { + if ( mapKey.getTypeAttribute() != null ) { + return mapKey.getTypeAttribute(); + } + if ( mapKey.getType() != null ) { + return mapKey.getType().getName(); + } + return null; + } + + @Override + public Map getParameters() { + return mapKey.getType() != null + ? Helper.extractParameters( mapKey.getType().getParam() ) + : java.util.Collections.emptyMap(); + } + @Override + public Class getJavaType() { + return null; + } + }; + this.nature = PluralAttributeIndexBinding.Nature.BASIC; + } + + public MapKeySourceImpl(MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( + sourceMappingDocument, + new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + indexElement.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return indexElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } + ); + typeSource = new HibernateTypeSource() { + @Override + public String getName() { + return indexElement.getType(); + } + + @Override + public Map getParameters() { + return java.util.Collections.emptyMap(); + } + + @Override + public Class getJavaType() { + return null; + } + }; + + this.nature = PluralAttributeIndexBinding.Nature.BASIC; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return nature; + } + + @Override + public List getDefaultNamingStrategies() { + final Binder.DefaultNamingStrategy defaultNamingStrategy = + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.columnName( "idx" ); + } + }; + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public boolean isReferencedEntityAttribute() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List relationalValueSources() { + return valueSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapSourceImpl.java new file mode 100644 index 0000000000..71cb97aff6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MapSourceImpl.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.jaxb.spi.hbm.JaxbMapElement; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext; +import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; +import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; + +/** + * + */ +public class MapSourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + + private final PluralAttributeIndexSource indexSource; + + /** + * @param sourceMappingDocument + * @param mapElement + * @param container + */ + public MapSourceImpl( + MappingDocument sourceMappingDocument, + JaxbMapElement mapElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, mapElement, container ); + if ( mapElement.getMapKey() != null ) { + this.indexSource = new MapKeySourceImpl( sourceMappingDocument, mapElement.getMapKey() ); + } + else if ( mapElement.getIndex() != null ) { + this.indexSource = new MapKeySourceImpl( sourceMappingDocument, mapElement.getIndex() ); + } + else if ( mapElement.getCompositeMapKey() != null ) { + this.indexSource = new CompositePluralAttributeIndexSourceImpl( sourceMappingDocument, mapElement.getCompositeMapKey() ); + } + else if ( mapElement.getCompositeIndex() != null ) { + this.indexSource = new CompositePluralAttributeIndexSourceImpl( sourceMappingDocument, mapElement.getCompositeIndex() ); + } + else if ( mapElement.getMapKeyManyToMany() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else if ( mapElement.getIndexManyToMany() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else if ( mapElement.getIndexManyToAny() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else { + throw new AssertionFailure( "No map key found" ); + } + } + + @Override + public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context) { + if ( indexSource == null ) { + throw new NotYetImplementedException( "Plural attribute index source resolution not implemented yet." ); + + } + return indexSource; + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbMapElement getPluralAttributeElement() { + return ( JaxbMapElement ) super.getPluralAttributeElement(); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.source.PluralAttributeSource#getNature() + */ + @Override + public Nature getNature() { + return Nature.MAP; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MappingDocument.java similarity index 81% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MappingDocument.java index b9d8cb609b..1d92bee951 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/MappingDocument.java @@ -21,22 +21,24 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.internal.OverriddenMappingDefaults; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbFetchProfileElement; +import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.internal.source.OverriddenMappingDefaults; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.source.MappingDefaults; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; import org.hibernate.service.ServiceRegistry; /** @@ -84,11 +86,12 @@ public class MappingDocument { hbmJaxbRoot.getRoot().getCatalog(), null, null, + null, hbmJaxbRoot.getRoot().getDefaultCascade(), hbmJaxbRoot.getRoot().getDefaultAccess(), hbmJaxbRoot.getRoot().isDefaultLazy() ); - if ( hbmJaxbRoot.getRoot().getMeta() == null || hbmJaxbRoot.getRoot().getMeta().isEmpty() ) { + if ( CollectionHelper.isEmpty( hbmJaxbRoot.getRoot().getMeta() ) ) { this.metaAttributeContext = new MetaAttributeContext( metadata.getGlobalMetaAttributeContext() ); } else { @@ -169,5 +172,15 @@ public class MappingDocument { public void processFetchProfiles(List fetchProfiles, String containingEntityName) { // todo : this really needs to not be part of the context } + + @Override + public MappingException makeMappingException(String message) { + return new MappingException( message, getOrigin() ); + } + + @Override + public MappingException makeMappingException(String message, Exception cause) { + return new MappingException( message, cause, getOrigin() ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/NamedQueryBindingHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/NamedQueryBindingHelper.java new file mode 100644 index 0000000000..537e2b0c8e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/NamedQueryBindingHelper.java @@ -0,0 +1,212 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.hbm.JaxbLoadCollectionElement; +import org.hibernate.jaxb.spi.hbm.JaxbQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbSqlQueryElement; +import org.hibernate.metamodel.internal.source.hbm.parser.BasicQueryElementContentParser; +import org.hibernate.metamodel.internal.source.hbm.parser.SQLQueryElementContentParser; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * Helper class used to bind named query elements. + * + * @author Brett Meyer + * @author Strong Liu + */ +public class NamedQueryBindingHelper { + + /** + * Helper method used to bind {@code } element. + * + * @param queryElement The {@code } element. + * @param metadata The {@link org.hibernate.metamodel.Metadata} which this named query will be added to. + */ + public static void bindNamedQuery( + final JaxbQueryElement queryElement, + final MetadataImplementor metadata) { + final NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder(); + final BasicQueryElementContentParser parser = new BasicQueryElementContentParser(); + parser.parse( builder, queryElement ); + metadata.addNamedQuery( builder.createNamedQueryDefinition() ); + } + + public static void bindNamedSQLQuery( + final JaxbSqlQueryElement queryElement, + final LocalBindingContext bindingContext, + final MetadataImplementor metadata) { + final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder(); + final SQLQueryElementContentParser parser = new SQLQueryElementContentParser(); + + parser.parse( builder, queryElement ); + + final boolean callable = queryElement.isCallable(); + final String resultSetRef = queryElement.getResultsetRef(); + //TODO: check if the refereneced result set mapping definition exist or not? + builder.setCallable( callable ).setResultSetRef( resultSetRef ); + + NamedSQLQueryDefinition namedQuery; + //query returns are defined in the element. + if ( StringHelper.isNotEmpty( resultSetRef ) ) { + namedQuery = builder.createNamedQueryDefinition(); + } + else { + namedQuery = parser.buildQueryReturns( queryElement.getName(),builder, bindingContext, metadata ); + } + metadata.addNamedNativeQuery( namedQuery ); + } + + + + private static Map bindPropertyResults( + String alias, JaxbLoadCollectionElement element, + EntityBinding entityBinding) { + List returnPropertyElements + = element.getReturnProperty(); + List properties + = new ArrayList(); + List propertyNames = new ArrayList(); + HashMap> propertyResults = new HashMap>(); + for ( JaxbReturnPropertyElement propertyElement : returnPropertyElements ) { + String name = propertyElement.getName(); + if ( entityBinding == null || name.indexOf( '.' ) == -1 ) { + properties.add( propertyElement ); + propertyNames.add( name ); + } + else { + /** + * Reorder properties + * 1. get the parent property + * 2. list all the properties following the expected one in the parent property + * 3. calculate the lowest index and insert the property + */ + if ( entityBinding == null ) { + throw new org.hibernate.MappingException( + "dotted notation in or not yet supported" + ); + } + int dotIndex = name.lastIndexOf( '.' ); + String reducedName = name.substring( 0, dotIndex ); + AttributeBinding value = null;// getRecursiveAttributeBinding(entityBinding, reducedName ); + Iterable parentPropIter; + if ( CompositeAttributeBinding.class.isInstance( value ) ) { + CompositeAttributeBinding comp + = (CompositeAttributeBinding) value; + parentPropIter = comp.attributeBindings(); + } + else if ( SingularAssociationAttributeBinding.class.isInstance( + value + ) ) { + SingularAssociationAttributeBinding toOne + = SingularAssociationAttributeBinding.class.cast( + value + ); + EntityBinding referencedEntityBinding + = toOne.getReferencedEntityBinding(); + SingularAttributeBinding referencedAttributeBinding + = toOne.getReferencedAttributeBinding(); + try { + parentPropIter = CompositeAttributeBinding.class.cast( + referencedAttributeBinding + ).attributeBindings(); + } + catch ( ClassCastException e ) { + throw new org.hibernate.MappingException( + "dotted notation reference neither a component nor a many/one to one", e + ); + } + } + else { + throw new org.hibernate.MappingException( + "dotted notation reference neither a component nor a many/one to one" + ); + } + boolean hasFollowers = false; + List followers = new ArrayList(); + for ( AttributeBinding binding : parentPropIter ) { + String currentPropertyName + = binding.getAttribute().getName(); + String currentName = reducedName + '.' + + currentPropertyName; + if ( hasFollowers ) { + followers.add( currentName ); + } + if ( name.equals( currentName ) ) { + hasFollowers = true; + } + } + + int index = propertyNames.size(); + int followersSize = followers.size(); + for ( int loop = 0; loop < followersSize; loop++ ) { + String follower = followers.get( loop ); + int currentIndex = getIndexOfFirstMatchingProperty( + propertyNames, follower + ); + index = currentIndex != -1 && currentIndex < index + ? currentIndex : index; + } + propertyNames.add( index, name ); + properties.add( index, propertyElement ); + } + } + + Map results = new HashMap( propertyResults.size() ); + return results; + } + + + + private static int getIndexOfFirstMatchingProperty(List propertyNames, + String follower) { + int propertySize = propertyNames.size(); + for ( int propIndex = 0; propIndex < propertySize; propIndex++ ) { + if ( ( (String) propertyNames.get( propIndex ) ).startsWith( + follower + ) ) { + return propIndex; + } + } + return -1; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToManyPluralAttributeElementSourceImpl.java similarity index 60% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToManyPluralAttributeElementSourceImpl.java index 8176952c40..a5914c01dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToManyPluralAttributeElementSourceImpl.java @@ -21,38 +21,45 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToManyElement; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.OneToManyPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; +import org.hibernate.jaxb.spi.hbm.JaxbOneToManyElement; +import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource; +import org.hibernate.metamodel.spi.source.PluralAttributeSource; /** * @author Steve Ebersole */ -public class OneToManyPluralAttributeElementSourceImpl implements OneToManyPluralAttributeElementSource { +public class OneToManyPluralAttributeElementSourceImpl + extends AbstractPluralAssociationElementSourceImpl + implements OneToManyPluralAttributeElementSource { private final JaxbOneToManyElement oneToManyElement; - private final LocalBindingContext bindingContext; + private final Set cascadeStyles; public OneToManyPluralAttributeElementSourceImpl( - JaxbOneToManyElement oneToManyElement, - LocalBindingContext bindingContext) { + MappingDocument mappingDocument, + final PluralAttributeSource pluralAttributeSource, + final JaxbOneToManyElement oneToManyElement, + String cascadeString) { + super( mappingDocument, pluralAttributeSource ); this.oneToManyElement = oneToManyElement; - this.bindingContext = bindingContext; + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); } @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.ONE_TO_MANY; + public Nature getNature() { + return Nature.ONE_TO_MANY; } @Override public String getReferencedEntityName() { return StringHelper.isNotEmpty( oneToManyElement.getEntityName() ) ? oneToManyElement.getEntityName() - : bindingContext.qualifyClassName( oneToManyElement.getClazz() ); + : bindingContext().qualifyClassName( oneToManyElement.getClazz() ); } @Override @@ -60,4 +67,9 @@ public class OneToManyPluralAttributeElementSourceImpl implements OneToManyPlura return oneToManyElement.getNotFound() == null || ! "ignore".equals( oneToManyElement.getNotFound().value() ); } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java new file mode 100644 index 0000000000..5c797677c7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java @@ -0,0 +1,199 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { + private final JaxbOneToOneElement oneToOneElement; + private final List valueSources; + private final String containingTableName; + + OneToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbOneToOneElement oneToOneElement, + final String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument, naturalIdMutability, oneToOneElement.getPropertyRef() ); + this.oneToOneElement = oneToOneElement; + this.containingTableName = logicalTableName; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + // Not applicable to one-to-one + return null; + } + + @Override + public String getFormulaAttribute() { + return oneToOneElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + // Not applicable to one-to-one + return null; + } + + @Override + public List getFormula() { + return oneToOneElement.getFormula(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return false; + } + } + ); + } + + @Override + public String getName() { + return oneToOneElement.getName(); + } + + @Override + public String getPropertyAccessorName() { + return oneToOneElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public Set getCascadeStyles() { + return Helper.interpretCascadeStyles( oneToOneElement.getCascade(), bindingContext() ); + } + + @Override + protected String getFetchSelectionString() { + return oneToOneElement.getFetch()!=null? oneToOneElement.getFetch().value() : null; + } + + @Override + protected String getLazySelectionString() { + return oneToOneElement.getLazy()!=null? oneToOneElement.getLazy().value() : null; + } + + @Override + protected String getOuterJoinSelectionString() { + return oneToOneElement.getOuterJoin()!=null? oneToOneElement.getOuterJoin().value() : null; + } + + @Override + public Nature getNature() { + return Nature.ONE_TO_ONE; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + protected boolean requiresImmediateFetch() { + return !oneToOneElement.isConstrained(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Iterable getMetaAttributeSources() { + return oneToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return oneToOneElement.getClazz() != null + ? bindingContext().qualifyClassName( oneToOneElement.getClazz() ) + : oneToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return true; + } + + @Override + public String getExplicitForeignKeyName() { + return oneToOneElement.getForeignKey(); + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return oneToOneElement.isConstrained() ? ForeignKeyDirection.FROM_PARENT : ForeignKeyDirection.TO_PARENT; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java similarity index 51% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java index 1def9cc4ab..3ca2b01bdf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java @@ -21,36 +21,39 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbKeyElement; -import org.hibernate.metamodel.relational.ForeignKey; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.PluralAttributeKeySource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyElement; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Steve Ebersole */ -public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { +public class PluralAttributeKeySourceImpl + extends AbstractHbmSourceNode + implements PluralAttributeKeySource { private final JaxbKeyElement keyElement; private final List valueSources; public PluralAttributeKeySourceImpl( + MappingDocument mappingDocument, final JaxbKeyElement keyElement, final AttributeSourceContainer container) { + super( mappingDocument ); this.keyElement = keyElement; this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - @Override public boolean isIncludedInInsertByDefault() { return true; @@ -58,7 +61,7 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { @Override public boolean isIncludedInUpdateByDefault() { - return Helper.getBooleanValue( keyElement.isUpdate(), true ); + return Helper.getValue( keyElement.isUpdate(), true ); } @Override @@ -67,38 +70,69 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { } @Override - public String getFormulaAttribute() { - return null; + public List getColumn() { + return keyElement.getColumn(); } @Override - public List getColumnOrFormulaElements() { - return keyElement.getColumn(); + public boolean isForceNotNull() { + return Helper.getValue( keyElement.isNotNull(), false ); } - }, - container.getLocalBindingContext() + } ); } - @Override - public List getValueSources() { - return valueSources; - } - @Override public String getExplicitForeignKeyName() { return keyElement.getForeignKey(); } + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return keyElement.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegate() { + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( keyElement.getPropertyRef() ); + } + + @Override + public String getReferencedAttributeName() { + return keyElement.getPropertyRef(); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( keyElement.getPropertyRef() ); + } + }; + } + @Override public ForeignKey.ReferentialAction getOnDeleteAction() { - return "cascade".equals( keyElement.getOnDelete() ) + return "cascade".equals( keyElement.getOnDelete().value() ) ? ForeignKey.ReferentialAction.CASCADE : ForeignKey.ReferentialAction.NO_ACTION; } @Override - public String getReferencedEntityAttributeName() { - return keyElement.getPropertyRef(); + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PropertyAttributeSourceImpl.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PropertyAttributeSourceImpl.java index 815cad8548..0cb03bdf3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PropertyAttributeSourceImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,33 +21,41 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbPropertyElement; import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.SizeSource; /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class PropertyAttributeSourceImpl implements SingularAttributeSource { +class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements SingularAttributeSource { private final JaxbPropertyElement propertyElement; - private final ExplicitHibernateTypeSource typeSource; + private final HibernateTypeSource typeSource; private final List valueSources; + private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability; + private final String containingTableName; - PropertyAttributeSourceImpl(final JaxbPropertyElement propertyElement, LocalBindingContext bindingContext) { + PropertyAttributeSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbPropertyElement propertyElement, + final String logicalTableName, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument ); this.propertyElement = propertyElement; - this.typeSource = new ExplicitHibernateTypeSource() { + this.typeSource = new HibernateTypeSource() { private final String name = propertyElement.getTypeAttribute() != null ? propertyElement.getTypeAttribute() : propertyElement.getType() != null @@ -66,42 +74,63 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource { public Map getParameters() { return parameters; } + @Override + public Class getJavaType() { + return null; + } }; + this.containingTableName = logicalTableName; this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { @Override public String getColumnAttribute() { - return propertyElement.getColumn(); + return propertyElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + // TODO: propertyElement.getPrecision() and getScale() return String, + // but should return int + return Helper.createSizeSourceIfMapped( + propertyElement.getLength(), + propertyElement.getPrecision() == null ? null : Integer.valueOf( propertyElement.getPrecision() ), + propertyElement.getScale() == null ? null : Integer.valueOf( propertyElement.getScale() ) + ); } @Override public String getFormulaAttribute() { + return propertyElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return propertyElement.getColumn(); + } + + @Override + public List getFormula() { return propertyElement.getFormula(); } - @Override - public List getColumnOrFormulaElements() { - return propertyElement.getColumnOrFormula(); - } - @Override public String getContainingTableName() { - // todo : need to implement this... - return null; + return logicalTableName; } @Override public boolean isIncludedInInsertByDefault() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); + return Helper.getValue( propertyElement.isInsert(), true ); } @Override public boolean isIncludedInUpdateByDefault() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); + return Helper.getValue( propertyElement.isUpdate(), true ); } - }, - bindingContext + } ); + this.naturalIdMutability = naturalIdMutability; } @Override @@ -110,7 +139,7 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource { } @Override - public ExplicitHibernateTypeSource getTypeInformation() { + public HibernateTypeSource getTypeInformation() { return typeSource; } @@ -119,34 +148,29 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource { return propertyElement.getAccess(); } - @Override - public boolean isInsertable() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); - } - - @Override - public boolean isUpdatable() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); - } - @Override public PropertyGeneration getGeneration() { - return PropertyGeneration.parse( propertyElement.getGenerated() ); + return PropertyGeneration.parse( propertyElement.getGenerated().value() ); } @Override public boolean isLazy() { - return Helper.getBooleanValue( propertyElement.isLazy(), false ); + return Helper.getValue( propertyElement.isLazy(), false ); + } + + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; } @Override public boolean isIncludedInOptimisticLocking() { - return Helper.getBooleanValue( propertyElement.isOptimisticLock(), true ); + return Helper.getValue( propertyElement.isOptimisticLock(), true ); } @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; + public Nature getNature() { + return Nature.BASIC; } @Override @@ -156,17 +180,22 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource { @Override public boolean areValuesIncludedInInsertByDefault() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); + return Helper.getValue( propertyElement.isInsert(), true ); } @Override public boolean areValuesIncludedInUpdateByDefault() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); + return Helper.getValue( propertyElement.isUpdate(), true ); } @Override public boolean areValuesNullableByDefault() { - return ! Helper.getBooleanValue( propertyElement.isNotNull(), false ); + return ! Helper.getValue( propertyElement.isNotNull(), false ); + } + + @Override + public String getContainingTableName() { + return containingTableName; } @Override @@ -180,7 +209,7 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource { } @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( propertyElement.getMeta() ); + public Iterable getMetaAttributeSources() { + return propertyElement.getMeta(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ResultSetMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ResultSetMappingBinder.java new file mode 100644 index 0000000000..fd81cd04e9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ResultSetMappingBinder.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbLoadCollectionElement; +import org.hibernate.jaxb.spi.hbm.JaxbResultsetElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnJoinElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnScalarElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.LocalBindingContext; +import org.hibernate.type.Type; + +public class ResultSetMappingBinder { + public static ResultSetMappingDefinition buildResultSetMappingDefinitions( + final JaxbResultsetElement element, final LocalBindingContext bindingContext, + final MetadataImplementor metadata) { + final ResultSetMappingDefinition definition = new ResultSetMappingDefinition( element.getName() ); + int cnt = 0; + for ( final JaxbReturnScalarElement r : element.getReturnScalar() ) { + String column = r.getColumn(); + String typeFromXML = r.getType(); + Type type = StringHelper.isNotEmpty( typeFromXML ) ? metadata.getTypeResolver() + .heuristicType( typeFromXML ) : null; + definition.addQueryReturn( new NativeSQLQueryScalarReturn( column, type ) ); + } + for ( final JaxbReturnElement r : element.getReturn() ) { + definition.addQueryReturn( new ReturnBinder( r, cnt++, bindingContext, metadata ).process() ); + } + for ( final JaxbReturnJoinElement r : element.getReturnJoin() ) { + definition.addQueryReturn( new ReturnJoinBinder( r, cnt++, bindingContext, metadata ).process() ); + } + for ( final JaxbLoadCollectionElement r : element.getLoadCollection() ) { + definition.addQueryReturn( new LoadCollectionBinder( r, cnt++, bindingContext, metadata ).process() ); + } + + return definition; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnBinder.java new file mode 100644 index 0000000000..53c32a92c8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnBinder.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbReturnElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnPropertyElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Strong Liu + */ +class ReturnBinder extends AbstractReturnBinder { + ReturnBinder( + final JaxbReturnElement element, final int elementIndex, final LocalBindingContext context, + final MetadataImplementor metadata) { + super( element, elementIndex, context, metadata ); + } + + @Override + NativeSQLQueryReturn process() { + final String clazz = element.getClazz(); + String entityName = element.getEntityName(); + if ( StringHelper.isEmpty( clazz ) && StringHelper.isEmpty( entityName ) ) { + throw context.makeMappingException( + " must specify either a class or entity-name" + ); + } + entityName = StringHelper.isNotEmpty( entityName ) ? entityName : context.qualifyClassName( clazz ); + final EntityBinding entityBinding = metadata.getEntityBinding( entityName ); + // TODO throw exception here?? + // if ( entityBinding == null ) { + // throw bindingContext.makeMappingException( "Can't locate entitybinding" ); + // } + + final Map propertyResults = new HashMap(); + bindDiscriminatorColumn( propertyResults ); + processReturnProperties( new ReturnPropertiesCallbackImpl2( alias, propertyResults, context ) ); + + return new NativeSQLQueryRootReturn( + alias, entityName, propertyResults, lockMode + ); + } + + + private void bindDiscriminatorColumn(final Map propertyResults) { + final JaxbReturnElement.JaxbReturnDiscriminator discriminator = element.getReturnDiscriminator(); + if ( discriminator != null && StringHelper.isNotEmpty( discriminator.getColumn() ) ) { + String discriminatorColumn = StringHelper.unquote( discriminator.getColumn() ); + propertyResults.put( "class", new String[] { discriminatorColumn } ); + } + } + + private static class ReturnPropertiesCallbackImpl2 implements ReturnPropertiesCallback { + private final LocalBindingContext bindingContext; + private final String alias; + private final Map propertyResults; + + private ReturnPropertiesCallbackImpl2( + final String alias, final Map propertyResults, + final LocalBindingContext bindingContext) { + this.alias = alias; + this.bindingContext = bindingContext; + this.propertyResults = propertyResults; + } + + @Override + public void process(final JaxbReturnPropertyElement propertyElement) { + final String name = propertyElement.getName(); + if ( "class".equals( name ) ) { + throw bindingContext.makeMappingException( + "class is not a valid property name to use in a , use instead" + ); + } + if ( propertyResults.containsKey( name ) ) { + throw bindingContext.makeMappingException( + "duplicate return-property for property " + name + " on alias " + alias + ); + } + final List returnColumnNames = getResultColumns( propertyElement, bindingContext ); + + if ( returnColumnNames.isEmpty() ) { + throw bindingContext.makeMappingException( + "return-property for alias " + alias + " must specify at least one column or return-column name" + ); + } + + propertyResults.put( name, returnColumnNames.toArray( new String[returnColumnNames.size()] ) ); + } + + private static List getResultColumns( + final JaxbReturnPropertyElement propertyresult, final LocalBindingContext context) { + List allResultColumns = new ArrayList(); + if ( propertyresult.getColumn() != null ) { + String column = context.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( propertyresult.getColumn() ); + allResultColumns.add( column ); + } + for ( JaxbReturnPropertyElement.JaxbReturnColumn returnColumn : propertyresult.getReturnColumn() ) { + if ( returnColumn.getName() != null ) { + String column = context.getMetadataImplementor() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( returnColumn.getName() ); + + allResultColumns.add( column ); + } + } + return allResultColumns; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnJoinBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnJoinBinder.java new file mode 100644 index 0000000000..4b52185eda --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ReturnJoinBinder.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.jaxb.spi.hbm.JaxbReturnJoinElement; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Strong Liu + */ +class ReturnJoinBinder extends AbstractReturnBinder { + ReturnJoinBinder( + final JaxbReturnJoinElement element, final int elementIndex, final LocalBindingContext context, + final MetadataImplementor metadata) { + super( element, elementIndex, context, metadata ); + } + + @Override + NativeSQLQueryReturn process() { + final String roleAttribute = element.getProperty(); + int dot = roleAttribute.lastIndexOf( '.' ); + if ( dot == -1 ) { + throw context.makeMappingException( + "Role attribute for sql query return " + "[alias=" + alias + "] not formatted correctly " + "{owningAlias.propertyName}" + ); + } + final String roleOwnerAlias = roleAttribute.substring( 0, dot ); + final String roleProperty = roleAttribute.substring( dot + 1 ); + final Map propertyResults = new HashMap(); + processReturnProperties( new ReturnPropertiesCallbackImpl( alias, propertyResults, context ) ); + return new NativeSQLQueryJoinReturn( + alias, roleOwnerAlias, roleProperty, propertyResults, lockMode + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java new file mode 100644 index 0000000000..0bddd40ae2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java @@ -0,0 +1,593 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.TruthValue; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbClassElement; +import org.hibernate.jaxb.spi.hbm.JaxbCompositeIdElement; +import org.hibernate.jaxb.spi.hbm.JaxbDiscriminatorElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement; +import org.hibernate.jaxb.spi.hbm.JaxbMultiTenancyElement; +import org.hibernate.jaxb.spi.hbm.JaxbNaturalIdElement; +import org.hibernate.jaxb.spi.hbm.JaxbPolymorphismAttribute; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.AttributeSource; +import org.hibernate.metamodel.spi.source.ComponentAttributeSource; +import org.hibernate.metamodel.spi.source.DiscriminatorSource; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.MultiTenancySource; +import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.SizeSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements RootEntitySource { + private final TableSpecificationSource primaryTable; + private final Caching caching; + private final ValueHolder naturalIdCachingHolder; + + protected RootEntitySourceImpl( + MappingDocument sourceMappingDocument, + JaxbClassElement entityElement) { + super( sourceMappingDocument, entityElement ); + this.primaryTable = Helper.createTableSource( sourceMappingDocument(), entityElement, this ); + this.caching = Helper.createCaching( entityElement().getCache(), getEntityName() ); + this.naturalIdCachingHolder = Helper.createNaturalIdCachingHolder( + entityElement.getNaturalIdCache(), + getEntityName(), + caching + ); + afterInstantiation(); + } + + + + @Override + protected JaxbClassElement entityElement() { + return (JaxbClassElement) super.entityElement(); + } + + @Override + public IdentifierSource getIdentifierSource() { + if ( entityElement().getId() == null && entityElement().getCompositeId() == null ) { + throw makeMappingException( + String.format( "Entity [%s] did not define an identifier", getEntityName() ) + ); + } + + if ( entityElement().getId() != null ) { + return new SimpleIdentifierSourceImpl(); + } + else { + // if we get here, we should have a composite identifier. Just need to determine if it is aggregated, or not... + if ( StringHelper.isEmpty( entityElement().getCompositeId().getName() ) ) { + if ( entityElement().getCompositeId().isMapped() && + StringHelper.isEmpty( entityElement().getCompositeId().getClazz() ) ) { + throw makeMappingException( "mapped composite identifier must name component class to use." ); + } + return new NonAggregatedCompositeIdentifierSourceImpl(); + } + else { + if ( entityElement().getCompositeId().isMapped() ) { + throw makeMappingException("cannot combine mapped=\"true\" with specified name"); + } + return new AggregatedCompositeIdentifierSourceImpl(); + } + } + } + + @Override + public VersionAttributeSource getVersioningAttributeSource() { + if ( entityElement().getVersion() != null ) { + return new VersionAttributeSourceImpl( + sourceMappingDocument(), + entityElement().getVersion() + ); + } + else if ( entityElement().getTimestamp() != null ) { + return new TimestampAttributeSourceImpl( + sourceMappingDocument(), + entityElement().getTimestamp() + ); + } + return null; + } + + @Override + protected List buildAttributeSources(List attributeSources) { + final JaxbNaturalIdElement naturalId = entityElement().getNaturalId(); + if ( naturalId != null ) { + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = naturalId.isMutable() ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE; + processPropertyAttributes( attributeSources, naturalId.getProperty(), null, naturalIdMutability ); + processManyToOneAttributes( attributeSources, naturalId.getManyToOne(), null, naturalIdMutability ); + processComponentAttributes( attributeSources, naturalId.getComponent(), null, naturalIdMutability ); + processDynamicComponentAttributes( attributeSources, naturalId.getDynamicComponent(), null, naturalIdMutability ); + processAnyAttributes( attributeSources, naturalId.getAny(), null, naturalIdMutability ); + } + return super.buildAttributeSources( attributeSources ); + } + + @Override + public EntityMode getEntityMode() { + return determineEntityMode(); + } + + @Override + public boolean isMutable() { + return entityElement().isMutable(); + } + + @Override + public boolean isExplicitPolymorphism() { + return JaxbPolymorphismAttribute.EXPLICIT == entityElement().getPolymorphism(); + } + + @Override + public String getWhere() { + return entityElement().getWhere(); + } + + @Override + public String getRowId() { + return entityElement().getRowid(); + } + + @Override + public OptimisticLockStyle getOptimisticLockStyle() { + final String optimisticLockModeString = Helper.getValue( entityElement().getOptimisticLock().value(), "version" ); + try { + return OptimisticLockStyle.valueOf( optimisticLockModeString.toUpperCase() ); + } + catch ( Exception e ) { + throw new MappingException( + "Unknown optimistic-lock value : " + optimisticLockModeString, + sourceMappingDocument().getOrigin() + ); + } + } + + @Override + public Caching getCaching() { + return caching; + } + + @Override + public Caching getNaturalIdCaching() { + return naturalIdCachingHolder.getValue(); + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public String getDiscriminatorMatchValue() { + return entityElement().getDiscriminatorValue(); + } + + @Override + public DiscriminatorSource getDiscriminatorSource() { + final JaxbDiscriminatorElement discriminatorElement = entityElement().getDiscriminator(); + if ( discriminatorElement == null ) { + return null; + } + + return new DiscriminatorSource() { + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + SizeSource sizeSource = Helper.createSizeSourceIfMapped( discriminatorElement.getLength(), null, null ); + if ( StringHelper.isNotEmpty( discriminatorElement.getColumnAttribute() ) || sizeSource != null ) { + return new ColumnAttributeSourceImpl( + sourceMappingDocument(), + null, // root table + discriminatorElement.getColumnAttribute(), + sizeSource, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isNotNull() ? TruthValue.FALSE : TruthValue.TRUE + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormulaAttribute() ) ) { + return new FormulaImpl( + sourceMappingDocument(), + null, + discriminatorElement.getFormulaAttribute() + ); + } + else if ( discriminatorElement.getColumn() != null ) { + return new ColumnSourceImpl( + sourceMappingDocument(), + null, // root table + discriminatorElement.getColumn(), + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormula() ) ) { + return new FormulaImpl( + sourceMappingDocument(), + null, + discriminatorElement.getFormula() + ); + } + else { + throw new MappingException( "could not determine source of discriminator mapping", getOrigin() ); + } + } + + @Override + public String getExplicitHibernateTypeName() { + return discriminatorElement.getType(); + } + + @Override + public boolean isForced() { + return discriminatorElement.isForce(); + } + + @Override + public boolean isInserted() { + return discriminatorElement.isInsert(); + } + }; + } + + @Override + public MultiTenancySource getMultiTenancySource() { + final JaxbMultiTenancyElement jaxbMultiTenancy = entityElement().getMultiTenancy(); + if ( jaxbMultiTenancy == null ) { + return null; + } + + return new MultiTenancySource() { + @Override + public RelationalValueSource getRelationalValueSource() { + + if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getColumnAttribute() ) ) { + return new ColumnAttributeSourceImpl( + sourceMappingDocument(), + null, // root table + jaxbMultiTenancy.getColumnAttribute(), + null, + TruthValue.TRUE, + TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getFormulaAttribute() ) ) { + return new FormulaImpl( + sourceMappingDocument(), + null, + jaxbMultiTenancy.getFormulaAttribute() + ); + } + else if ( jaxbMultiTenancy.getColumn() != null ) { + return new ColumnSourceImpl( + sourceMappingDocument(), + null, // root table + jaxbMultiTenancy.getColumn(), + TruthValue.TRUE, + TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getFormula() ) ) { + return new FormulaImpl( + sourceMappingDocument(), + null, + jaxbMultiTenancy.getFormula() + ); + } + else { + return null; + } + } + + @Override + public boolean isShared() { + return jaxbMultiTenancy.isShared(); + } + + @Override + public boolean bindAsParameter() { + return jaxbMultiTenancy.isBindAsParam(); + } + }; + } + + private class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { + @Override + public SingularAttributeSource getIdentifierAttributeSource() { + return new SingularIdentifierAttributeSourceImpl( + sourceMappingDocument(), + entityElement().getId() + ); + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getId().getGenerator() != null ) { + final String generatorName = entityElement().getId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataImplementor() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getId().getUnsavedValue(); + } + + @Override + public Iterable getMetaAttributeSources() { + return entityElement().getId().getMeta(); + } + } + + private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource { + private final CompositeIdentifierComponentAttributeSourceImpl componentAttributeSource + = new CompositeIdentifierComponentAttributeSourceImpl(); + + @Override + public ComponentAttributeSource getIdentifierAttributeSource() { + return componentAttributeSource; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getCompositeId().getGenerator() != null ) { + final String generatorName = entityElement().getCompositeId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataImplementor() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getCompositeId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getCompositeId().getUnsavedValue().value(); + } + + @Override + public Iterable getMetaAttributeSources() { + return entityElement().getId().getMeta(); + } + } + + private class CompositeIdentifierComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl { + protected CompositeIdentifierComponentAttributeSourceImpl() { + super( + RootEntitySourceImpl.this.sourceMappingDocument(), + entityElement().getCompositeId(), + RootEntitySourceImpl.this, + null, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID + ); + } + + protected JaxbCompositeIdElement compositeIdElement() { + return (JaxbCompositeIdElement) componentSourceElement(); + } + + @Override + protected List buildAttributeSources() { + List attributeSources = new ArrayList(); + final JaxbCompositeIdElement compositeId = entityElement().getCompositeId(); + final List list = compositeId.getKeyPropertyOrKeyManyToOne(); + for ( final Object obj : list ) { + if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) { + JaxbKeyPropertyElement key = JaxbKeyPropertyElement.class.cast( obj ); + attributeSources.add( new IdentifierKeyAttributeSourceImpl( sourceMappingDocument(), key ) ); + } + if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) { + JaxbKeyManyToOneElement key = JaxbKeyManyToOneElement.class.cast( obj ); + attributeSources.add( new IdentifierKeyManyToOneSourceImpl( sourceMappingDocument(), key ) ); + } + } + return attributeSources; + } + + + @Override + public String getParentReferenceAttributeName() { + // composite-id cannot name parent + return null; + } + + @Override + public String getExplicitTuplizerClassName() { + // composite-id cannot name tuplizer + return null; + } + + @Override + public PropertyGeneration getGeneration() { + // identifiers have implicit generation + return null; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public List relationalValueSources() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + } + + private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource { + @Override + public Class getLookupIdClass() { + return StringHelper.isEmpty( entityElement().getCompositeId().getClazz() ) ? + null : + bindingContext().locateClassByName( + bindingContext().qualifyClassName( entityElement().getCompositeId().getClazz() ) + ); + } + + @Override + public String getIdClassPropertyAccessorName() { + return null; + } + + @Override + public List getAttributeSourcesMakingUpIdentifier() { + final List attributeSources = new ArrayList(); + final JaxbCompositeIdElement compositeId = entityElement().getCompositeId(); + final List list = compositeId.getKeyPropertyOrKeyManyToOne(); + for ( final Object obj : list ) { + if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) { + JaxbKeyPropertyElement key = JaxbKeyPropertyElement.class.cast( obj ); + attributeSources.add( new IdentifierKeyAttributeSourceImpl( sourceMappingDocument(), key ) ); + } + if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) { + JaxbKeyManyToOneElement key = JaxbKeyManyToOneElement.class.cast( obj ); + attributeSources.add( new IdentifierKeyManyToOneSourceImpl( sourceMappingDocument(), key ) ); + } + } + + return attributeSources; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getCompositeId().getGenerator() != null ) { + final String generatorName = entityElement().getCompositeId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataImplementor() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getCompositeId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getCompositeId().getUnsavedValue().value(); + } + + @Override + public Iterable getMetaAttributeSources() { + return entityElement().getCompositeId().getMeta(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java new file mode 100644 index 0000000000..14702fe9ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java @@ -0,0 +1,193 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbFetchStyleAttribute; +import org.hibernate.jaxb.spi.hbm.JaxbJoinElement; +import org.hibernate.jaxb.spi.hbm.JaxbOnDeleteAttribute; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.InLineViewSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SecondaryTableSource; +import org.hibernate.metamodel.spi.source.TableSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; + +/** + * @author Steve Ebersole + */ +class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements SecondaryTableSource { + private final JaxbJoinElement joinElement; + private final TableSpecificationSource joinTable; + private final List columnSources; + private final JoinColumnResolutionDelegate fkJoinColumnResolutionDelegate; + + @SuppressWarnings("unchecked") + public SecondaryTableSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbJoinElement joinElement, + Helper.InLineViewNameInferrer inLineViewNameInferrer) { + super( sourceMappingDocument ); + this.joinElement = joinElement; + this.joinTable = Helper.createTableSource( sourceMappingDocument(), joinElement, inLineViewNameInferrer ); + + // the cast is ok here because the adapter should never be returning formulas since the schema does not allow it + this.columnSources = extractColumnSources(); + + fkJoinColumnResolutionDelegate = joinElement.getKey().getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegateImpl( joinElement ); + } + + private List extractColumnSources() { + final List columnSources = new ArrayList(); + final List valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getContainingTableName() { + return joinElement.getTable(); + } + + @Override + public String getColumnAttribute() { + return joinElement.getKey().getColumnAttribute(); + } + + @Override + public List getColumn() { + return joinElement.getKey().getColumn(); + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + for ( RelationalValueSource valueSource : valueSources ) { + columnSources.add( (ColumnSource) valueSource ); + } + return columnSources; + } + + @Override + public TableSpecificationSource getTableSource() { + return joinTable; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + @Override + public String getComment() { + return joinElement.getComment(); + } + + @Override + public FetchStyle getFetchStyle() { + return joinElement.getFetch() == JaxbFetchStyleAttribute.JOIN ? + FetchStyle.JOIN : + FetchStyle.SELECT; + } + + @Override + public boolean isInverse() { + return joinElement.isInverse(); + } + + @Override + public boolean isOptional() { + return joinElement.isOptional(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return joinElement.getKey().getOnDelete() == JaxbOnDeleteAttribute.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return joinElement.getKey().getForeignKey(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkJoinColumnResolutionDelegate; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return Helper.buildCustomSql( joinElement.getSqlInsert() ); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return Helper.buildCustomSql( joinElement.getSqlUpdate() ); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return Helper.buildCustomSql( joinElement.getSqlDelete() ); + } + + + public String getLogicalTableNameForContainedColumns() { + return TableSource.class.isInstance( joinTable ) + ? ( (TableSource) joinTable ).getExplicitTableName() + : ( (InLineViewSource) joinTable ).getLogicalName(); + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final JaxbJoinElement joinElement; + + public JoinColumnResolutionDelegateImpl(JaxbJoinElement joinElement) { + this.joinElement = joinElement; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( getReferencedAttributeName() ); + } + + @Override + public String getReferencedAttributeName() { + return joinElement.getKey().getPropertyRef(); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( joinElement.getKey().getPropertyRef() ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SequentialPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SequentialPluralAttributeIndexSourceImpl.java new file mode 100644 index 0000000000..73fa9b5ac8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SequentialPluralAttributeIndexSourceImpl.java @@ -0,0 +1,195 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbIndexElement; +import org.hibernate.jaxb.spi.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SequentialPluralAttributeIndexSource; +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * + */ +public class SequentialPluralAttributeIndexSourceImpl extends AbstractHbmSourceNode implements SequentialPluralAttributeIndexSource { + private final List< RelationalValueSource > valueSources; + private final HibernateTypeSource typeSource; + private final int base; + + public SequentialPluralAttributeIndexSourceImpl(MappingDocument sourceMappingDocument, final JaxbListIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() { + + List< JaxbColumnElement > columnElements = indexElement.getColumn() == null ? Collections.EMPTY_LIST : Collections.singletonList( indexElement.getColumn() ); + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public List getColumn() { + return columnElements; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } ); + typeSource = new HibernateTypeSource() { + + @Override + public String getName() { + return "integer"; + } + + @Override + public Map< String, String > getParameters() { + return java.util.Collections.< String, String >emptyMap(); + } + @Override + public Class getJavaType() { + return null; + } + }; + base = Integer.parseInt( indexElement.getBase() ); + } + + public SequentialPluralAttributeIndexSourceImpl(MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + indexElement.getLength(), + null, + null + ); + } + @Override + public List getColumn() { + return indexElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } ); + typeSource = new HibernateTypeSource() { + + @Override + public String getName() { + return StringHelper.isEmpty( indexElement.getType() ) ? "integer" : indexElement.getType(); + } + + @Override + public Map< String, String > getParameters() { + return java.util.Collections.< String, String >emptyMap(); + } + @Override + public Class getJavaType() { + return null; + } + }; + base = 0; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + @Override + public int base() { + return base; + } + + @Override + public PluralAttributeIndexBinding.Nature getNature() { + return PluralAttributeIndexBinding.Nature.BASIC; + } + + @Override + public List getDefaultNamingStrategies() { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.columnName( "idx" ); + } + }; + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public boolean isReferencedEntityAttribute() { + return false; + } + + @Override + public List< RelationalValueSource > relationalValueSources() { + return valueSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SetSourceImpl.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SetSourceImpl.java index 64b4b6398b..7a1560284f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SetSourceImpl.java @@ -21,21 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSetElement; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.Orderable; -import org.hibernate.metamodel.source.binder.PluralAttributeNature; -import org.hibernate.metamodel.source.binder.Sortable; +import org.hibernate.jaxb.spi.hbm.JaxbSetElement; +import org.hibernate.metamodel.spi.source.AttributeSourceContainer; +import org.hibernate.metamodel.spi.source.Orderable; +import org.hibernate.metamodel.spi.source.Sortable; /** * @author Steve Ebersole */ -public class SetAttributeSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable, Sortable { - public SetAttributeSourceImpl(JaxbSetElement setElement, AttributeSourceContainer container) { - super( setElement, container ); +public class SetSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable, Sortable { + public SetSourceImpl( + MappingDocument sourceMappingDocument, + JaxbSetElement setElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, setElement, container ); } @Override @@ -44,13 +46,15 @@ public class SetAttributeSourceImpl extends AbstractPluralAttributeSourceImpl im } @Override - public PluralAttributeNature getPluralAttributeNature() { - return PluralAttributeNature.SET; + public Nature getNature() { + return Nature.SET; } @Override public boolean isSorted() { - return StringHelper.isNotEmpty( getComparatorName() ); + String comparatorName = getComparatorName(); + return StringHelper.isNotEmpty( comparatorName ) + && !comparatorName.equals("unsorted"); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SingularIdentifierAttributeSourceImpl.java similarity index 66% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SingularIdentifierAttributeSourceImpl.java index 9a97314783..9fcf12cae8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SingularIdentifierAttributeSourceImpl.java @@ -21,35 +21,39 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbIdElement; import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.SizeSource; /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbId idElement; - private final ExplicitHibernateTypeSource typeSource; +class SingularIdentifierAttributeSourceImpl + extends AbstractHbmSourceNode + implements SingularAttributeSource { + private final JaxbIdElement idElement; + private final HibernateTypeSource typeSource; private final List valueSources; public SingularIdentifierAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbId idElement, - LocalBindingContext bindingContext) { + MappingDocument mappingDocument, + final JaxbIdElement idElement) { + super( mappingDocument ); this.idElement = idElement; - this.typeSource = new ExplicitHibernateTypeSource() { + this.typeSource = new HibernateTypeSource() { private final String name = idElement.getTypeAttribute() != null ? idElement.getTypeAttribute() : idElement.getType() != null @@ -68,8 +72,14 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { public Map getParameters() { return parameters; } + + @Override + public Class getJavaType() { + return null; + } }; this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { @Override public String getColumnAttribute() { @@ -77,37 +87,29 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { } @Override - public String getFormulaAttribute() { - return null; + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + idElement.getLength(), + null, + null + ); } @Override - public List getColumnOrFormulaElements() { + public List getColumn() { return idElement.getColumn(); } - @Override - public String getContainingTableName() { - // by definition, the identifier should be bound to the primary table of the root entity - return null; - } - @Override public boolean isIncludedInInsertByDefault() { return true; } - @Override - public boolean isIncludedInUpdateByDefault() { - return false; - } - @Override public boolean isForceNotNull() { return true; } - }, - bindingContext + } ); } @@ -119,7 +121,7 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { } @Override - public ExplicitHibernateTypeSource getTypeInformation() { + public HibernateTypeSource getTypeInformation() { return typeSource; } @@ -128,16 +130,6 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { return idElement.getAccess(); } - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return false; - } - @Override public PropertyGeneration getGeneration() { return PropertyGeneration.INSERT; @@ -148,14 +140,19 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { return false; } + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + } + @Override public boolean isIncludedInOptimisticLocking() { return false; } @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; + public Nature getNature() { + return Nature.BASIC; } @Override @@ -170,7 +167,7 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { @Override public boolean areValuesIncludedInUpdateByDefault() { - return true; + return false; } @Override @@ -178,6 +175,11 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { return false; } + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + @Override public List relationalValueSources() { return valueSources; @@ -189,7 +191,7 @@ class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { } @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( idElement.getMeta() ); + public Iterable getMetaAttributeSources() { + return idElement.getMeta(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SizeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SizeSourceImpl.java new file mode 100644 index 0000000000..17b7c19b2d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SizeSourceImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.metamodel.spi.source.SizeSource; + +/** + * @author Gail Badner + */ +public class SizeSourceImpl implements SizeSource { + + private final Integer length; + private final Integer precision; + private final Integer scale; + + public SizeSourceImpl(Integer precision, Integer scale, Integer length) { + this.precision = precision; + this.scale = scale; + this.length = length; + } + + public boolean isLengthDefined() { + return length != null; + } + + public int getLength() { + if ( length == null ) { + throw new UnsupportedOperationException( "length is undefined." ); + } + return length; + } + + public boolean isPrecisionDefined() { + return precision != null; + } + + public int getPrecision() { + if ( precision == null ) { + throw new UnsupportedOperationException( "precision is undefined." ); + } + return precision; + } + + public boolean isScaleDefined() { + return scale != null; + } + + public int getScale() { + if ( scale == null ) { + throw new UnsupportedOperationException( "scale is undefined." ); + } + return scale; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SubclassEntitySourceImpl.java new file mode 100644 index 0000000000..e8ebc33721 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SubclassEntitySourceImpl.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.jaxb.spi.hbm.EntityElement; +import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement; +import org.hibernate.jaxb.spi.hbm.TableInformationSource; +import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; + +/** + * @author Steve Ebersole + */ +public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource { + private final EntitySource container; + private final TableSpecificationSource primaryTable; + protected SubclassEntitySourceImpl( + MappingDocument sourceMappingDocument, + EntityElement entityElement, + EntitySource container) { + super( sourceMappingDocument, entityElement ); + this.container = container; + this.primaryTable = TableInformationSource.class.isInstance( entityElement ) + ? Helper.createTableSource( sourceMappingDocument(), (TableInformationSource) entityElement, this ) + : null; + + + afterInstantiation(); + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public String getDiscriminatorMatchValue() { + return JaxbSubclassElement.class.isInstance( entityElement() ) + ? ( (JaxbSubclassElement) entityElement() ).getDiscriminatorValue() + : null; + } + + @Override + public EntitySource superclassEntitySource() { + return container; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TableSourceImpl.java new file mode 100644 index 0000000000..acce4380c6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TableSourceImpl.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.metamodel.spi.source.TableSource; + +/** + * @author Steve Ebersole + */ +public class TableSourceImpl + extends AbstractHbmSourceNode + implements TableSource { + private final String schema; + private final String catalog; + private final String tableName; + + TableSourceImpl(MappingDocument mappingDocument, String schema, String catalog, String tableName) { + super( mappingDocument ); + this.schema = schema; + this.catalog = catalog; + this.tableName = tableName; + } + + @Override + public String getExplicitSchemaName() { + return schema; + } + + @Override + public String getExplicitCatalogName() { + return catalog; + } + + @Override + public String getExplicitTableName() { + return tableName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java similarity index 64% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java index 52ef5eeab6..c5e895a497 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java @@ -21,60 +21,43 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbTimestampElement; import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class TimestampAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbTimestamp timestampElement; - private final LocalBindingContext bindingContext; +class TimestampAttributeSourceImpl + extends AbstractHbmSourceNode + implements VersionAttributeSource { + private final JaxbTimestampElement timestampElement; private final List valueSources; TimestampAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbTimestamp timestampElement, - LocalBindingContext bindingContext) { + MappingDocument mappingDocument, + final JaxbTimestampElement timestampElement) { + super( mappingDocument ); this.timestampElement = timestampElement; - this.bindingContext = bindingContext; this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { @Override public String getColumnAttribute() { - return timestampElement.getColumn(); + return timestampElement.getColumnAttribute(); } - - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { - return null; - } - - @Override - public String getContainingTableName() { - // by definition the version should come from the primary table of the root entity. - return null; - } - @Override public boolean isIncludedInInsertByDefault() { return true; @@ -84,12 +67,11 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { public boolean isIncludedInUpdateByDefault() { return true; } - }, - bindingContext + } ); } - private final ExplicitHibernateTypeSource typeSource = new ExplicitHibernateTypeSource() { + private final HibernateTypeSource typeSource = new HibernateTypeSource() { @Override public String getName() { return "db".equals( timestampElement.getSource() ) ? "dbtimestamp" : "timestamp"; @@ -99,6 +81,10 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { public Map getParameters() { return null; } + @Override + public Class getJavaType() { + return null; + } }; @Override @@ -107,7 +93,7 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { } @Override - public ExplicitHibernateTypeSource getTypeInformation() { + public HibernateTypeSource getTypeInformation() { return typeSource; } @@ -116,16 +102,6 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { return timestampElement.getAccess(); } - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return true; - } - private ValueHolder propertyGenerationValue = new ValueHolder( new ValueHolder.DeferredInitializer() { @Override @@ -134,10 +110,7 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { ? PropertyGeneration.NEVER : PropertyGeneration.parse( timestampElement.getGenerated().value() ); if ( propertyGeneration == PropertyGeneration.INSERT ) { - throw new MappingException( - "'generated' attribute cannot be 'insert' for versioning property", - bindingContext.getOrigin() - ); + throw makeMappingException( "'generated' attribute cannot be 'insert' for versioning property" ); } return propertyGeneration; } @@ -154,14 +127,19 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { return false; } + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + } + @Override public boolean isIncludedInOptimisticLocking() { return false; } @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; + public Nature getNature() { + return Nature.BASIC; } @Override @@ -184,6 +162,11 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { return true; } + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + @Override public List relationalValueSources() { return valueSources; @@ -195,7 +178,12 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { } @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( timestampElement.getMeta() ); + public Iterable getMetaAttributeSources() { + return timestampElement.getMeta(); + } + + @Override + public String getUnsavedValue() { + return timestampElement.getUnsavedValue().value(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TypeDescriptorSourceImpl.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TypeDescriptorSourceImpl.java index 492299ad68..b16446c1dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TypeDescriptorSourceImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,44 +21,46 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.internal.source.hbm; -import java.util.Collection; -import java.util.List; import java.util.Map; -import java.util.Set; + +import org.hibernate.jaxb.spi.hbm.JaxbTypedefElement; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; /** - * Identifies the specific semantic of a plural valued attribute. - * * @author Steve Ebersole */ -public enum PluralAttributeNature { - BAG( "bag", Collection.class ), - IDBAG( "idbag", Collection.class ), - SET( "set", Set.class ), - LIST( "list", List.class ), - MAP( "map", Map.class ); +public class TypeDescriptorSourceImpl implements TypeDescriptorSource { + private static final String[] NO_REGISTRATION_KEYS = new String[0]; private final String name; - private final Class javaContract; - private final boolean indexed; + private final String implementationClassName; + private final Map params; - PluralAttributeNature(String name, Class javaContract) { - this.name = name; - this.javaContract = javaContract; - this.indexed = Map.class.isAssignableFrom( javaContract ) || List.class.isAssignableFrom( javaContract ); + public TypeDescriptorSourceImpl(JaxbTypedefElement typeDefElement) { + this.name = typeDefElement.getName(); + this.implementationClassName = typeDefElement.getClazz(); + this.params = Helper.extractParameters( typeDefElement.getParam() ); } + @Override public String getName() { return name; } - public Class getJavaContract() { - return javaContract; + @Override + public String getTypeImplementationClassName() { + return implementationClassName; } - public boolean isIndexed() { - return indexed; + @Override + public String[] getRegistrationKeys() { + return NO_REGISTRATION_KEYS; + } + + @Override + public Map getParameters() { + return params; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UnexpectedAttributeSourceTypeException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UnexpectedAttributeSourceTypeException.java new file mode 100644 index 0000000000..2e423bd59f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UnexpectedAttributeSourceTypeException.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import org.hibernate.HibernateException; + +/** + * @author Steve Ebersole + */ +public class UnexpectedAttributeSourceTypeException extends HibernateException { + public UnexpectedAttributeSourceTypeException(String message) { + super( message ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UniqueConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UniqueConstraintSourceImpl.java new file mode 100644 index 0000000000..c3ff52ff7b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/UniqueConstraintSourceImpl.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.hbm; + +import java.util.List; + +import org.hibernate.metamodel.spi.source.UniqueConstraintSource; + +/** + * @author Hardy Ferentschik + */ +class UniqueConstraintSourceImpl extends AbstractConstraintSource implements UniqueConstraintSource { + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames, List orderings) { +// super( name, tableName, columnNames, orderings ); + super( name, tableName ); + } + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { +// super( name, tableName, columnNames, Collections.EMPTY_LIST ); + super( name, tableName ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "UniqueConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java similarity index 64% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java index 79dc3d42e6..91e513129a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java @@ -21,75 +21,64 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.internal.source.hbm; import java.util.List; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbVersionElement; import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.HibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; + /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class VersionAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbVersion versionElement; - private final LocalBindingContext bindingContext; +class VersionAttributeSourceImpl + extends AbstractHbmSourceNode + implements VersionAttributeSource { + private final JaxbVersionElement versionElement; private final List valueSources; VersionAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbVersion versionElement, - LocalBindingContext bindingContext) { + MappingDocument mappingDocument, + final JaxbVersionElement versionElement) { + super( mappingDocument ); this.versionElement = versionElement; - this.bindingContext = bindingContext; this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), new Helper.ValueSourcesAdapter() { @Override public String getColumnAttribute() { return versionElement.getColumnAttribute(); } - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { + public List getColumn() { return versionElement.getColumn(); } - @Override - public String getContainingTableName() { - // by definition the version should come from the primary table of the root entity. - return null; - } - @Override public boolean isIncludedInInsertByDefault() { - return Helper.getBooleanValue( versionElement.isInsert(), true ); + return Helper.getValue( versionElement.isInsert(), true ); } @Override public boolean isIncludedInUpdateByDefault() { return true; } - }, - bindingContext + } ); } - private final ExplicitHibernateTypeSource typeSource = new ExplicitHibernateTypeSource() { + private final HibernateTypeSource typeSource = new HibernateTypeSource() { @Override public String getName() { return versionElement.getType() == null ? "integer" : versionElement.getType(); @@ -99,15 +88,24 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { public Map getParameters() { return null; } + @Override + public Class getJavaType() { + return null; + } }; + @Override + public String getUnsavedValue() { + return versionElement.getUnsavedValue().value(); + } + @Override public String getName() { return versionElement.getName(); } @Override - public ExplicitHibernateTypeSource getTypeInformation() { + public HibernateTypeSource getTypeInformation() { return typeSource; } @@ -116,16 +114,6 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { return versionElement.getAccess(); } - @Override - public boolean isInsertable() { - return Helper.getBooleanValue( versionElement.isInsert(), true ); - } - - @Override - public boolean isUpdatable() { - return true; - } - private ValueHolder propertyGenerationValue = new ValueHolder( new ValueHolder.DeferredInitializer() { @Override @@ -134,16 +122,12 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { ? PropertyGeneration.NEVER : PropertyGeneration.parse( versionElement.getGenerated().value() ); if ( propertyGeneration == PropertyGeneration.INSERT ) { - throw new MappingException( - "'generated' attribute cannot be 'insert' for versioning property", - bindingContext.getOrigin() - ); + throw makeMappingException( "'generated' attribute cannot be 'insert' for versioning property" ); } return propertyGeneration; } } ); - @Override public PropertyGeneration getGeneration() { return propertyGenerationValue.getValue(); @@ -154,14 +138,19 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { return false; } + @Override + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() { + return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID; + } + @Override public boolean isIncludedInOptimisticLocking() { return false; } @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; + public Nature getNature() { + return Nature.BASIC; } @Override @@ -171,7 +160,7 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { @Override public boolean areValuesIncludedInInsertByDefault() { - return true; + return Helper.getValue( versionElement.isInsert(), true ); } @Override @@ -184,6 +173,11 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { return true; } + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + @Override public List relationalValueSources() { return valueSources; @@ -195,7 +189,7 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { } @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( versionElement.getMeta() ); + public Iterable getMetaAttributeSources() { + return versionElement.getMeta(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/AbstractQueryElementContentsParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/AbstractQueryElementContentsParser.java new file mode 100644 index 0000000000..a8e013958e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/AbstractQueryElementContentsParser.java @@ -0,0 +1,228 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm.parser; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.CacheMode; +import org.hibernate.FlushMode; +import org.hibernate.MappingException; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.jaxb.spi.hbm.JaxbCacheModeAttribute; +import org.hibernate.jaxb.spi.hbm.JaxbFlushModeAttribute; +import org.hibernate.jaxb.spi.hbm.JaxbQueryElement; +import org.hibernate.jaxb.spi.hbm.JaxbQueryParamElement; +import org.hibernate.jaxb.spi.hbm.JaxbSqlQueryElement; +import org.hibernate.jaxb.spi.hbm.QuerySourceElement; + +/** + * @author Brett Meyer + */ +abstract class AbstractQueryElementContentsParser { + + // TODO: Hate the use of QuerySourceElement -- remove/refactor. + + public void parse( NamedQueryDefinitionBuilder builder, + final JaxbQueryElement queryElement ) { + + QuerySourceElement element = new QuerySourceElement() { + @Override + public List getContent() { + return queryElement.getContent(); + } + + @Override + public JaxbCacheModeAttribute getCacheMode() { + return queryElement.getCacheMode(); + } + + @Override + public String getCacheRegion() { + return queryElement.getCacheRegion(); + } + + @Override + public boolean isCacheable() { + return queryElement.isCacheable(); + } + + @Override + public String getComment() { + return queryElement.getComment(); + } + + @Override + public Integer getFetchSize() { + return queryElement.getFetchSize(); + } + + @Override + public JaxbFlushModeAttribute getFlushMode() { + return queryElement.getFlushMode(); + } + + @Override + public String getName() { + return queryElement.getName(); + } + + @Override + public boolean isReadOnly() { + return queryElement.isReadOnly(); + } + + @Override + public Integer getTimeout() { + return queryElement.getTimeout(); + } + }; + + parse( builder, element ); + } + + public void parse( NamedQueryDefinitionBuilder builder, + final JaxbSqlQueryElement queryElement ) { + + QuerySourceElement element = new QuerySourceElement() { + @Override + public List getContent() { + return queryElement.getContent(); + } + + @Override + public JaxbCacheModeAttribute getCacheMode() { + return queryElement.getCacheMode(); + } + + @Override + public String getCacheRegion() { + return queryElement.getCacheRegion(); + } + + @Override + public boolean isCacheable() { + return queryElement.isCacheable(); + } + + @Override + public String getComment() { + return queryElement.getComment(); + } + + @Override + public Integer getFetchSize() { + return queryElement.getFetchSize(); + } + + @Override + public JaxbFlushModeAttribute getFlushMode() { + return queryElement.getFlushMode(); + } + + @Override + public String getName() { + return queryElement.getName(); + } + + @Override + public boolean isReadOnly() { + return queryElement.isReadOnly(); + } + + @Override + public Integer getTimeout() { + return queryElement.getTimeout(); + } + }; + + parse( builder, element ); + } + + private void parse( NamedQueryDefinitionBuilder builder, + QuerySourceElement queryElement ) { + final String queryName = queryElement.getName(); + final boolean cacheable = queryElement.isCacheable(); + final String region = queryElement.getCacheRegion(); + final Integer timeout = queryElement.getTimeout(); + final Integer fetchSize = queryElement.getFetchSize(); + final boolean readonly = queryElement.isReadOnly(); + final String comment = queryElement.getComment(); + final CacheMode cacheMode = queryElement.getCacheMode() == null + ? null : CacheMode.valueOf( queryElement + .getCacheMode().value().toUpperCase() ); + final FlushMode flushMode = queryElement.getFlushMode() == null + ? null : FlushMode.valueOf( queryElement + .getFlushMode().value().toUpperCase() ); + + builder.setName( queryName ).setCacheable( cacheable ) + .setCacheRegion( region ).setTimeout( timeout ) + .setFetchSize( fetchSize ).setFlushMode( flushMode ) + .setCacheMode( cacheMode ).setReadOnly( readonly ) + .setComment( comment ); + + final List list = queryElement.getContent(); + parse( queryName, list, builder ); + } + + private void parse(String queryName, List contents, + NamedQueryDefinitionBuilder builder) { + final Map queryParam = new HashMap(); + String query = ""; + boolean isQueryDefined = false; + for ( Serializable obj : contents ) { + if ( obj == null ) { + continue; + } + else if ( JaxbQueryParamElement.class.isInstance( obj ) ) { + JaxbQueryParamElement element + = JaxbQueryParamElement.class.cast( obj ); + queryParam.put( element.getName(), element.getType() ); + } + else if ( String.class.isInstance( obj ) ) { + if ( !isQueryDefined ) { + if ( StringHelper.isNotEmpty( obj.toString().trim() ) ) { + query = obj.toString().trim(); + isQueryDefined = true; + } + + } + else { + throw new MappingException( + "Duplicate query string is defined in Named query[+" + + queryName + "]" ); + } + } + parseExtra( queryName, obj, builder ); + } + builder.setParameterTypes( queryParam ); + if ( StringHelper.isEmpty( query ) ) { + throw new MappingException( + "Named query[" + queryName+ "] has no query string defined"); + } + builder.setQuery( query ); + } + + protected abstract void parseExtra(String queryName, Serializable obj, NamedQueryDefinitionBuilder builder); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/BasicQueryElementContentParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/BasicQueryElementContentParser.java new file mode 100644 index 0000000000..d35da28fc0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/BasicQueryElementContentParser.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm.parser; + +import java.io.Serializable; + +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; + +/** + * @author Brett Meyer + */ +public class BasicQueryElementContentParser extends AbstractQueryElementContentsParser { + + @Override + protected void parseExtra(String queryName, Serializable obj, + NamedQueryDefinitionBuilder builder) { + // do nothing + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/SQLQueryElementContentParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/SQLQueryElementContentParser.java new file mode 100644 index 0000000000..29108b0a59 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/parser/SQLQueryElementContentParser.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.source.hbm.parser; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; + +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.jaxb.spi.hbm.JaxbLoadCollectionElement; +import org.hibernate.jaxb.spi.hbm.JaxbResultsetElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnJoinElement; +import org.hibernate.jaxb.spi.hbm.JaxbReturnScalarElement; +import org.hibernate.jaxb.spi.hbm.JaxbSynchronizeElement; +import org.hibernate.metamodel.internal.source.hbm.ResultSetMappingBinder; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.source.LocalBindingContext; + +/** + * @author Brett Meyer + * @author String Liu + */ +public class SQLQueryElementContentParser extends AbstractQueryElementContentsParser { + private final List synchronizedTables = new ArrayList(); + private final List loadCollectionElements = new ArrayList(); + private final List returnScalarElements = new ArrayList(); + private final List returnElements = new ArrayList(); + private final List returnJoinElements = new ArrayList(); + + @Override + protected void parseExtra( String queryName, Serializable obj, + NamedQueryDefinitionBuilder builder ) { + if ( !JAXBElement.class.isInstance( obj ) ) { + return; + } + JAXBElement jaxbElement = JAXBElement.class.cast( obj ); + Class targetType = jaxbElement.getDeclaredType(); + Object value = jaxbElement.getValue(); + if ( JaxbSynchronizeElement.class == targetType ) { + JaxbSynchronizeElement element = JaxbSynchronizeElement.class.cast( value ); + synchronizedTables.add( element.getTable() ); + } + else if ( JaxbLoadCollectionElement.class == targetType ) { + loadCollectionElements.add( JaxbLoadCollectionElement.class.cast( value ) ); + } + else if ( JaxbReturnScalarElement.class == targetType ) { + returnScalarElements.add( JaxbReturnScalarElement.class.cast( value ) ); + } + else if ( JaxbReturnElement.class == targetType ) { + returnElements.add( JaxbReturnElement.class.cast( value ) ); + } + else if ( JaxbReturnJoinElement.class == targetType ) { + returnJoinElements.add( JaxbReturnJoinElement.class.cast( value ) ); + } + } + + public NamedSQLQueryDefinition buildQueryReturns( + final String queryName, + final NamedSQLQueryDefinitionBuilder builder, + final LocalBindingContext bindingContext, + final MetadataImplementor metadata ) { + + final JaxbResultsetElement mockedResultSet = new JaxbResultsetElement(){ + @Override + public String getName() { + return queryName; + } + @Override + public List getLoadCollection() { + return loadCollectionElements; + } + + @Override + public List getReturn() { + return returnElements; + } + + @Override + public List getReturnJoin() { + return returnJoinElements; + } + + @Override + public List getReturnScalar() { + return returnScalarElements; + } + }; + + + final ResultSetMappingDefinition definition = ResultSetMappingBinder.buildResultSetMappingDefinitions( mockedResultSet,bindingContext,metadata ); + return builder.setQueryReturns( definition.getQueryReturns() ) + .setQuerySpaces( synchronizedTables ) + .createNamedQueryDefinition(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java deleted file mode 100644 index bad9ae1c74..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.dialect.Dialect; - -/** - * Support for writing {@link Constraint} implementations - * - * @todo do we need to support defining these on particular schemas/catalogs? - * - * @author Steve Ebersole - * @author Gail Badner - */ -public abstract class AbstractConstraint implements Constraint { - private final TableSpecification table; - private final String name; - private List columns = new ArrayList(); - - protected AbstractConstraint(TableSpecification table, String name) { - this.table = table; - this.name = name; - } - - public TableSpecification getTable() { - return table; - } - - public String getName() { - return name; - } - - public Iterable getColumns() { - return columns; - } - - protected int getColumnSpan() { - return columns.size(); - } - - protected List internalColumnAccess() { - return columns; - } - - public void addColumn(Column column) { - internalAddColumn( column ); - } - - protected void internalAddColumn(Column column) { - if ( column.getTable() != getTable() ) { - throw new AssertionFailure( - String.format( - "Unable to add column to constraint; tables [%s, %s] did not match", - column.getTable().toLoggableString(), - getTable().toLoggableString() - ) - ); - } - columns.add( column ); - } - - protected boolean isCreationVetoed(Dialect dialect) { - return false; - } - - protected abstract String sqlConstraintStringInAlterTable(Dialect dialect); - - public String[] sqlDropStrings(Dialect dialect) { - if ( isCreationVetoed( dialect ) ) { - return null; - } - else { - return new String[] { - new StringBuilder() - .append( "alter table " ) - .append( getTable().getQualifiedName( dialect ) ) - .append( " drop constraint " ) - .append( dialect.quote( getName() ) ) - .toString() - }; - } - } - - public String[] sqlCreateStrings(Dialect dialect) { - if ( isCreationVetoed( dialect ) ) { - return null; - } - else { - return new String[] { - new StringBuilder( "alter table " ) - .append( getTable().getQualifiedName( dialect ) ) - .append( sqlConstraintStringInAlterTable( dialect ) ) - .toString() - }; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java deleted file mode 100644 index 3165c6b107..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Convenience base class for implementing the {@link ValueContainer} contract centralizing commonality - * between modeling tables, views and inline views. - * - * @author Steve Ebersole - */ -public abstract class AbstractTableSpecification implements TableSpecification { - private final static AtomicInteger tableCounter = new AtomicInteger( 0 ); - private final int tableNumber; - - private final LinkedHashMap values = new LinkedHashMap(); - - private final PrimaryKey primaryKey = new PrimaryKey( this ); - private final List foreignKeys = new ArrayList(); - - public AbstractTableSpecification() { - this.tableNumber = tableCounter.getAndIncrement(); - } - - @Override - public int getTableNumber() { - return tableNumber; - } - - @Override - public Iterable values() { - return values.values(); - } - - @Override - public Column locateOrCreateColumn(String name) { - if(values.containsKey( name )){ - return (Column) values.get( name ); - } - final Column column = new Column( this, values.size(), name ); - values.put( name, column ); - return column; - } - - @Override - public DerivedValue locateOrCreateDerivedValue(String fragment) { - if(values.containsKey( fragment )){ - return (DerivedValue) values.get( fragment ); - } - final DerivedValue value = new DerivedValue( this, values.size(), fragment ); - values.put( fragment, value ); - return value; - } - - @Override - public Tuple createTuple(String name) { - return new Tuple( this, name ); - } - - @Override - public Iterable getForeignKeys() { - return foreignKeys; - } - - @Override - public ForeignKey createForeignKey(TableSpecification targetTable, String name) { - ForeignKey fk = new ForeignKey( this, targetTable, name ); - foreignKeys.add( fk ); - return fk; - } - - @Override - public PrimaryKey getPrimaryKey() { - return primaryKey; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java deleted file mode 100644 index 577712bc44..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.relational.state.ColumnRelationalState; - -/** - * Models a physical column - * - * @author Gavin King - * @author Steve Ebersole - */ -public class Column extends AbstractSimpleValue { - private final Identifier columnName; - private boolean nullable; - private boolean unique; - - private String defaultValue; - private String checkCondition; - private String sqlType; - - private String readFragment; - private String writeFragment; - - private String comment; - - private Size size = new Size(); - - protected Column(TableSpecification table, int position, String name) { - this( table, position, Identifier.toIdentifier( name ) ); - } - - protected Column(TableSpecification table, int position, Identifier name) { - super( table, position ); - this.columnName = name; - } - - public void initialize(ColumnRelationalState state, boolean forceNonNullable, boolean forceUnique) { - size.initialize( state.getSize() ); - nullable = ! forceNonNullable && state.isNullable(); - unique = ! forceUnique && state.isUnique(); - checkCondition = state.getCheckCondition(); - defaultValue = state.getDefault(); - sqlType = state.getSqlType(); - - // TODO: this should go into binding instead (I think???) - writeFragment = state.getCustomWriteFragment(); - readFragment = state.getCustomReadFragment(); - comment = state.getComment(); - for ( String uniqueKey : state.getUniqueKeys() ) { - getTable().getOrCreateUniqueKey( uniqueKey ).addColumn( this ); - } - for ( String index : state.getIndexes() ) { - getTable().getOrCreateIndex( index ).addColumn( this ); - } - } - - public Identifier getColumnName() { - return columnName; - } - - public boolean isNullable() { - return nullable; - } - - public void setNullable(boolean nullable) { - this.nullable = nullable; - } - - public boolean isUnique() { - return unique; - } - - public void setUnique(boolean unique) { - this.unique = unique; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - public String getCheckCondition() { - return checkCondition; - } - - public void setCheckCondition(String checkCondition) { - this.checkCondition = checkCondition; - } - - public String getSqlType() { - return sqlType; - } - - public void setSqlType(String sqlType) { - this.sqlType = sqlType; - } - - public String getReadFragment() { - return readFragment; - } - - public void setReadFragment(String readFragment) { - this.readFragment = readFragment; - } - - public String getWriteFragment() { - return writeFragment; - } - - public void setWriteFragment(String writeFragment) { - this.writeFragment = writeFragment; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public Size getSize() { - return size; - } - - public void setSize(Size size) { - this.size = size; - } - - @Override - public String toLoggableString() { - return getTable().getLoggableValueQualifier() + '.' + getColumnName(); - } - - @Override - public String getAlias(Dialect dialect) { - String alias = columnName.getName(); - int lastLetter = StringHelper.lastIndexOfLetter( columnName.getName() ); - if ( lastLetter == -1 ) { - alias = "column"; - } - boolean useRawName = - columnName.getName().equals( alias ) && - alias.length() <= dialect.getMaxAliasLength() && - ! columnName.isQuoted() && - ! columnName.getName().toLowerCase().equals( "rowid" ); - if ( ! useRawName ) { - String unique = - new StringBuilder() - .append( getPosition() ) - .append( '_' ) - .append( getTable().getTableNumber() ) - .append( '_' ) - .toString(); - if ( unique.length() >= dialect.getMaxAliasLength() ) { - throw new MappingException( - "Unique suffix [" + unique + "] length must be less than maximum [" + dialect.getMaxAliasLength() + "]" - ); - } - if ( alias.length() + unique.length() > dialect.getMaxAliasLength()) { - alias = alias.substring( 0, dialect.getMaxAliasLength() - unique.length() ); - } - alias = alias + unique; - } - return alias; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java deleted file mode 100644 index 3291b967ed..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.Metadata; - -/** - * Represents a database and manages the named schema/catalog pairs defined within. - * - * @author Steve Ebersole - * @author Gail Badner - */ -public class Database { - private final Schema.Name implicitSchemaName; - - private final Map schemaMap = new HashMap(); - private final List auxiliaryDatabaseObjects = new ArrayList(); - - public Database(Metadata.Options options) { - String schemaName = options.getDefaultSchemaName(); - String catalogName = options.getDefaultCatalogName(); - if ( options.isGloballyQuotedIdentifiers() ) { - schemaName = StringHelper.quote( schemaName ); - catalogName = StringHelper.quote( catalogName ); - } - implicitSchemaName = new Schema.Name( schemaName, catalogName ); - makeSchema( implicitSchemaName ); - } - - public Schema getDefaultSchema() { - return schemaMap.get( implicitSchemaName ); - } - - public Schema locateSchema(Schema.Name name) { - if ( name.getSchema() == null && name.getCatalog() == null ) { - return getDefaultSchema(); - } - Schema schema = schemaMap.get( name ); - if ( schema == null ) { - schema = makeSchema( name ); - } - return schema; - } - - private Schema makeSchema(Schema.Name name) { - Schema schema; - schema = new Schema( name ); - schemaMap.put( name, schema ); - return schema; - } - - public Schema getSchema(Identifier schema, Identifier catalog) { - return locateSchema( new Schema.Name( schema, catalog ) ); - } - - public Schema getSchema(String schema, String catalog) { - return locateSchema( new Schema.Name( Identifier.toIdentifier( schema ), Identifier.toIdentifier( catalog ) ) ); - } - - public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) { - if ( auxiliaryDatabaseObject == null ) { - throw new IllegalArgumentException( "Auxiliary database object is null." ); - } - auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject ); - } - - public Iterable getAuxiliaryDatabaseObjects() { - return auxiliaryDatabaseObjects; - } - - public String[] generateSchemaCreationScript(Dialect dialect) { - Set exportIdentifiers = new HashSet( 50 ); - List script = new ArrayList( 50 ); - - for ( Schema schema : schemaMap.values() ) { - // TODO: create schema/catalog??? - for ( Table table : schema.getTables() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, table ); - } - } - - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - - for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, uniqueKey ); - } - - for ( Index index : table.getIndexes() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, index ); - } - - if ( dialect.hasAlterTable() ) { - for ( ForeignKey foreignKey : table.getForeignKeys() ) { - // only add the foreign key if its target is a physical table - if ( Table.class.isInstance( foreignKey.getTargetTable() ) ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, foreignKey ); - } - } - } - - } - } - - // TODO: add sql create strings from PersistentIdentifierGenerator.sqlCreateStrings() - - for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjects ) { - if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, auxiliaryDatabaseObject ); - } - } - - return ArrayHelper.toStringArray( script ); - } - - public String[] generateDropSchemaScript(Dialect dialect) { - Set exportIdentifiers = new HashSet( 50 ); - List script = new ArrayList( 50 ); - - - // drop them in reverse order in case db needs it done that way... - for ( int i = auxiliaryDatabaseObjects.size() - 1 ; i >= 0 ; i-- ) { - AuxiliaryDatabaseObject object = auxiliaryDatabaseObjects.get( i ); - if ( object.appliesToDialect( dialect ) ) { - addSqlDropStrings( dialect, exportIdentifiers, script, object ); - } - } - - if ( dialect.dropConstraints() ) { - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - for ( ForeignKey foreignKey : table.getForeignKeys() ) { - // only include foreign key if the target table is physical - if ( foreignKey.getTargetTable() instanceof Table ) { - addSqlDropStrings( dialect, exportIdentifiers, script, foreignKey ); - } - } - } - } - } - - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - addSqlDropStrings( dialect, exportIdentifiers, script, table ); - } - } - - // TODO: add sql drop strings from PersistentIdentifierGenerator.sqlCreateStrings() - - // TODO: drop schemas/catalogs??? - - return ArrayHelper.toStringArray( script ); - } - - private static void addSqlDropStrings( - Dialect dialect, - Set exportIdentifiers, - List script, - Exportable exportable) { - addSqlStrings( - exportIdentifiers, script, exportable.getExportIdentifier(), exportable.sqlDropStrings( dialect ) - ); - } - - private static void addSqlCreateStrings( - Dialect dialect, - Set exportIdentifiers, - List script, - Exportable exportable) { - addSqlStrings( - exportIdentifiers, script, exportable.getExportIdentifier(), exportable.sqlCreateStrings( dialect ) - ); - } - - private static void addSqlStrings( - Set exportIdentifiers, - List script, - String exportIdentifier, - String[] sqlStrings) { - if ( sqlStrings == null ) { - return; - } - if ( exportIdentifiers.contains( exportIdentifier ) ) { - throw new MappingException( - "SQL strings added more than once for: " + exportIdentifier - ); - } - exportIdentifiers.add( exportIdentifier ); - script.addAll( Arrays.asList( sqlStrings ) ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java deleted file mode 100644 index 25a36aac8b..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.HashMap; -import java.util.Map; - -/** - * Represents a named schema/catalog pair and manages objects defined within. - * - * @author Steve Ebersole - */ -public class Schema { - private final Name name; - private Map inLineViews = new HashMap(); - private Map tables = new HashMap(); - - public Schema(Name name) { - this.name = name; - } - - public Schema(Identifier schema, Identifier catalog) { - this( new Name( schema, catalog ) ); - } - - public Name getName() { - return name; - } - - public Table locateTable(Identifier name) { - return tables.get( name ); - } - - public Table createTable(Identifier name) { - Table table = new Table( this, name ); - tables.put( name, table ); - return table; - } - - public Table locateOrCreateTable(Identifier name) { - final Table existing = locateTable( name ); - if ( existing == null ) { - return createTable( name ); - } - return existing; - } - - public Iterable

getTables() { - return tables.values(); - } - - public InLineView getInLineView(String logicalName) { - return inLineViews.get( logicalName ); - } - - public InLineView createInLineView(String logicalName, String subSelect) { - InLineView inLineView = new InLineView( this, logicalName, subSelect ); - inLineViews.put( logicalName, inLineView ); - return inLineView; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "Schema" ); - sb.append( "{name=" ).append( name ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Schema schema = (Schema) o; - - if ( name != null ? !name.equals( schema.name ) : schema.name != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return name != null ? name.hashCode() : 0; - } - - public static class Name { - private final Identifier schema; - private final Identifier catalog; - - public Name(Identifier schema, Identifier catalog) { - this.schema = schema; - this.catalog = catalog; - } - - public Name(String schema, String catalog) { - this( Identifier.toIdentifier( schema ), Identifier.toIdentifier( catalog ) ); - } - - public Identifier getSchema() { - return schema; - } - - public Identifier getCatalog() { - return catalog; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "Name" ); - sb.append( "{schema=" ).append( schema ); - sb.append( ", catalog=" ).append( catalog ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Name name = (Name) o; - - if ( catalog != null ? !catalog.equals( name.catalog ) : name.catalog != null ) { - return false; - } - if ( schema != null ? !schema.equals( name.schema ) : name.schema != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = schema != null ? schema.hashCode() : 0; - result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); - return result; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java deleted file mode 100644 index f88c2fdf08..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; - -import org.hibernate.dialect.Dialect; - -/** - * Models the concept of a relational TABLE (or VIEW). - * - * @author Gavin King - * @author Steve Ebersole - */ -public class Table extends AbstractTableSpecification implements Exportable { - private final Schema database; - private final Identifier tableName; - private final ObjectName objectName; - private final String qualifiedName; - - private final LinkedHashMap indexes = new LinkedHashMap(); - private final LinkedHashMap uniqueKeys = new LinkedHashMap(); - private final List checkConstraints = new ArrayList(); - private final List comments = new ArrayList(); - - public Table(Schema database, String tableName) { - this( database, Identifier.toIdentifier( tableName ) ); - } - - public Table(Schema database, Identifier tableName) { - this.database = database; - this.tableName = tableName; - objectName = new ObjectName( database.getName().getSchema(), database.getName().getCatalog(), tableName ); - this.qualifiedName = objectName.toText(); - } - - @Override - public Schema getSchema() { - return database; - } - - public Identifier getTableName() { - return tableName; - } - - @Override - public String getLoggableValueQualifier() { - return qualifiedName; - } - - @Override - public String getExportIdentifier() { - return qualifiedName; - } - - @Override - public String toLoggableString() { - return qualifiedName; - } - - @Override - public Iterable getIndexes() { - return indexes.values(); - } - - public Index getOrCreateIndex(String name) { - if( indexes.containsKey( name ) ){ - return indexes.get( name ); - } - Index index = new Index( this, name ); - indexes.put(name, index ); - return index; - } - - @Override - public Iterable getUniqueKeys() { - return uniqueKeys.values(); - } - - public UniqueKey getOrCreateUniqueKey(String name) { - if( uniqueKeys.containsKey( name ) ){ - return uniqueKeys.get( name ); - } - UniqueKey uniqueKey = new UniqueKey( this, name ); - uniqueKeys.put(name, uniqueKey ); - return uniqueKey; - } - - @Override - public Iterable getCheckConstraints() { - return checkConstraints; - } - - @Override - public void addCheckConstraint(String checkCondition) { - //todo ? StringHelper.isEmpty( checkCondition ); - //todo default name? - checkConstraints.add( new CheckConstraint( this, "", checkCondition ) ); - } - - @Override - public Iterable getComments() { - return comments; - } - - @Override - public void addComment(String comment) { - comments.add( comment ); - } - - @Override - public String getQualifiedName(Dialect dialect) { - return objectName.toText( dialect ); - } - - public String[] sqlCreateStrings(Dialect dialect) { - boolean hasPrimaryKey = getPrimaryKey().getColumns().iterator().hasNext(); - StringBuilder buf = - new StringBuilder( - hasPrimaryKey ? dialect.getCreateTableString() : dialect.getCreateMultisetTableString() ) - .append( ' ' ) - .append( objectName.toText( dialect ) ) - .append( " (" ); - - - // TODO: fix this when identity columns are supported by new metadata (HHH-6436) - // for now, assume false - //boolean identityColumn = idValue != null && idValue.isIdentityColumn( metadata.getIdentifierGeneratorFactory(), dialect ); - boolean isPrimaryKeyIdentity = false; - - // Try to find out the name of the primary key to create it as identity if the IdentityGenerator is used - String pkColName = null; - if ( hasPrimaryKey && isPrimaryKeyIdentity ) { - Column pkColumn = getPrimaryKey().getColumns().iterator().next(); - pkColName = pkColumn.getColumnName().encloseInQuotesIfQuoted( dialect ); - } - - boolean isFirst = true; - for ( SimpleValue simpleValue : values() ) { - if ( ! Column.class.isInstance( simpleValue ) ) { - continue; - } - if ( isFirst ) { - isFirst = false; - } - else { - buf.append( ", " ); - } - Column col = ( Column ) simpleValue; - String colName = col.getColumnName().encloseInQuotesIfQuoted( dialect ); - - buf.append( colName ).append( ' ' ); - - if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { - // to support dialects that have their own identity data type - if ( dialect.hasDataTypeInIdentityColumn() ) { - buf.append( getTypeString( col, dialect ) ); - } - buf.append( ' ' ) - .append( dialect.getIdentityColumnString( col.getDatatype().getTypeCode() ) ); - } - else { - buf.append( getTypeString( col, dialect ) ); - - String defaultValue = col.getDefaultValue(); - if ( defaultValue != null ) { - buf.append( " default " ).append( defaultValue ); - } - - if ( col.isNullable() ) { - buf.append( dialect.getNullColumnString() ); - } - else { - buf.append( " not null" ); - } - - } - - if ( col.isUnique() ) { - UniqueKey uk = getOrCreateUniqueKey( col.getColumnName() - .encloseInQuotesIfQuoted( dialect ) + '_' ); - uk.addColumn( col ); - buf.append( dialect.getUniqueDelegate() - .getColumnDefinitionUniquenessFragment( col ) ); - } - - if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) { - buf.append( " check (" ) - .append( col.getCheckCondition() ) - .append( ")" ); - } - - String columnComment = col.getComment(); - if ( columnComment != null ) { - buf.append( dialect.getColumnComment( columnComment ) ); - } - } - if ( hasPrimaryKey ) { - buf.append( ", " ) - .append( getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) ); - } - - buf.append( dialect.getUniqueDelegate().getTableCreationUniqueConstraintsFragment( this ) ); - - if ( dialect.supportsTableCheck() ) { - for ( CheckConstraint checkConstraint : checkConstraints ) { - buf.append( ", check (" ) - .append( checkConstraint ) - .append( ')' ); - } - } - - buf.append( ')' ); - buf.append( dialect.getTableTypeString() ); - - String[] sqlStrings = new String[ comments.size() + 1 ]; - sqlStrings[ 0 ] = buf.toString(); - - for ( int i = 0 ; i < comments.size(); i++ ) { - sqlStrings[ i + 1 ] = dialect.getTableComment( comments.get( i ) ); - } - - return sqlStrings; - } - - private static String getTypeString(Column col, Dialect dialect) { - String typeString = null; - if ( col.getSqlType() != null ) { - typeString = col.getSqlType(); - } - else { - Size size = col.getSize() == null ? - new Size( ) : - col.getSize(); - - typeString = dialect.getTypeName( - col.getDatatype().getTypeCode(), - size.getLength(), - size.getPrecision(), - size.getScale() - ); - } - return typeString; - } - - @Override - public String[] sqlDropStrings(Dialect dialect) { - return new String[] { dialect.getDropTableString( getQualifiedName( dialect ) ) }; - } - - @Override - public String toString() { - return "Table{name=" + qualifiedName + '}'; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java deleted file mode 100644 index c566dead53..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.LinkedHashSet; - -/** - * Models a compound value (a tuple or row-value-constructor is SQL terms). It is both a {@link Value} and - * a {@link ValueContainer} simultaneously. - *

- * IMPL NOTE : in terms of the tables themselves, SQL has no notion of a tuple/compound-value. We simply model - * it this way because: - *

    - *
  • it is a cleaner mapping to the logical model
  • - *
  • it allows more meaningful traversals from simple values back up to table through any intermediate tuples - * because it gives us a better understanding of the model.
  • - *
  • it better conveys intent
  • - *
  • it adds richness to the model
  • - *
- * - * @author Steve Ebersole - */ -public class Tuple implements Value, ValueContainer, Loggable { - private final TableSpecification table; - private final String name; - private final LinkedHashSet values = new LinkedHashSet(); - - public Tuple(TableSpecification table, String name) { - this.table = table; - this.name = name; - } - - @Override - public TableSpecification getTable() { - return table; - } - - public int valuesSpan() { - return values.size(); - } - - @Override - public Iterable values() { - return values; - } - - public void addValue(SimpleValue value) { - if ( ! value.getTable().equals( getTable() ) ) { - throw new IllegalArgumentException( "Tuple can only group values from same table" ); - } - values.add( value ); - } - - @Override - public String getLoggableValueQualifier() { - return getTable().getLoggableValueQualifier() + '.' + name + "{tuple}"; - } - - @Override - public String toLoggableString() { - return getLoggableValueQualifier(); - } - - @Override - public void validateJdbcTypes(JdbcCodes typeCodes) { - for ( Value value : values() ) { - value.validateJdbcTypes( typeCodes ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java deleted file mode 100644 index 985272bc47..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source; - -import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.Mapping; -import org.hibernate.engine.spi.NamedQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.metamodel.Metadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.relational.Database; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.TypeResolver; - -/** - * @author Steve Ebersole - */ -public interface MetadataImplementor extends Metadata, BindingContext, Mapping { - public ServiceRegistry getServiceRegistry(); - - public Database getDatabase(); - - public TypeResolver getTypeResolver(); - - public void addImport(String entityName, String entityName1); - - public void addEntity(EntityBinding entityBinding); - - public void addCollection(PluralAttributeBinding collectionBinding); - - public void addFetchProfile(FetchProfile profile); - - public void addTypeDefinition(TypeDef typeDef); - - public void addFilterDefinition(FilterDefinition filterDefinition); - - public void addIdGenerator(IdGenerator generator); - - public void registerIdentifierGenerator(String name, String clazz); - - public void addNamedNativeQuery(NamedSQLQueryDefinition def); - - public void addNamedQuery(NamedQueryDefinition def); - - public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition); - - // todo : this needs to move to AnnotationBindingContext - public void setGloballyQuotedIdentifiers(boolean b); - - public MetaAttributeContext getGlobalMetaAttributeContext(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java deleted file mode 100644 index cf375fb65a..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.hibernate.AssertionFailure; -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder; -import org.hibernate.metamodel.source.annotations.global.FilterDefBinder; -import org.hibernate.metamodel.source.annotations.global.IdGeneratorBinder; -import org.hibernate.metamodel.source.annotations.global.QueryBinder; -import org.hibernate.metamodel.source.annotations.global.TableBinder; -import org.hibernate.metamodel.source.annotations.global.TypeDefBinder; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; -import org.hibernate.metamodel.source.annotations.xml.mocker.EntityMappingsMocker; -import org.hibernate.metamodel.source.binder.Binder; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.internal.MetadataImpl; - -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; -import org.jboss.logging.Logger; - -/** - * Main class responsible to creating and binding the Hibernate meta-model from annotations. - * This binder only has to deal with the (jandex) annotation index/repository. XML configuration is already processed - * and pseudo annotations are created. - * - * @author Hardy Ferentschik - * @author Steve Ebersole - */ -public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProcessor { - private static final Logger LOG = Logger.getLogger( AnnotationMetadataSourceProcessorImpl.class ); - - private final MetadataImplementor metadata; - private AnnotationBindingContext bindingContext; - - public AnnotationMetadataSourceProcessorImpl(MetadataImpl metadata) { - this.metadata = metadata; - } - - @Override - @SuppressWarnings( { "unchecked" }) - public void prepare(MetadataSources sources) { - // create a jandex index from the annotated classes - Indexer indexer = new Indexer(); - for ( Class clazz : sources.getAnnotatedClasses() ) { - indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" ); - } - - // add package-info from the configured packages - for ( String packageName : sources.getAnnotatedPackages() ) { - indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" ); - } - - Index index = indexer.complete(); - - List> mappings = new ArrayList>(); - for ( JaxbRoot root : sources.getJaxbRootList() ) { - if ( root.getRoot() instanceof JaxbEntityMappings ) { - mappings.add( (JaxbRoot) root ); - } - } - if ( !mappings.isEmpty() ) { - index = parseAndUpdateIndex( mappings, index ); - } - - if ( index.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ) != null ) { - // todo : this needs to move to AnnotationBindingContext - // what happens right now is that specifying this in an orm.xml causes it to effect all orm.xmls - metadata.setGloballyQuotedIdentifiers( true ); - } - bindingContext = new AnnotationBindingContextImpl( metadata, index ); - } - - @Override - public void processIndependentMetadata(MetadataSources sources) { - assertBindingContextExists(); - TypeDefBinder.bind( bindingContext ); - } - - private void assertBindingContextExists() { - if ( bindingContext == null ) { - throw new AssertionFailure( "The binding context should exist. Has prepare been called!?" ); - } - } - - @Override - public void processTypeDependentMetadata(MetadataSources sources) { - assertBindingContextExists(); - IdGeneratorBinder.bind( bindingContext ); - } - - @Override - public void processMappingMetadata(MetadataSources sources, List processedEntityNames) { - assertBindingContextExists(); - // need to order our annotated entities into an order we can process - Set hierarchies = EntityHierarchyBuilder.createEntityHierarchies( bindingContext ); - - Binder binder = new Binder( bindingContext.getMetadataImplementor(), new ArrayList() ); - for ( EntityHierarchy hierarchy : hierarchies ) { - binder.processEntityHierarchy( hierarchy ); - } - } - - @Override - public void processMappingDependentMetadata(MetadataSources sources) { - TableBinder.bind( bindingContext ); - FetchProfileBinder.bind( bindingContext ); - QueryBinder.bind( bindingContext ); - FilterDefBinder.bind( bindingContext ); - } - - private Index parseAndUpdateIndex(List> mappings, Index annotationIndex) { - List list = new ArrayList( mappings.size() ); - for ( JaxbRoot jaxbRoot : mappings ) { - list.add( jaxbRoot.getRoot() ); - } - return new EntityMappingsMocker( list, annotationIndex, metadata.getServiceRegistry() ).mockNewIndex(); - } - - private void indexClass(Indexer indexer, String className) { - InputStream stream = metadata.getServiceRegistry().getService( ClassLoaderService.class ).locateResourceStream( - className - ); - try { - indexer.index( stream ); - } - catch ( IOException e ) { - throw new HibernateException( "Unable to open input stream for class " + className, e ); - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java deleted file mode 100644 index 8b1f1a49dc..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.beans.Introspector; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -/** - * Some helper methods for reflection tasks - * - * @author Hardy Ferentschik - */ -public class ReflectionHelper { - - private ReflectionHelper() { - } - - /** - * Process bean properties getter by applying the JavaBean naming conventions. - * - * @param member the member for which to get the property name. - * - * @return The bean method name with the "is" or "get" prefix stripped off, {@code null} - * the method name id not according to the JavaBeans standard. - */ - public static String getPropertyName(Member member) { - String name = null; - - if ( member instanceof Field ) { - name = member.getName(); - } - - if ( member instanceof Method ) { - String methodName = member.getName(); - if ( methodName.startsWith( "is" ) ) { - name = Introspector.decapitalize( methodName.substring( 2 ) ); - } - else if ( methodName.startsWith( "has" ) ) { - name = Introspector.decapitalize( methodName.substring( 3 ) ); - } - else if ( methodName.startsWith( "get" ) ) { - name = Introspector.decapitalize( methodName.substring( 3 ) ); - } - } - return name; - } - - public static boolean isProperty(Member m) { - if ( m instanceof Method ) { - Method method = (Method) m; - return !method.isSynthetic() - && !method.isBridge() - && !Modifier.isStatic( method.getModifiers() ) - && method.getParameterTypes().length == 0 - && ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) ); - } - else { - return !Modifier.isTransient( m.getModifiers() ) && !m.isSynthetic(); - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java deleted file mode 100644 index 8c81080eac..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.FetchType; - -import org.hibernate.FetchMode; -import org.hibernate.annotations.NotFoundAction; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl; -import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; - -/** - * Represents an association attribute. - * - * @author Hardy Ferentschik - * @todo Check whether we need further subclasses for different association types. Needs to evolve during development (HF) - */ -public class AssociationAttribute extends MappedAttribute { - private final AttributeNature associationNature; - private final boolean ignoreNotFound; - private final String referencedEntityType; - private final String mappedBy; - private final Set cascadeTypes; - private final boolean isOptional; - private final boolean isLazy; - private final boolean isOrphanRemoval; - private final FetchMode fetchMode; - private final boolean mapsId; - private final String referencedIdAttributeName; - - private boolean isInsertable = true; - private boolean isUpdatable = true; - private AttributeTypeResolver resolver; - - public static AssociationAttribute createAssociationAttribute(String name, - Class attributeType, - AttributeNature attributeNature, - String accessType, - Map> annotations, - EntityBindingContext context) { - return new AssociationAttribute( - name, - attributeType, - attributeNature, - accessType, - annotations, - context - ); - } - - private AssociationAttribute(String name, - Class javaType, - AttributeNature associationType, - String accessType, - Map> annotations, - EntityBindingContext context) { - super( name, javaType, accessType, annotations, context ); - this.associationNature = associationType; - this.ignoreNotFound = ignoreNotFound(); - - AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation( - annotations, - associationType.getAnnotationDotName() - ); - - // using jandex we don't really care which exact type of annotation we are dealing with - this.referencedEntityType = determineReferencedEntityType( associationAnnotation ); - this.mappedBy = determineMappedByAttributeName( associationAnnotation ); - this.isOptional = determineOptionality( associationAnnotation ); - this.isLazy = determineFetchType( associationAnnotation ); - this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation ); - this.cascadeTypes = determineCascadeTypes( associationAnnotation ); - - this.fetchMode = determineFetchMode(); - this.referencedIdAttributeName = determineMapsId(); - this.mapsId = referencedIdAttributeName != null; - } - - public boolean isIgnoreNotFound() { - return ignoreNotFound; - } - - public String getReferencedEntityType() { - return referencedEntityType; - } - - public String getMappedBy() { - return mappedBy; - } - - public AttributeNature getAssociationNature() { - return associationNature; - } - - public Set getCascadeTypes() { - return cascadeTypes; - } - - public boolean isOrphanRemoval() { - return isOrphanRemoval; - } - - public FetchMode getFetchMode() { - return fetchMode; - } - - public String getReferencedIdAttributeName() { - return referencedIdAttributeName; - } - - public boolean mapsId() { - return mapsId; - } - - @Override - public AttributeTypeResolver getHibernateTypeResolver() { - if ( resolver == null ) { - resolver = getDefaultHibernateTypeResolver(); - } - return resolver; - } - - @Override - public boolean isLazy() { - return isLazy; - } - - @Override - public boolean isOptional() { - return isOptional; - } - - @Override - public boolean isInsertable() { - return isInsertable; - } - - @Override - public boolean isUpdatable() { - return isUpdatable; - } - - @Override - public PropertyGeneration getPropertyGeneration() { - return PropertyGeneration.NEVER; - } - - private AttributeTypeResolver getDefaultHibernateTypeResolver() { - return new CompositeAttributeTypeResolver( new AttributeTypeResolverImpl( this ) ); - } - - private boolean ignoreNotFound() { - NotFoundAction action = NotFoundAction.EXCEPTION; - AnnotationInstance notFoundAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.NOT_FOUND - ); - if ( notFoundAnnotation != null ) { - AnnotationValue actionValue = notFoundAnnotation.value( "action" ); - if ( actionValue != null ) { - action = Enum.valueOf( NotFoundAction.class, actionValue.asEnum() ); - } - } - - return NotFoundAction.IGNORE.equals( action ); - } - - private boolean determineOptionality(AnnotationInstance associationAnnotation) { - boolean optional = true; - - AnnotationValue optionalValue = associationAnnotation.value( "optional" ); - if ( optionalValue != null ) { - optional = optionalValue.asBoolean(); - } - - return optional; - } - - private boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) { - boolean orphanRemoval = false; - AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" ); - if ( orphanRemovalValue != null ) { - orphanRemoval = orphanRemovalValue.asBoolean(); - } - return orphanRemoval; - } - - private boolean determineFetchType(AnnotationInstance associationAnnotation) { - boolean lazy = false; - AnnotationValue fetchValue = associationAnnotation.value( "fetch" ); - if ( fetchValue != null ) { - FetchType fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() ); - if ( FetchType.LAZY.equals( fetchType ) ) { - lazy = true; - } - } - return lazy; - } - - private String determineReferencedEntityType(AnnotationInstance associationAnnotation) { - String targetTypeName = getAttributeType().getName(); - - AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.TARGET - ); - if ( targetAnnotation != null ) { - targetTypeName = targetAnnotation.value().asClass().name().toString(); - } - - AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" ); - if ( targetEntityValue != null ) { - targetTypeName = targetEntityValue.asClass().name().toString(); - } - - return targetTypeName; - } - - private String determineMappedByAttributeName(AnnotationInstance associationAnnotation) { - String mappedBy = null; - AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" ); - if ( mappedByAnnotationValue != null ) { - mappedBy = mappedByAnnotationValue.asString(); - } - - return mappedBy; - } - - private Set determineCascadeTypes(AnnotationInstance associationAnnotation) { - Set cascadeTypes = new HashSet(); - AnnotationValue cascadeValue = associationAnnotation.value( "cascade" ); - if ( cascadeValue != null ) { - String[] cascades = cascadeValue.asEnumArray(); - for ( String s : cascades ) { - cascadeTypes.add( Enum.valueOf( CascadeType.class, s ) ); - } - } - return cascadeTypes; - } - - private FetchMode determineFetchMode() { - FetchMode mode = FetchMode.DEFAULT; - - AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.FETCH ); - if ( fetchAnnotation != null ) { - org.hibernate.annotations.FetchMode annotationFetchMode = JandexHelper.getEnumValue( - fetchAnnotation, - "value", - org.hibernate.annotations.FetchMode.class - ); - mode = EnumConversionHelper.annotationFetchModeToHibernateFetchMode( annotationFetchMode ); - } - - return mode; - } - - private String determineMapsId() { - String referencedIdAttributeName; - AnnotationInstance mapsIdAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.MAPS_ID ); - if ( mapsIdAnnotation == null ) { - return null; - } - - if ( !( AttributeNature.MANY_TO_ONE.equals( getAssociationNature() ) || AttributeNature.MANY_TO_ONE - .equals( getAssociationNature() ) ) ) { - throw new MappingException( - "@MapsId can only be specified on a many-to-one or one-to-one associations", - getContext().getOrigin() - ); - } - - referencedIdAttributeName = JandexHelper.getValue( mapsIdAnnotation, "value", String.class ); - - return referencedIdAttributeName; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java deleted file mode 100644 index 1f36ab1f58..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; - -/** - * Contains the information about a single {@link javax.persistence.AttributeOverride}. Instances of this class - * are creating during annotation processing and then applied onto the persistence attributes. - * - * @author Hardy Ferentschik - * @todo Take care of prefixes of the form 'element', 'key' and 'value'. Add another type enum to handle this. (HF) - */ -public class AttributeOverride { - private static final String PROPERTY_PATH_SEPARATOR = "."; - private final ColumnValues columnValues; - private final String attributePath; - - public AttributeOverride(AnnotationInstance attributeOverrideAnnotation) { - this( null, attributeOverrideAnnotation ); - } - - public AttributeOverride(String prefix, AnnotationInstance attributeOverrideAnnotation) { - if ( attributeOverrideAnnotation == null ) { - throw new IllegalArgumentException( "An AnnotationInstance needs to be passed" ); - } - - if ( !JPADotNames.ATTRIBUTE_OVERRIDE.equals( attributeOverrideAnnotation.name() ) ) { - throw new AssertionFailure( "A @AttributeOverride annotation needs to be passed to the constructor" ); - } - - columnValues = new ColumnValues( - JandexHelper.getValue( - attributeOverrideAnnotation, - "column", - AnnotationInstance.class - ) - ); - attributePath = createAttributePath( - prefix, - JandexHelper.getValue( attributeOverrideAnnotation, "name", String.class ) - ); - } - - public ColumnValues getColumnValues() { - return columnValues; - } - - public String getAttributePath() { - return attributePath; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "AttributeOverride" ); - sb.append( "{columnValues=" ).append( columnValues ); - sb.append( ", attributePath='" ).append( attributePath ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - AttributeOverride that = (AttributeOverride) o; - - if ( attributePath != null ? !attributePath.equals( that.attributePath ) : that.attributePath != null ) { - return false; - } - if ( columnValues != null ? !columnValues.equals( that.columnValues ) : that.columnValues != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = columnValues != null ? columnValues.hashCode() : 0; - result = 31 * result + ( attributePath != null ? attributePath.hashCode() : 0 ); - return result; - } - - private String createAttributePath(String prefix, String name) { - String path = ""; - if ( StringHelper.isNotEmpty( prefix ) ) { - path += prefix; - } - if ( StringHelper.isNotEmpty( path ) && !path.endsWith( PROPERTY_PATH_SEPARATOR ) ) { - path += PROPERTY_PATH_SEPARATOR; - } - path += name; - return path; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java deleted file mode 100644 index 232318662e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.internal.util.StringHelper; - -/** - * @author Hardy Ferentschik - */ -public class ColumnSourceImpl extends ColumnValuesSourceImpl { - private final MappedAttribute attribute; - private final String name; - - ColumnSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { - super( attribute.getColumnValues() ); - if ( attributeOverride != null ) { - setOverrideColumnValues( attributeOverride.getColumnValues() ); - } - this.attribute = attribute; - this.name = resolveColumnName(); - } - - protected String resolveColumnName() { - if ( StringHelper.isEmpty( super.getName() ) ) { - //no @Column defined. - return attribute.getContext().getNamingStrategy().propertyToColumnName( attribute.getName() ); - } - else { - return super.getName(); - } - } - - @Override - public String getName() { - return name; - } - - @Override - public String getReadFragment() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCustomReadFragment(); - } - else { - return null; - } - } - - @Override - public String getWriteFragment() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCustomWriteFragment(); - } - else { - return null; - } - } - - @Override - public String getCheckCondition() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCheckCondition(); - } - else { - return null; - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java deleted file mode 100644 index 16480cf0c0..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; - -/** - * @author Steve Ebersole - */ -public class ColumnValuesSourceImpl implements ColumnSource { - private ColumnValues columnValues; - - public ColumnValuesSourceImpl(ColumnValues columnValues) { - this.columnValues = columnValues; - } - - void setOverrideColumnValues(ColumnValues columnValues) { - this.columnValues = columnValues; - } - - @Override - public String getName() { - return columnValues.getName(); - } - - @Override - public boolean isNullable() { - return columnValues.isNullable(); - } - - @Override - public String getDefaultValue() { - return null; - } - - @Override - public String getSqlType() { - // todo - return null; - } - - @Override - public Datatype getDatatype() { - // todo - return null; - } - - @Override - public Size getSize() { - return new Size( - columnValues.getPrecision(), - columnValues.getScale(), - columnValues.getLength(), - Size.LobMultiplier.NONE - ); - } - - @Override - public boolean isUnique() { - return columnValues.isUnique(); - } - - @Override - public String getComment() { - // todo - return null; - } - - @Override - public boolean isIncludedInInsert() { - return columnValues.isInsertable(); - } - - @Override - public boolean isIncludedInUpdate() { - return columnValues.isUpdatable(); - } - - @Override - public String getContainingTableName() { - return columnValues.getTable(); - } - - - // these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getReadFragment() { - return null; - } - - @Override - public String getWriteFragment() { - return null; - } - - @Override - public String getCheckCondition() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java deleted file mode 100644 index 6c4b1d7ce5..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.Map; - -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; - -/** - * @author Strong Liu - */ -public class ExplicitHibernateTypeSourceImpl implements ExplicitHibernateTypeSource { - private final AttributeTypeResolver typeResolver; - - public ExplicitHibernateTypeSourceImpl(AttributeTypeResolver typeResolver) { - this.typeResolver = typeResolver; - } - - @Override - public String getName() { - return typeResolver.getExplicitHibernateTypeName(); - } - - @Override - public Map getParameters() { - return typeResolver.getExplicitHibernateTypeParameters(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java deleted file mode 100644 index 8daaee9048..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.hibernate.metamodel.source.annotations.attribute; - -/** - * @author Strong Liu - */ -public class FormulaValue { - private String tableName; - private final String expression; - - public FormulaValue(String tableName, String expression) { - this.tableName = tableName; - this.expression = expression; - } - - public String getExpression() { - return expression; - } - - public String getContainingTableName() { - return tableName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java deleted file mode 100644 index 758e2c6e04..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.List; -import java.util.Map; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.DotName; - -/** - * Base class for the different types of mapped attributes - * - * @author Hardy Ferentschik - */ -public abstract class MappedAttribute implements Comparable { - /** - * Annotations defined on the attribute, keyed against the annotation dot name. - */ - private final Map> annotations; - - /** - * The property name. - */ - private final String name; - - /** - * The java type of the attribute - */ - private final Class attributeType; - - /** - * The access type for this property. At the moment this is either 'field' or 'property', but Hibernate - * also allows custom named accessors (see {@link org.hibernate.property.PropertyAccessorFactory}). - */ - private final String accessType; - - /** - * Defines the column values (relational values) for this property. - */ - private ColumnValues columnValues; - - /** - * Is this property an id property (or part thereof). - */ - private final boolean isId; - - /** - * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic - * locking). - */ - private final boolean isOptimisticLockable; - - /** - * The binding context - */ - private final EntityBindingContext context; - - MappedAttribute(String name, Class attributeType, String accessType, Map> annotations, EntityBindingContext context) { - this.context = context; - this.annotations = annotations; - this.name = name; - this.attributeType = attributeType; - this.accessType = accessType; - - //if this attribute has either @Id or @EmbeddedId, then it is an id attribute - AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); - AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.EMBEDDED_ID - ); - isId = ( idAnnotation != null || embeddedIdAnnotation != null ); - - AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.COLUMN - ); - columnValues = new ColumnValues( columnAnnotation ); - - this.isOptimisticLockable = checkOptimisticLockAnnotation(); - } - - public String getName() { - return name; - } - - public final Class getAttributeType() { - return attributeType; - } - - public String getAccessType() { - return accessType; - } - - public EntityBindingContext getContext() { - return context; - } - - public Map> annotations() { - return annotations; - } - - public ColumnValues getColumnValues() { - return columnValues; - } - - public boolean isId() { - return isId; - } - - public boolean isOptimisticLockable() { - return isOptimisticLockable; - } - - @Override - public int compareTo(MappedAttribute mappedProperty) { - return name.compareTo( mappedProperty.getName() ); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "MappedAttribute" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } - - public abstract AttributeTypeResolver getHibernateTypeResolver(); - - public abstract boolean isLazy(); - - public abstract boolean isOptional(); - - public abstract boolean isInsertable(); - - public abstract boolean isUpdatable(); - - public abstract PropertyGeneration getPropertyGeneration(); - - private boolean checkOptimisticLockAnnotation() { - boolean triggersVersionIncrement = true; - AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.OPTIMISTIC_LOCK - ); - if ( optimisticLockAnnotation != null ) { - boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean(); - triggersVersionIncrement = !exclude; - } - return triggersVersionIncrement; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java deleted file mode 100644 index 3b97d0b62c..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class SingularAttributeSourceImpl implements SingularAttributeSource { - private final MappedAttribute attribute; - private final AttributeOverride attributeOverride; - - public SingularAttributeSourceImpl(MappedAttribute attribute) { - this(attribute, null); - } - - public SingularAttributeSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { - this.attribute = attribute; - this.attributeOverride = attributeOverride; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return new ExplicitHibernateTypeSourceImpl( attribute.getHibernateTypeResolver() ); - } - - @Override - public String getPropertyAccessorName() { - return attribute.getAccessType(); - } - - @Override - public boolean isInsertable() { - return attribute.isInsertable(); - } - - @Override - public boolean isUpdatable() { - return attribute.isUpdatable(); - } - - @Override - public PropertyGeneration getGeneration() { - return attribute.getPropertyGeneration(); - } - - @Override - public boolean isLazy() { - return attribute.isLazy(); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return attribute.isOptimisticLockable(); - } - - @Override - public String getName() { - return attribute.getName(); - } - - @Override - public List relationalValueSources() { - List valueSources = new ArrayList(); - valueSources.add( new ColumnSourceImpl( attribute, attributeOverride ) ); - return valueSources; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public Iterable metaAttributes() { - return Collections.emptySet(); - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java deleted file mode 100644 index 3eae19acdc..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.Set; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.ToOneAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource { - private final AssociationAttribute associationAttribute; - private final Set cascadeStyles; - - public ToOneAttributeSourceImpl(AssociationAttribute associationAttribute) { - super( associationAttribute ); - this.associationAttribute = associationAttribute; - this.cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( associationAttribute.getCascadeTypes() ); - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.MANY_TO_ONE; - } - - @Override - public String getReferencedEntityName() { - return associationAttribute.getReferencedEntityType(); - } - - @Override - public String getReferencedEntityAttributeName() { - return associationAttribute.getMappedBy(); - } - - @Override - public Iterable getCascadeStyles() { - return cascadeStyles; - } - - @Override - public FetchMode getFetchMode() { - return associationAttribute.getFetchMode(); - } - - @Override - public FetchTiming getFetchTiming() { - // todo : implement - return FetchTiming.IMMEDIATE; - } - - @Override - public FetchStyle getFetchStyle() { - // todo : implement - return FetchStyle.JOIN; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java deleted file mode 100644 index f163fe520c..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -/** - * @author Strong Liu - */ -public class AttributeTypeResolverImpl extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - - public AttributeTypeResolverImpl(MappedAttribute mappedAttribute) { - this.mappedAttribute = mappedAttribute; - } - - @Override - protected String resolveHibernateTypeName(AnnotationInstance typeAnnotation) { - String typeName = null; - if ( typeAnnotation != null ) { - typeName = JandexHelper.getValue( typeAnnotation, "type", String.class ); - } - return typeName; - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance typeAnnotation) { - HashMap typeParameters = new HashMap(); - AnnotationValue parameterAnnotationValue = typeAnnotation.value( "parameters" ); - if ( parameterAnnotationValue != null ) { - AnnotationInstance[] parameterAnnotations = parameterAnnotationValue.asNestedArray(); - for ( AnnotationInstance parameterAnnotationInstance : parameterAnnotations ) { - typeParameters.put( - JandexHelper.getValue( parameterAnnotationInstance, "name", String.class ), - JandexHelper.getValue( parameterAnnotationInstance, "value", String.class ) - ); - } - } - return typeParameters; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - HibernateDotNames.TYPE - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java deleted file mode 100644 index 79c80e9157..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.EnumType; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class EnumeratedTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - private final boolean isMapKey; - - public EnumeratedTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - this.isMapKey = false;//todo - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - JPADotNames.ENUMERATED - ); - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance enumeratedAnnotation) { - boolean isEnum = mappedAttribute.getAttributeType().isEnum(); - if ( !isEnum ) { - if ( enumeratedAnnotation != null ) { - throw new AnnotationException( "Attribute " + mappedAttribute.getName() + " is not a Enumerated type, but has a @Enumerated annotation." ); - } - else { - return null; - } - } - return EnumType.class.getName(); - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - HashMap typeParameters = new HashMap(); - typeParameters.put( EnumType.ENUM, mappedAttribute.getAttributeType().getName() ); - if ( annotationInstance != null ) { - javax.persistence.EnumType enumType = JandexHelper.getEnumValue( - annotationInstance, - "value", - javax.persistence.EnumType.class - ); - if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); - } - else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.VARCHAR ) ); - } - else { - throw new AssertionFailure( "Unknown EnumType: " + enumType ); - } - } - else { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); - } - return typeParameters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java deleted file mode 100644 index f0d405e903..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.io.Serializable; -import java.sql.Blob; -import java.sql.Clob; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.CharacterArrayClobType; -import org.hibernate.type.PrimitiveCharacterArrayClobType; -import org.hibernate.type.SerializableToBlobType; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.WrappedMaterializedBlobType; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class LobTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - - public LobTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( mappedAttribute.annotations(), JPADotNames.LOB ); - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance annotationInstance) { - if ( annotationInstance == null ) { - return null; - } - String type = null; - if ( Clob.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.CLOB.getName(); - } - else if ( Blob.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.BLOB.getName(); - } - else if ( String.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.MATERIALIZED_CLOB.getName(); - } - else if ( Character[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = CharacterArrayClobType.class.getName(); - } - else if ( char[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = PrimitiveCharacterArrayClobType.class.getName(); - } - else if ( Byte[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = WrappedMaterializedBlobType.class.getName(); - } - else if ( byte[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.MATERIALIZED_BLOB.getName(); - } - else if ( Serializable.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = SerializableToBlobType.class.getName(); - } - else { - type = "blob"; - } - return type; - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - if ( getExplicitHibernateTypeName().equals( SerializableToBlobType.class.getName() ) ) { - HashMap typeParameters = new HashMap(); - typeParameters.put( - SerializableToBlobType.CLASS_NAME, - mappedAttribute.getAttributeType().getName() - ); - return typeParameters; - } - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java deleted file mode 100644 index 41414aa63e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.Calendar; -import java.util.Date; -import javax.persistence.TemporalType; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.StandardBasicTypes; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class TemporalTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - private final boolean isMapKey; - - public TemporalTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - this.isMapKey = false;//todo - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance temporalAnnotation) { - - if ( isTemporalType( mappedAttribute.getAttributeType() ) ) { - if ( temporalAnnotation == null ) { - //SPEC 11.1.47 The Temporal annotation must be specified for persistent fields or properties of type java.util.Date and java.util.Calendar. - throw new AnnotationException( "Attribute " + mappedAttribute.getName() + " is a Temporal type, but no @Temporal annotation found." ); - } - TemporalType temporalType = JandexHelper.getEnumValue( temporalAnnotation, "value", TemporalType.class ); - boolean isDate = Date.class.isAssignableFrom( mappedAttribute.getAttributeType() ); - String type; - switch ( temporalType ) { - case DATE: - type = isDate ? StandardBasicTypes.DATE.getName() : StandardBasicTypes.CALENDAR_DATE.getName(); - break; - case TIME: - type = StandardBasicTypes.TIME.getName(); - if ( !isDate ) { - throw new NotYetImplementedException( "Calendar cannot persist TIME only" ); - } - break; - case TIMESTAMP: - type = isDate ? StandardBasicTypes.TIMESTAMP.getName() : StandardBasicTypes.CALENDAR.getName(); - break; - default: - throw new AssertionFailure( "Unknown temporal type: " + temporalType ); - } - return type; - } - else { - if ( temporalAnnotation != null ) { - throw new AnnotationException( - "@Temporal should only be set on a java.util.Date or java.util.Calendar property: " + mappedAttribute - .getName() - ); - } - } - return null; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - JPADotNames.TEMPORAL - ); - } - - private static boolean isTemporalType(Class type) { - return Date.class.isAssignableFrom( type ) || Calendar.class.isAssignableFrom( type ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java deleted file mode 100644 index b7331a26aa..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute.type; - -/** - * This package contains type binding code for basic attributes. - */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java deleted file mode 100644 index 3ab8e3d2c1..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.ToOneAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ComponentAttributeSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; - -/** - * Annotation backed implementation of {@code ComponentAttributeSource}. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class ComponentAttributeSourceImpl implements ComponentAttributeSource { - private static final String PATH_SEPERATOR = "."; - private final EmbeddableClass embeddableClass; - private final ValueHolder> classReference; - private final Map attributeOverrides; - private final String path; - - public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass, String parentPath, Map attributeOverrides) { - this.embeddableClass = embeddableClass; - this.classReference = new ValueHolder>( embeddableClass.getConfiguredClass() ); - this.attributeOverrides = attributeOverrides; - if ( StringHelper.isEmpty( parentPath ) ) { - path = embeddableClass.getEmbeddedAttributeName(); - } - else { - path = parentPath + "." + embeddableClass.getEmbeddedAttributeName(); - } - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.COMPONENT; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public String getClassName() { - return embeddableClass.getConfiguredClass().getName(); - } - - @Override - public ValueHolder> getClassReference() { - return classReference; - } - - @Override - public String getName() { - return embeddableClass.getEmbeddedAttributeName(); - } - - @Override - public String getExplicitTuplizerClassName() { - return embeddableClass.getCustomTuplizer(); - } - - @Override - public String getPropertyAccessorName() { - return embeddableClass.getClassAccessType().toString().toLowerCase(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return embeddableClass.getLocalBindingContext(); - } - - @Override - public Iterable attributeSources() { - List attributeList = new ArrayList(); - for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) { - AttributeOverride attributeOverride = null; - String tmp = getPath() + PATH_SEPERATOR + attribute.getName(); - if ( attributeOverrides.containsKey( tmp ) ) { - attributeOverride = attributeOverrides.get( tmp ); - } - attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) ); - } - for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) { - attributeList.add( - new ComponentAttributeSourceImpl( - embeddable, - getPath(), - createAggregatedOverrideMap() - ) - ); - } - for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes() ) { - attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); - } - return attributeList; - } - - @Override - public String getPath() { - return path; - } - - @Override - public String getParentReferenceAttributeName() { - return embeddableClass.getParentReferencingAttributeName(); - } - - @Override - public Iterable metaAttributes() { - // not relevant for annotations - return Collections.emptySet(); - } - - @Override - public List relationalValueSources() { - // none, they are defined on the simple sub-attributes - return null; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - // probably need to check for @Target in EmbeddableClass (HF) - return null; - } - - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return true; - } - - @Override - public PropertyGeneration getGeneration() { - return null; - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return true; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ComponentAttributeSourceImpl" ); - sb.append( "{embeddableClass=" ).append( embeddableClass.getConfiguredClass().getSimpleName() ); - sb.append( '}' ); - return sb.toString(); - } - - private Map createAggregatedOverrideMap() { - // add all overrides passed down to this instance - they override overrides ;-) which are defined further down - // the embeddable chain - Map aggregatedOverrideMap = new HashMap( - attributeOverrides - ); - - for ( Map.Entry entry : embeddableClass.getAttributeOverrideMap().entrySet() ) { - String fullPath = getPath() + PATH_SEPERATOR + entry.getKey(); - if ( !aggregatedOverrideMap.containsKey( fullPath ) ) { - aggregatedOverrideMap.put( fullPath, entry.getValue() ); - } - } - return aggregatedOverrideMap; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java deleted file mode 100644 index a2e8a60fed..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import javax.persistence.AccessType; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.ReflectionHelper; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.AttributeNature; -import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; -import org.jboss.logging.Logger; - -import com.fasterxml.classmate.ResolvedTypeWithMembers; -import com.fasterxml.classmate.members.HierarchicType; -import com.fasterxml.classmate.members.ResolvedMember; - -/** - * Base class for a configured entity, mapped super class or embeddable - * - * @author Hardy Ferentschik - */ -public class ConfiguredClass { - public static final Logger LOG = Logger.getLogger( ConfiguredClass.class.getName() ); - - /** - * The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy. - */ - private final ConfiguredClass parent; - - /** - * The Jandex class info for this configured class. Provides access to the annotation defined on this configured class. - */ - private final ClassInfo classInfo; - - /** - * The actual java type. - */ - private final Class clazz; - - /** - * The default access type for this entity - */ - private final AccessType classAccessType; - - /** - * The type of configured class, entity, mapped super class, embeddable, ... - */ - private final ConfiguredClassType configuredClassType; - - /** - * The id attributes - */ - private final Map idAttributeMap; - - /** - * The mapped association attributes for this entity - */ - private final Map associationAttributeMap; - - /** - * The mapped simple attributes for this entity - */ - private final Map simpleAttributeMap; - - /** - * The version attribute or {@code null} in case none exists. - */ - private BasicAttribute versionAttribute; - - /** - * The embedded classes for this entity - */ - private final Map embeddedClasses = new HashMap(); - - /** - * A map of all attribute overrides defined in this class. The override name is "normalised", meaning as if specified - * on class level. If the override is specified on attribute level the attribute name is used as prefix. - */ - private final Map attributeOverrideMap; - - private final Set transientFieldNames = new HashSet(); - private final Set transientMethodNames = new HashSet(); - - /** - * Fully qualified name of a custom tuplizer - */ - private final String customTuplizer; - - private final EntityBindingContext localBindingContext; - - public ConfiguredClass( - ClassInfo classInfo, - AccessType defaultAccessType, - ConfiguredClass parent, - AnnotationBindingContext context) { - this.parent = parent; - this.classInfo = classInfo; - this.clazz = context.locateClassByName( classInfo.toString() ); - this.configuredClassType = determineType(); - this.classAccessType = determineClassAccessType( defaultAccessType ); - this.customTuplizer = determineCustomTuplizer(); - - this.simpleAttributeMap = new TreeMap(); - this.idAttributeMap = new TreeMap(); - this.associationAttributeMap = new TreeMap(); - - this.localBindingContext = new EntityBindingContext( context, this ); - - collectAttributes(); - attributeOverrideMap = Collections.unmodifiableMap( findAttributeOverrides() ); - } - - public String getName() { - return clazz.getName(); - } - - public Class getConfiguredClass() { - return clazz; - } - - public ClassInfo getClassInfo() { - return classInfo; - } - - public ConfiguredClass getParent() { - return parent; - } - - public EntityBindingContext getLocalBindingContext() { - return localBindingContext; - } - - public Iterable getSimpleAttributes() { - return simpleAttributeMap.values(); - } - - public Iterable getIdAttributes() { - return idAttributeMap.values(); - } - - public BasicAttribute getVersionAttribute() { - return versionAttribute; - } - - public Iterable getAssociationAttributes() { - return associationAttributeMap.values(); - } - - public Map getEmbeddedClasses() { - return embeddedClasses; - } - - public Map getAttributeOverrideMap() { - return attributeOverrideMap; - } - - public AccessType getClassAccessType() { - return classAccessType; - } - - public String getCustomTuplizer() { - return customTuplizer; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ConfiguredClass" ); - sb.append( "{clazz=" ).append( clazz.getSimpleName() ); - sb.append( '}' ); - return sb.toString(); - } - - private ConfiguredClassType determineType() { - if ( classInfo.annotations().containsKey( JPADotNames.ENTITY ) ) { - return ConfiguredClassType.ENTITY; - } - else if ( classInfo.annotations().containsKey( JPADotNames.MAPPED_SUPERCLASS ) ) { - return ConfiguredClassType.MAPPED_SUPERCLASS; - } - else if ( classInfo.annotations().containsKey( JPADotNames.EMBEDDABLE ) ) { - return ConfiguredClassType.EMBEDDABLE; - } - else { - return ConfiguredClassType.NON_ENTITY; - } - } - - private AccessType determineClassAccessType(AccessType defaultAccessType) { - // default to the hierarchy access type to start with - AccessType accessType = defaultAccessType; - - AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ACCESS ); - if ( accessAnnotation != null && accessAnnotation.target().getClass().equals( ClassInfo.class ) ) { - accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); - } - - return accessType; - } - - /** - * Find all attributes for this configured class and add them to the corresponding map - */ - private void collectAttributes() { - // find transient field and method names - findTransientFieldAndMethodNames(); - - // use the class mate library to generic types - ResolvedTypeWithMembers resolvedType = localBindingContext.resolveMemberTypes( - localBindingContext.getResolvedType( - clazz - ) - ); - for ( HierarchicType hierarchicType : resolvedType.allTypesAndOverrides() ) { - if ( hierarchicType.getType().getErasedType().equals( clazz ) ) { - resolvedType = localBindingContext.resolveMemberTypes( hierarchicType.getType() ); - break; - } - } - - if ( resolvedType == null ) { - throw new AssertionFailure( "Unable to resolve types for " + clazz.getName() ); - } - - Set explicitlyConfiguredMemberNames = createExplicitlyConfiguredAccessProperties( resolvedType ); - - if ( AccessType.FIELD.equals( classAccessType ) ) { - Field fields[] = clazz.getDeclaredFields(); - Field.setAccessible( fields, true ); - for ( Field field : fields ) { - if ( isPersistentMember( transientFieldNames, explicitlyConfiguredMemberNames, field ) ) { - createMappedAttribute( field, resolvedType, AccessType.FIELD ); - } - } - } - else { - Method[] methods = clazz.getDeclaredMethods(); - Method.setAccessible( methods, true ); - for ( Method method : methods ) { - if ( isPersistentMember( transientMethodNames, explicitlyConfiguredMemberNames, method ) ) { - createMappedAttribute( method, resolvedType, AccessType.PROPERTY ); - } - } - } - } - - private boolean isPersistentMember(Set transientNames, Set explicitlyConfiguredMemberNames, Member member) { - if ( !ReflectionHelper.isProperty( member ) ) { - return false; - } - - if ( transientNames.contains( member.getName() ) ) { - return false; - } - - if ( explicitlyConfiguredMemberNames.contains( ReflectionHelper.getPropertyName( member ) ) ) { - return false; - } - - return true; - } - - /** - * Creates {@code MappedProperty} instances for the explicitly configured persistent properties - * - * @param resolvedMembers the resolved type parameters for this class - * - * @return the property names of the explicitly configured attribute names in a set - */ - private Set createExplicitlyConfiguredAccessProperties(ResolvedTypeWithMembers resolvedMembers) { - Set explicitAccessPropertyNames = new HashSet(); - - List accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS ); - if ( accessAnnotations == null ) { - return explicitAccessPropertyNames; - } - - // iterate over all @Access annotations defined on the current class - for ( AnnotationInstance accessAnnotation : accessAnnotations ) { - // we are only interested at annotations defined on fields and methods - AnnotationTarget annotationTarget = accessAnnotation.target(); - if ( !( annotationTarget.getClass().equals( MethodInfo.class ) || annotationTarget.getClass() - .equals( FieldInfo.class ) ) ) { - continue; - } - - AccessType accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); - - if ( !isExplicitAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ) ) { - continue; - } - - // the placement is correct, get the member - Member member; - if ( annotationTarget instanceof MethodInfo ) { - Method m; - try { - m = clazz.getMethod( ( (MethodInfo) annotationTarget ).name() ); - } - catch ( NoSuchMethodException e ) { - throw new HibernateException( - "Unable to load method " - + ( (MethodInfo) annotationTarget ).name() - + " of class " + clazz.getName() - ); - } - member = m; - accessType = AccessType.PROPERTY; - } - else { - Field f; - try { - f = clazz.getField( ( (FieldInfo) annotationTarget ).name() ); - } - catch ( NoSuchFieldException e ) { - throw new HibernateException( - "Unable to load field " - + ( (FieldInfo) annotationTarget ).name() - + " of class " + clazz.getName() - ); - } - member = f; - accessType = AccessType.FIELD; - } - if ( ReflectionHelper.isProperty( member ) ) { - createMappedAttribute( member, resolvedMembers, accessType ); - explicitAccessPropertyNames.add( ReflectionHelper.getPropertyName( member ) ); - } - } - return explicitAccessPropertyNames; - } - - private boolean isExplicitAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) { - // when the access type of the class is FIELD - // overriding access annotations must be placed on properties AND have the access type PROPERTY - if ( AccessType.FIELD.equals( classAccessType ) ) { - if ( !( annotationTarget instanceof MethodInfo ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter)", classInfo.name().toString() - ); - return false; - } - - if ( !AccessType.PROPERTY.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + - "Using AccessType.FIELD on the property has no effect", - classInfo.name().toString() - ); - return false; - } - } - - // when the access type of the class is PROPERTY - // overriding access annotations must be placed on fields and have the access type FIELD - if ( AccessType.PROPERTY.equals( classAccessType ) ) { - if ( !( annotationTarget instanceof FieldInfo ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field ", classInfo.name().toString() - ); - return false; - } - - if ( !AccessType.FIELD.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field with an access type of AccessType.FIELD. " + - "Using AccessType.PROPERTY on the field has no effect", - classInfo.name().toString() - ); - return false; - } - } - return true; - } - - private void createMappedAttribute(Member member, ResolvedTypeWithMembers resolvedType, AccessType accessType) { - final String attributeName = ReflectionHelper.getPropertyName( member ); - ResolvedMember[] resolvedMembers; - if ( member instanceof Field ) { - resolvedMembers = resolvedType.getMemberFields(); - } - else { - resolvedMembers = resolvedType.getMemberMethods(); - } - Class attributeType = (Class) findResolvedType( member.getName(), resolvedMembers ); - final Map> annotations = JandexHelper.getMemberAnnotations( - classInfo, member.getName() - ); - - AttributeNature attributeNature = determineAttributeNature( annotations ); - String accessTypeString = accessType.toString().toLowerCase(); - switch ( attributeNature ) { - case BASIC: { - BasicAttribute attribute = BasicAttribute.createSimpleAttribute( - attributeName, attributeType, annotations, accessTypeString, getLocalBindingContext() - ); - if ( attribute.isId() ) { - idAttributeMap.put( attributeName, attribute ); - } - else if ( attribute.isVersioned() ) { - if ( versionAttribute == null ) { - versionAttribute = attribute; - } - else { - throw new MappingException( "Multiple version attributes", localBindingContext.getOrigin() ); - } - } - else { - simpleAttributeMap.put( attributeName, attribute ); - } - break; - } - case ELEMENT_COLLECTION: { - throw new NotYetImplementedException( "Element collections must still be implemented." ); - } - case EMBEDDED_ID: { - throw new NotYetImplementedException( "Embedded ids must still be implemented." ); - } - case EMBEDDED: { - AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.TARGET - ); - if ( targetAnnotation != null ) { - attributeType = localBindingContext.locateClassByName( - JandexHelper.getValue( targetAnnotation, "value", String.class ) - ); - } - resolveEmbeddable( attributeName, attributeType ); - break; - } - // OneToOne, OneToMany, ManyToOne, ManyToMany - default: { - AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute( - attributeName, - attributeType, - attributeNature, - accessTypeString, - annotations, - getLocalBindingContext() - ); - associationAttributeMap.put( attributeName, attribute ); - } - } - } - - private void resolveEmbeddable(String attributeName, Class type) { - ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() ); - if ( embeddableClassInfo == null ) { - String msg = String.format( - "Attribute '%s#%s' is annotated with @Embedded, but '%s' does not seem to be annotated " + - "with @Embeddable. Are all annotated classes added to the configuration?", - getConfiguredClass().getSimpleName(), - attributeName, - type.getSimpleName() - ); - throw new AnnotationException( msg ); - } - - localBindingContext.resolveAllTypes( type.getName() ); - EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy( - localBindingContext.locateClassByName( embeddableClassInfo.toString() ), - attributeName, - classAccessType, - localBindingContext - ); - embeddedClasses.put( attributeName, hierarchy.getLeaf() ); - } - - /** - * Given the annotations defined on a persistent attribute this methods determines the attribute type. - * - * @param annotations the annotations defined on the persistent attribute - * - * @return an instance of the {@code AttributeType} enum - */ - private AttributeNature determineAttributeNature(Map> annotations) { - EnumMap discoveredAttributeTypes = - new EnumMap( AttributeNature.class ); - - AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ); - if ( oneToOne != null ) { - discoveredAttributeTypes.put( AttributeNature.ONE_TO_ONE, oneToOne ); - } - - AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ); - if ( oneToMany != null ) { - discoveredAttributeTypes.put( AttributeNature.ONE_TO_MANY, oneToMany ); - } - - AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ); - if ( manyToOne != null ) { - discoveredAttributeTypes.put( AttributeNature.MANY_TO_ONE, manyToOne ); - } - - AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ); - if ( manyToMany != null ) { - discoveredAttributeTypes.put( AttributeNature.MANY_TO_MANY, manyToMany ); - } - - AnnotationInstance embedded = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED ); - if ( embedded != null ) { - discoveredAttributeTypes.put( AttributeNature.EMBEDDED, embedded ); - } - - AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); - if ( embeddedId != null ) { - discoveredAttributeTypes.put( AttributeNature.EMBEDDED_ID, embeddedId ); - } - - AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.ELEMENT_COLLECTION - ); - if ( elementCollection != null ) { - discoveredAttributeTypes.put( AttributeNature.ELEMENT_COLLECTION, elementCollection ); - } - - if ( discoveredAttributeTypes.size() == 0 ) { - return AttributeNature.BASIC; - } - else if ( discoveredAttributeTypes.size() == 1 ) { - return discoveredAttributeTypes.keySet().iterator().next(); - } - else { - throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() ); - } - } - - private Type findResolvedType(String name, ResolvedMember[] resolvedMembers) { - for ( ResolvedMember resolvedMember : resolvedMembers ) { - if ( resolvedMember.getName().equals( name ) ) { - return resolvedMember.getType().getErasedType(); - } - } - throw new AssertionFailure( - String.format( - "Unable to resolve type of attribute %s of class %s", - name, - classInfo.name().toString() - ) - ); - } - - /** - * Populates the sets of transient field and method names. - */ - private void findTransientFieldAndMethodNames() { - List transientMembers = classInfo.annotations().get( JPADotNames.TRANSIENT ); - if ( transientMembers == null ) { - return; - } - - for ( AnnotationInstance transientMember : transientMembers ) { - AnnotationTarget target = transientMember.target(); - if ( target instanceof FieldInfo ) { - transientFieldNames.add( ( (FieldInfo) target ).name() ); - } - else { - transientMethodNames.add( ( (MethodInfo) target ).name() ); - } - } - } - - private Map findAttributeOverrides() { - Map attributeOverrideList = new HashMap(); - - AnnotationInstance attributeOverrideAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ATTRIBUTE_OVERRIDE - ); - if ( attributeOverrideAnnotation != null ) { - String prefix = createPathPrefix( attributeOverrideAnnotation.target() ); - AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation ); - attributeOverrideList.put( override.getAttributePath(), override ); - } - - AnnotationInstance attributeOverridesAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ATTRIBUTE_OVERRIDES - ); - if ( attributeOverridesAnnotation != null ) { - AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray(); - for ( AnnotationInstance annotationInstance : annotationInstances ) { - String prefix = createPathPrefix( attributeOverridesAnnotation.target() ); - AttributeOverride override = new AttributeOverride( prefix, annotationInstance ); - attributeOverrideList.put( override.getAttributePath(), override ); - } - } - return attributeOverrideList; - } - - private String createPathPrefix(AnnotationTarget target) { - String prefix = null; - if ( target instanceof FieldInfo || target instanceof MethodInfo ) { - prefix = JandexHelper.getPropertyName( target ); - } - return prefix; - } - - private List findAssociationOverrides() { - List associationOverrideList = new ArrayList(); - - AnnotationInstance associationOverrideAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDE - ); - if ( associationOverrideAnnotation != null ) { - associationOverrideList.add( associationOverrideAnnotation ); - } - - AnnotationInstance associationOverridesAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDES - ); - if ( associationOverrideAnnotation != null ) { - AnnotationInstance[] attributeOverride = associationOverridesAnnotation.value().asNestedArray(); - Collections.addAll( associationOverrideList, attributeOverride ); - } - - return associationOverrideList; - } - - private String determineCustomTuplizer() { - final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation( - classInfo, HibernateDotNames.TUPLIZERS - ); - if ( tuplizersAnnotation == null ) { - return null; - } - - AnnotationInstance[] annotations = JandexHelper.getValue( - tuplizersAnnotation, - "value", - AnnotationInstance[].class - ); - - AnnotationInstance pojoTuplizerAnnotation = null; - for ( AnnotationInstance tuplizerAnnotation : annotations ) { - if ( EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() ) == EntityMode.POJO ) { - pojoTuplizerAnnotation = tuplizerAnnotation; - break; - } - } - - String customTuplizer = null; - if ( pojoTuplizerAnnotation != null ) { - customTuplizer = pojoTuplizerAnnotation.value( "impl" ).asString(); - } - return customTuplizer; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java deleted file mode 100644 index ce162b0fef..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.AccessType; - -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; - -/** - * Represents the information about an entity annotated with {@code @Embeddable}. - * - * @author Hardy Ferentschik - */ -public class EmbeddableClass extends ConfiguredClass { - private final String embeddedAttributeName; - private final String parentReferencingAttributeName; - - public EmbeddableClass( - ClassInfo classInfo, - String embeddedAttributeName, - ConfiguredClass parent, - AccessType defaultAccessType, - AnnotationBindingContext context) { - super( classInfo, defaultAccessType, parent, context ); - this.embeddedAttributeName = embeddedAttributeName; - this.parentReferencingAttributeName = checkParentAnnotation(); - } - - private String checkParentAnnotation() { - AnnotationInstance parentAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.PARENT - ); - if ( parentAnnotation == null ) { - return null; - } - else { - return JandexHelper.getPropertyName( parentAnnotation.target() ); - } - } - - public String getEmbeddedAttributeName() { - return embeddedAttributeName; - } - - public String getParentReferencingAttributeName() { - return parentReferencingAttributeName; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java deleted file mode 100644 index d873e89a17..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java +++ /dev/null @@ -1,986 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.AccessType; -import javax.persistence.DiscriminatorType; -import javax.persistence.PersistenceException; -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostRemove; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; - -import org.hibernate.AnnotationException; -import org.hibernate.MappingException; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.annotations.OptimisticLockType; -import org.hibernate.annotations.PolymorphismType; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.ColumnValues; -import org.hibernate.metamodel.source.annotations.attribute.FormulaValue; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.TableSource; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; -import org.jboss.jandex.Type.Kind; - -/** - * Represents an entity or mapped superclass configured via annotations/orm-xml. - * - * @author Hardy Ferentschik - */ -public class EntityClass extends ConfiguredClass { - private final IdType idType; - private final InheritanceType inheritanceType; - - private final String explicitEntityName; - private final String customLoaderQueryName; - private final List synchronizedTableNames; - private final int batchSize; - - private final TableSource primaryTableSource; - private final Set secondaryTableSources; - private final Set constraintSources; - - private boolean isMutable; - private boolean isExplicitPolymorphism; - private OptimisticLockStyle optimisticLockStyle; - private String whereClause; - private String rowId; - private Caching caching; - private boolean isDynamicInsert; - private boolean isDynamicUpdate; - private boolean isSelectBeforeUpdate; - private String customPersister; - - private CustomSQL customInsert; - private CustomSQL customUpdate; - private CustomSQL customDelete; - - private boolean isLazy; - private String proxy; - - private ColumnValues discriminatorColumnValues; - private FormulaValue discriminatorFormula; - private Class discriminatorType; - private String discriminatorMatchValue; - private boolean isDiscriminatorForced = true; - private boolean isDiscriminatorIncludedInSql = true; - - private final List jpaCallbacks; - - public EntityClass( - ClassInfo classInfo, - EntityClass parent, - AccessType hierarchyAccessType, - InheritanceType inheritanceType, - AnnotationBindingContext context) { - super( classInfo, hierarchyAccessType, parent, context ); - this.inheritanceType = inheritanceType; - this.idType = determineIdType(); - boolean hasOwnTable = definesItsOwnTable(); - this.explicitEntityName = determineExplicitEntityName(); - this.constraintSources = new HashSet(); - - if ( hasOwnTable ) { - AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.TABLE - ); - this.primaryTableSource = createTableSource( tableAnnotation ); - } - else { - this.primaryTableSource = null; - } - - this.secondaryTableSources = createSecondaryTableSources(); - this.customLoaderQueryName = determineCustomLoader(); - this.synchronizedTableNames = determineSynchronizedTableNames(); - this.batchSize = determineBatchSize(); - this.jpaCallbacks = determineEntityListeners(); - - processHibernateEntitySpecificAnnotations(); - processCustomSqlAnnotations(); - processProxyGeneration(); - processDiscriminator(); - } - - public ColumnValues getDiscriminatorColumnValues() { - return discriminatorColumnValues; - } - - public FormulaValue getDiscriminatorFormula() { - return discriminatorFormula; - } - - public Class getDiscriminatorType() { - return discriminatorType; - } - - public IdType getIdType() { - return idType; - } - - public boolean isExplicitPolymorphism() { - return isExplicitPolymorphism; - } - - public boolean isMutable() { - return isMutable; - } - - public OptimisticLockStyle getOptimisticLockStyle() { - return optimisticLockStyle; - } - - public String getWhereClause() { - return whereClause; - } - - public String getRowId() { - return rowId; - } - - public Caching getCaching() { - return caching; - } - - public TableSource getPrimaryTableSource() { - if ( definesItsOwnTable() ) { - return primaryTableSource; - } - else { - return ( (EntityClass) getParent() ).getPrimaryTableSource(); - } - } - - public Set getSecondaryTableSources() { - return secondaryTableSources; - } - - public Set getConstraintSources() { - return constraintSources; - } - - public String getExplicitEntityName() { - return explicitEntityName; - } - - public String getEntityName() { - return getConfiguredClass().getSimpleName(); - } - - public boolean isDynamicInsert() { - return isDynamicInsert; - } - - public boolean isDynamicUpdate() { - return isDynamicUpdate; - } - - public boolean isSelectBeforeUpdate() { - return isSelectBeforeUpdate; - } - - public String getCustomLoaderQueryName() { - return customLoaderQueryName; - } - - public CustomSQL getCustomInsert() { - return customInsert; - } - - public CustomSQL getCustomUpdate() { - return customUpdate; - } - - public CustomSQL getCustomDelete() { - return customDelete; - } - - public List getSynchronizedTableNames() { - return synchronizedTableNames; - } - - public String getCustomPersister() { - return customPersister; - } - - public boolean isLazy() { - return isLazy; - } - - public String getProxy() { - return proxy; - } - - public int getBatchSize() { - return batchSize; - } - - public boolean isEntityRoot() { - return getParent() == null; - } - - public boolean isDiscriminatorForced() { - return isDiscriminatorForced; - } - - public boolean isDiscriminatorIncludedInSql() { - return isDiscriminatorIncludedInSql; - } - - public String getDiscriminatorMatchValue() { - return discriminatorMatchValue; - } - - public List getJpaCallbacks() { - return jpaCallbacks; - } - - private String determineExplicitEntityName() { - final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.ENTITY - ); - return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class ); - } - - - private boolean definesItsOwnTable() { - return !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) || isEntityRoot(); - } - - private IdType determineIdType() { - List idAnnotations = findIdAnnotations( JPADotNames.ID ); - List embeddedIdAnnotations = findIdAnnotations( JPADotNames.EMBEDDED_ID ); - - if ( !idAnnotations.isEmpty() && !embeddedIdAnnotations.isEmpty() ) { - throw new MappingException( - "@EmbeddedId and @Id cannot be used together. Check the configuration for " + getName() + "." - ); - } - - if ( !embeddedIdAnnotations.isEmpty() ) { - if ( embeddedIdAnnotations.size() == 1 ) { - return IdType.EMBEDDED; - } - else { - throw new AnnotationException( "Multiple @EmbeddedId annotations are not allowed" ); - } - } - - if ( !idAnnotations.isEmpty() ) { - return idAnnotations.size() == 1 ? IdType.SIMPLE : IdType.COMPOSED; - } - return IdType.NONE; - } - - private List findIdAnnotations(DotName idAnnotationType) { - List idAnnotationList = new ArrayList(); - if ( getClassInfo().annotations().containsKey( idAnnotationType ) ) { - idAnnotationList.addAll( getClassInfo().annotations().get( idAnnotationType ) ); - } - ConfiguredClass parent = getParent(); - while ( parent != null ) { - if ( parent.getClassInfo().annotations().containsKey( idAnnotationType ) ) { - idAnnotationList.addAll( parent.getClassInfo().annotations().get( idAnnotationType ) ); - } - parent = parent.getParent(); - } - return idAnnotationList; - } - - private void processDiscriminator() { - if ( !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) { - return; - } - - final AnnotationInstance discriminatorValueAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.DISCRIMINATOR_VALUE - ); - if ( discriminatorValueAnnotation != null ) { - this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); - } - - final AnnotationInstance discriminatorColumnAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN - ); - - final AnnotationInstance discriminatorFormulaAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.DISCRIMINATOR_FORMULA - ); - - - Class type = String.class; // string is the discriminator default - if ( discriminatorFormulaAnnotation != null ) { - String expression = JandexHelper.getValue( discriminatorFormulaAnnotation, "value", String.class ); - discriminatorFormula = new FormulaValue( getPrimaryTableSource().getExplicitTableName(), expression ); - } - discriminatorColumnValues = new ColumnValues( null ); //(stliu) give null here, will populate values below - discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null - if ( discriminatorColumnAnnotation != null ) { - - DiscriminatorType discriminatorType = Enum.valueOf( - DiscriminatorType.class, discriminatorColumnAnnotation.value( "discriminatorType" ).asEnum() - ); - switch ( discriminatorType ) { - case STRING: { - type = String.class; - break; - } - case CHAR: { - type = Character.class; - break; - } - case INTEGER: { - type = Integer.class; - break; - } - default: { - throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); - } - } - - discriminatorColumnValues.setName( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "name", - String.class - ) - ); - discriminatorColumnValues.setLength( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "length", - Integer.class - ) - ); - discriminatorColumnValues.setColumnDefinition( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "columnDefinition", - String.class - ) - ); - } - discriminatorType = type; - - AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.DISCRIMINATOR_OPTIONS - ); - if ( discriminatorOptionsAnnotation != null ) { - isDiscriminatorForced = discriminatorOptionsAnnotation.value( "force" ).asBoolean(); - isDiscriminatorIncludedInSql = discriminatorOptionsAnnotation.value( "insert" ).asBoolean(); - } - else { - isDiscriminatorForced = false; - isDiscriminatorIncludedInSql = true; - } - } - - private void processHibernateEntitySpecificAnnotations() { - final AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.ENTITY - ); - - // see HHH-6400 - PolymorphismType polymorphism = PolymorphismType.IMPLICIT; - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "polymorphism" ) != null ) { - polymorphism = PolymorphismType.valueOf( hibernateEntityAnnotation.value( "polymorphism" ).asEnum() ); - } - isExplicitPolymorphism = polymorphism == PolymorphismType.EXPLICIT; - - // see HHH-6401 - OptimisticLockType optimisticLockType = OptimisticLockType.VERSION; - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "optimisticLock" ) != null ) { - optimisticLockType = OptimisticLockType.valueOf( - hibernateEntityAnnotation.value( "optimisticLock" ) - .asEnum() - ); - } - optimisticLockStyle = OptimisticLockStyle.valueOf( optimisticLockType.name() ); - - final AnnotationInstance hibernateImmutableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.IMMUTABLE - ); - isMutable = hibernateImmutableAnnotation == null - && hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "mutable" ) != null - && hibernateEntityAnnotation.value( "mutable" ).asBoolean(); - - - final AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.WHERE - ); - whereClause = whereAnnotation != null && whereAnnotation.value( "clause" ) != null ? - whereAnnotation.value( "clause" ).asString() : null; - - final AnnotationInstance rowIdAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.ROW_ID - ); - rowId = rowIdAnnotation != null && rowIdAnnotation.value() != null - ? rowIdAnnotation.value().asString() : null; - - caching = determineCachingSettings(); - - // see HHH-6397 - isDynamicInsert = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "dynamicInsert" ) != null - && hibernateEntityAnnotation.value( "dynamicInsert" ).asBoolean(); - - // see HHH-6398 - isDynamicUpdate = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "dynamicUpdate" ) != null - && hibernateEntityAnnotation.value( "dynamicUpdate" ).asBoolean(); - - - // see HHH-6399 - isSelectBeforeUpdate = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "selectBeforeUpdate" ) != null - && hibernateEntityAnnotation.value( "selectBeforeUpdate" ).asBoolean(); - - // Custom persister - final String entityPersisterClass; - final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.PERSISTER - ); - if ( persisterAnnotation == null || persisterAnnotation.value( "impl" ) == null ) { - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "persister" ) != null ) { - entityPersisterClass = hibernateEntityAnnotation.value( "persister" ).asString(); - } - else { - entityPersisterClass = null; - } - } - else { - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "persister" ) != null ) { - // todo : error? - } - entityPersisterClass = persisterAnnotation.value( "impl" ).asString(); - } - this.customPersister = entityPersisterClass; - } - - private Caching determineCachingSettings() { - final AnnotationInstance hibernateCacheAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.CACHE - ); - if ( hibernateCacheAnnotation != null ) { - final org.hibernate.cache.spi.access.AccessType accessType = hibernateCacheAnnotation.value( "usage" ) == null - ? getLocalBindingContext().getMappingDefaults().getCacheAccessType() - : CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() ) - .toAccessType(); - return new Caching( - hibernateCacheAnnotation.value( "region" ) == null - ? getName() - : hibernateCacheAnnotation.value( "region" ).asString(), - accessType, - hibernateCacheAnnotation.value( "include" ) != null - && "all".equals( hibernateCacheAnnotation.value( "include" ).asString() ) - ); - } - - final AnnotationInstance jpaCacheableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.CACHEABLE - ); - - boolean cacheable = true; // true is the default - if ( jpaCacheableAnnotation != null && jpaCacheableAnnotation.value() != null ) { - cacheable = jpaCacheableAnnotation.value().asBoolean(); - } - - final boolean doCaching; - switch ( getLocalBindingContext().getMetadataImplementor().getOptions().getSharedCacheMode() ) { - case ALL: { - doCaching = true; - break; - } - case ENABLE_SELECTIVE: { - doCaching = cacheable; - break; - } - case DISABLE_SELECTIVE: { - doCaching = jpaCacheableAnnotation == null || cacheable; - break; - } - default: { - // treat both NONE and UNSPECIFIED the same - doCaching = false; - break; - } - } - - if ( !doCaching ) { - return null; - } - - return new Caching( - getName(), - getLocalBindingContext().getMappingDefaults().getCacheAccessType(), - true - ); - } - - /** - * todo see {@code Binder#createTable} - * - * @param tableAnnotation a annotation instance, either {@link javax.persistence.Table} or {@link javax.persistence.SecondaryTable} - * - * @return A table source for the specified annotation instance - */ - private TableSource createTableSource(AnnotationInstance tableAnnotation) { - String schema = null; - String catalog = null; - if ( tableAnnotation != null ) { - schema = JandexHelper.getValue( tableAnnotation, "schema", String.class ); - catalog = JandexHelper.getValue( tableAnnotation, "catalog", String.class ); - } - // process the table name - String tableName = null; - String logicalTableName = null; - - if ( tableAnnotation != null ) { - logicalTableName = JandexHelper.getValue( tableAnnotation, "name", String.class ); - if ( StringHelper.isNotEmpty( logicalTableName ) ) { - tableName = logicalTableName; - } - createUniqueConstraints( tableAnnotation, tableName ); - } - - TableSourceImpl tableSourceImpl; - if ( tableAnnotation == null || JPADotNames.TABLE.equals( tableAnnotation.name() ) ) { - // for the main table @Table we use 'null' as logical name - tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, null ); - } - else { - // for secondary tables a name must be specified which is used as logical table name - tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, logicalTableName ); - } - return tableSourceImpl; - } - - private Set createSecondaryTableSources() { - Set secondaryTableSources = new HashSet(); - AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.SECONDARY_TABLES - ); - AnnotationInstance secondaryTable = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.SECONDARY_TABLE - ); - // collect all @secondaryTable annotations - List secondaryTableAnnotations = new ArrayList(); - if ( secondaryTable != null ) { - secondaryTableAnnotations.add( - secondaryTable - ); - } - - if ( secondaryTables != null ) { - secondaryTableAnnotations.addAll( - Arrays.asList( - JandexHelper.getValue( secondaryTables, "value", AnnotationInstance[].class ) - ) - ); - } - - // create table sources - for ( AnnotationInstance annotationInstance : secondaryTableAnnotations ) { - secondaryTableSources.add( createTableSource( annotationInstance ) ); - } - - return secondaryTableSources; - } - - - private void createUniqueConstraints(AnnotationInstance tableAnnotation, String tableName) { - AnnotationValue value = tableAnnotation.value( "uniqueConstraints" ); - if ( value == null ) { - return; - } - - AnnotationInstance[] uniqueConstraints = value.asNestedArray(); - for ( AnnotationInstance unique : uniqueConstraints ) { - String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString(); - String[] columnNames = unique.value( "columnNames" ).asStringArray(); - UniqueConstraintSourceImpl uniqueConstraintSource = - new UniqueConstraintSourceImpl( - name, tableName, Arrays.asList( columnNames ) - ); - constraintSources.add( uniqueConstraintSource ); - } - } - - private String determineCustomLoader() { - String customLoader = null; - // Custom sql loader - final AnnotationInstance sqlLoaderAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.LOADER - ); - if ( sqlLoaderAnnotation != null ) { - customLoader = sqlLoaderAnnotation.value( "namedQuery" ).asString(); - } - return customLoader; - } - - private CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation) { - if ( customSqlAnnotation == null ) { - return null; - } - - final String sql = customSqlAnnotation.value( "sql" ).asString(); - final boolean isCallable = customSqlAnnotation.value( "callable" ) != null - && customSqlAnnotation.value( "callable" ).asBoolean(); - - final ExecuteUpdateResultCheckStyle checkStyle = customSqlAnnotation.value( "check" ) == null - ? isCallable - ? ExecuteUpdateResultCheckStyle.NONE - : ExecuteUpdateResultCheckStyle.COUNT - : ExecuteUpdateResultCheckStyle.valueOf( customSqlAnnotation.value( "check" ).asEnum() ); - - return new CustomSQL( sql, isCallable, checkStyle ); - } - - private void processCustomSqlAnnotations() { - // Custom sql insert - final AnnotationInstance sqlInsertAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_INSERT - ); - customInsert = createCustomSQL( sqlInsertAnnotation ); - - // Custom sql update - final AnnotationInstance sqlUpdateAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_UPDATE - ); - customUpdate = createCustomSQL( sqlUpdateAnnotation ); - - // Custom sql delete - final AnnotationInstance sqlDeleteAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_DELETE - ); - customDelete = createCustomSQL( sqlDeleteAnnotation ); - } - - private List determineSynchronizedTableNames() { - final AnnotationInstance synchronizeAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SYNCHRONIZE - ); - if ( synchronizeAnnotation != null ) { - final String[] tableNames = synchronizeAnnotation.value().asStringArray(); - return Arrays.asList( tableNames ); - } - else { - return Collections.emptyList(); - } - } - - private void processProxyGeneration() { - // Proxy generation - final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.PROXY - ); - if ( hibernateProxyAnnotation != null ) { - isLazy = hibernateProxyAnnotation.value( "lazy" ) == null - || hibernateProxyAnnotation.value( "lazy" ).asBoolean(); - if ( isLazy ) { - final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" ); - if ( proxyClassValue == null ) { - proxy = getName(); - } - else { - proxy = proxyClassValue.asString(); - } - } - else { - proxy = null; - } - } - else { - isLazy = true; - proxy = getName(); - } - } - - private int determineBatchSize() { - final AnnotationInstance batchSizeAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.BATCH_SIZE - ); - return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt(); - } - - private List determineEntityListeners() { - List callbackClassList = new ArrayList(); - - // Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded) - if ( JandexHelper.getSingleAnnotation( getClassInfo(), JPADotNames.EXCLUDE_DEFAULT_LISTENERS ) == null ) { - List defaultEntityListenerAnnotations = getLocalBindingContext().getIndex() - .getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); - for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) { - for ( Type callbackClass : annotation.value().asClassArray() ) { - String callbackClassName = callbackClass.name().toString(); - try { - processDefaultJpaCallbacks( callbackClassName, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName ); - } - } - } - } - - // Bind JPA entity listener callbacks, using superclasses first (unless excluded) - List annotationList = getClassInfo().annotations().get( JPADotNames.ENTITY_LISTENERS ); - if ( annotationList != null ) { - for ( AnnotationInstance annotation : annotationList ) { - for ( Type callbackClass : annotation.value().asClassArray() ) { - String callbackClassName = callbackClass.name().toString(); - try { - processJpaCallbacks( callbackClassName, true, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName ); - } - } - } - } - - // Bind JPA entity.mapped superclass callbacks, using superclasses first (unless excluded) - try { - processJpaCallbacks( getName(), false, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( - error.getMessage() + "entity/mapped superclass " + getClassInfo().name().toString() - ); - } - - return callbackClassList; - } - - private void processDefaultJpaCallbacks(String instanceCallbackClassName, List jpaCallbackClassList) { - ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName ); - - // Process superclass first if available and not excluded - if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) { - DotName superName = callbackClassInfo.superName(); - if ( superName != null ) { - processDefaultJpaCallbacks( instanceCallbackClassName, jpaCallbackClassList ); - } - } - - String callbackClassName = callbackClassInfo.name().toString(); - Map, String> callbacksByType = new HashMap, String>(); - createDefaultCallback( - PrePersist.class, PseudoJpaDotNames.DEFAULT_PRE_PERSIST, callbackClassName, callbacksByType - ); - createDefaultCallback( - PreRemove.class, PseudoJpaDotNames.DEFAULT_PRE_REMOVE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PreUpdate.class, PseudoJpaDotNames.DEFAULT_PRE_UPDATE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostLoad.class, PseudoJpaDotNames.DEFAULT_POST_LOAD, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostPersist.class, PseudoJpaDotNames.DEFAULT_POST_PERSIST, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostRemove.class, PseudoJpaDotNames.DEFAULT_POST_REMOVE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostUpdate.class, PseudoJpaDotNames.DEFAULT_POST_UPDATE, callbackClassName, callbacksByType - ); - if ( !callbacksByType.isEmpty() ) { - jpaCallbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, true ) ); - } - } - - private void processJpaCallbacks(String instanceCallbackClassName, boolean isListener, List callbackClassList) { - - ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName ); - - // Process superclass first if available and not excluded - if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) { - DotName superName = callbackClassInfo.superName(); - if ( superName != null ) { - processJpaCallbacks( - instanceCallbackClassName, - isListener, - callbackClassList - ); - } - } - - Map, String> callbacksByType = new HashMap, String>(); - createCallback( PrePersist.class, JPADotNames.PRE_PERSIST, callbacksByType, callbackClassInfo, isListener ); - createCallback( PreRemove.class, JPADotNames.PRE_REMOVE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PreUpdate.class, JPADotNames.PRE_UPDATE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostLoad.class, JPADotNames.POST_LOAD, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostPersist.class, JPADotNames.POST_PERSIST, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostRemove.class, JPADotNames.POST_REMOVE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostUpdate.class, JPADotNames.POST_UPDATE, callbacksByType, callbackClassInfo, isListener ); - if ( !callbacksByType.isEmpty() ) { - callbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, isListener ) ); - } - } - - private void createDefaultCallback(Class callbackTypeClass, - DotName callbackTypeName, - String callbackClassName, - Map, String> callbacksByClass) { - for ( AnnotationInstance callback : getLocalBindingContext().getIndex().getAnnotations( callbackTypeName ) ) { - MethodInfo methodInfo = (MethodInfo) callback.target(); - validateMethod( methodInfo, callbackTypeClass, callbacksByClass, true ); - if ( methodInfo.declaringClass().name().toString().equals( callbackClassName ) ) { - if ( methodInfo.args().length != 1 ) { - throw new PersistenceException( - String.format( - "Callback method %s must have exactly one argument defined as either Object or %s in ", - methodInfo.name(), - getEntityName() - ) - ); - } - callbacksByClass.put( callbackTypeClass, methodInfo.name() ); - } - } - } - - private void createCallback(Class callbackTypeClass, - DotName callbackTypeName, - Map, String> callbacksByClass, - ClassInfo callbackClassInfo, - boolean isListener) { - Map> annotations = callbackClassInfo.annotations(); - List annotationInstances = annotations.get( callbackTypeName ); - if ( annotationInstances == null ) { - return; - } - for ( AnnotationInstance callbackAnnotation : annotationInstances ) { - MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target(); - validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener ); - callbacksByClass.put( callbackTypeClass, methodInfo.name() ); - } - } - - private void validateMethod(MethodInfo methodInfo, - Class callbackTypeClass, - Map, String> callbacksByClass, - boolean isListener) { - if ( methodInfo.returnType().kind() != Kind.VOID ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have a void return type in " ); - } - if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must not be static or final in " ); - } - Type[] argTypes = methodInfo.args(); - if ( isListener ) { - if ( argTypes.length != 1 ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have exactly one argument in " ); - } - String argTypeName = argTypes[0].name().toString(); - if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( getName() ) ) { - throw new PersistenceException( - "The argument for callback method " + methodInfo.name() + - " must be defined as either Object or " + getEntityName() + " in " - ); - } - } - else if ( argTypes.length != 0 ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have no arguments in " ); - } - if ( callbacksByClass.containsKey( callbackTypeClass ) ) { - throw new PersistenceException( - "Only one method may be annotated as a " + callbackTypeClass.getSimpleName() + - " callback method in " - ); - } - } - - // Process JPA callbacks, in superclass-first order (unless superclasses are excluded), using default listeners first - // (unless default listeners are excluded), then entity listeners, and finally the entity/mapped superclass itself - private class JpaCallbackClassImpl implements JpaCallbackClass { - - private final Map, String> callbacksByType; - private final String name; - private final boolean isListener; - - private JpaCallbackClassImpl(String name, - Map, String> callbacksByType, - boolean isListener) { - this.name = name; - this.callbacksByType = callbacksByType; - this.isListener = isListener; - } - - @Override - public String getCallbackMethod(Class callbackType) { - return callbacksByType.get( callbackType ); - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean isListener() { - return isListener; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java deleted file mode 100644 index 4c6c677e4e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.ToOneAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Hardy Ferentschik - */ -public class EntitySourceImpl implements EntitySource { - private final EntityClass entityClass; - private final Set subclassEntitySources; - - public EntitySourceImpl(EntityClass entityClass) { - this.entityClass = entityClass; - this.subclassEntitySources = new HashSet(); - } - - public EntityClass getEntityClass() { - return entityClass; - } - - @Override - public Origin getOrigin() { - return entityClass.getLocalBindingContext().getOrigin(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return entityClass.getLocalBindingContext(); - } - - @Override - public String getEntityName() { - return entityClass.getName(); - } - - @Override - public String getClassName() { - return entityClass.getName(); - } - - @Override - public String getJpaEntityName() { - return entityClass.getExplicitEntityName(); - } - - @Override - public TableSource getPrimaryTable() { - return entityClass.getPrimaryTableSource(); - } - - @Override - public boolean isAbstract() { - return false; - } - - @Override - public boolean isLazy() { - return entityClass.isLazy(); - } - - @Override - public String getProxy() { - return entityClass.getProxy(); - } - - @Override - public int getBatchSize() { - return entityClass.getBatchSize(); - } - - @Override - public boolean isDynamicInsert() { - return entityClass.isDynamicInsert(); - } - - @Override - public boolean isDynamicUpdate() { - return entityClass.isDynamicUpdate(); - } - - @Override - public boolean isSelectBeforeUpdate() { - return entityClass.isSelectBeforeUpdate(); - } - - @Override - public String getCustomTuplizerClassName() { - return entityClass.getCustomTuplizer(); - } - - @Override - public String getCustomPersisterClassName() { - return entityClass.getCustomPersister(); - } - - @Override - public String getCustomLoaderName() { - return entityClass.getCustomLoaderQueryName(); - } - - @Override - public CustomSQL getCustomSqlInsert() { - return entityClass.getCustomInsert(); - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return entityClass.getCustomUpdate(); - } - - @Override - public CustomSQL getCustomSqlDelete() { - return entityClass.getCustomDelete(); - } - - @Override - public List getSynchronizedTableNames() { - return entityClass.getSynchronizedTableNames(); - } - - @Override - public Iterable metaAttributes() { - return Collections.emptySet(); - } - - @Override - public String getPath() { - return entityClass.getName(); - } - - @Override - public Iterable attributeSources() { - List attributeList = new ArrayList(); - for ( BasicAttribute attribute : entityClass.getSimpleAttributes() ) { - attributeList.add( new SingularAttributeSourceImpl( attribute ) ); - } - for ( EmbeddableClass component : entityClass.getEmbeddedClasses().values() ) { - attributeList.add( - new ComponentAttributeSourceImpl( - component, - "", - entityClass.getAttributeOverrideMap() - ) - ); - } - for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) { - attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); - } - return attributeList; - } - - @Override - public void add(SubclassEntitySource subclassEntitySource) { - subclassEntitySources.add( subclassEntitySource ); - } - - @Override - public Iterable subclassEntitySources() { - return subclassEntitySources; - } - - @Override - public String getDiscriminatorMatchValue() { - return entityClass.getDiscriminatorMatchValue(); - } - - @Override - public Iterable getConstraints() { - return entityClass.getConstraintSources(); - } - - @Override - public List getJpaCallbackClasses() { - return entityClass.getJpaCallbacks(); - } - - @Override - public Iterable getSecondaryTables() { - return entityClass.getSecondaryTableSources(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java deleted file mode 100644 index 808c0b0cd9..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.DiscriminatorSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.SimpleIdentifierSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.IdentifierSource; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntitySource { - public RootEntitySourceImpl(EntityClass entityClass) { - super( entityClass ); - } - - @Override - public IdentifierSource getIdentifierSource() { - IdType idType = getEntityClass().getIdType(); - switch ( idType ) { - case SIMPLE: { - BasicAttribute attribute = getEntityClass().getIdAttributes().iterator().next(); - return new SimpleIdentifierSourceImpl( attribute, getEntityClass().getAttributeOverrideMap() ); - } - case COMPOSED: { - throw new NotYetImplementedException( "Composed ids must still be implemented." ); - } - case EMBEDDED: { - throw new NotYetImplementedException( "Embedded ids must still be implemented." ); - } - default: { - throw new AssertionFailure( "The root entity needs to specify an identifier" ); - } - } - } - - @Override - public SingularAttributeSource getVersioningAttributeSource() { - SingularAttributeSource attributeSource = null; - EntityClass entityClass = getEntityClass(); - if ( entityClass.getVersionAttribute() != null ) { - attributeSource = new SingularAttributeSourceImpl( entityClass.getVersionAttribute() ); - } - return attributeSource; - } - - @Override - public DiscriminatorSource getDiscriminatorSource() { - DiscriminatorSource discriminatorSource = null; - if ( getEntityClass().getDiscriminatorColumnValues() != null ) { - discriminatorSource = new DiscriminatorSourceImpl( getEntityClass() ); - } - return discriminatorSource; - } - - @Override - public EntityMode getEntityMode() { - return EntityMode.POJO; - } - - @Override - public boolean isMutable() { - return getEntityClass().isMutable(); - } - - @Override - public boolean isExplicitPolymorphism() { - return getEntityClass().isExplicitPolymorphism(); - } - - @Override - public String getWhere() { - return getEntityClass().getWhereClause(); - } - - @Override - public String getRowId() { - return getEntityClass().getRowId(); - } - - @Override - public OptimisticLockStyle getOptimisticLockStyle() { - return getEntityClass().getOptimisticLockStyle(); - } - - @Override - public Caching getCaching() { - return getEntityClass().getCaching(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java deleted file mode 100644 index 9c5c5c26fd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.annotations.FilterDef; -import org.hibernate.annotations.FilterDefs; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.type.Type; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link FilterDefs} and {@link FilterDef} annotations. - * - * @author Hardy Ferentschik - */ -public class FilterDefBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - FilterDefBinder.class.getName() - ); - - /** - * Binds all {@link FilterDefs} and {@link FilterDef} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEF ); - for ( AnnotationInstance filterDef : annotations ) { - bind( bindingContext.getMetadataImplementor(), filterDef ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEFS ); - for ( AnnotationInstance filterDefs : annotations ) { - AnnotationInstance[] filterDefAnnotations = JandexHelper.getValue( - filterDefs, - "value", - AnnotationInstance[].class - ); - for ( AnnotationInstance filterDef : filterDefAnnotations ) { - bind( bindingContext.getMetadataImplementor(), filterDef ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance filterDef) { - String name = JandexHelper.getValue( filterDef, "name", String.class ); - Map prms = new HashMap(); - for ( AnnotationInstance prm : JandexHelper.getValue( filterDef, "parameters", AnnotationInstance[].class ) ) { - prms.put( - JandexHelper.getValue( prm, "name", String.class ), - metadata.getTypeResolver().heuristicType( JandexHelper.getValue( prm, "type", String.class ) ) - ); - } - metadata.addFilterDefinition( - new FilterDefinition( - name, - JandexHelper.getValue( filterDef, "defaultCondition", String.class ), - prms - ) - ); - LOG.debugf( "Binding filter definition: %s", name ); - } - - private FilterDefBinder() { - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java deleted file mode 100644 index 8039fd7802..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.persistence.GenerationType; -import javax.persistence.SequenceGenerator; - -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.GenericGenerators; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.id.MultipleHiLoPerTableGenerator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.SequenceHiLoGenerator; -import org.hibernate.id.TableHiLoGenerator; -import org.hibernate.id.enhanced.SequenceStyleGenerator; -import org.hibernate.id.enhanced.TableGenerator; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and - * {@link GenericGenerators} annotations. - * - * @author Hardy Ferentschik - */ -public class IdGeneratorBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - IdGeneratorBinder.class.getName() - ); - - private IdGeneratorBinder() { - } - - /** - * Binds all {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and - * {@link GenericGenerators} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex() - .getAnnotations( JPADotNames.SEQUENCE_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindSequenceGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.TABLE_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindTableGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindGenericGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATORS ); - for ( AnnotationInstance generators : annotations ) { - for ( AnnotationInstance generator : JandexHelper.getValue( - generators, - "value", - AnnotationInstance[].class - ) ) { - bindGenericGenerator( bindingContext.getMetadataImplementor(), generator ); - } - } - } - - private static void addStringParameter(AnnotationInstance annotation, - String element, - Map parameters, - String parameter) { - String string = JandexHelper.getValue( annotation, element, String.class ); - if ( StringHelper.isNotEmpty( string ) ) { - parameters.put( parameter, string ); - } - } - - private static void bindGenericGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( - generator, - "parameters", - AnnotationInstance[].class - ); - for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { - parameterMap.put( - JandexHelper.getValue( parameterAnnotation, "name", String.class ), - JandexHelper.getValue( parameterAnnotation, "value", String.class ) - ); - } - metadata.addIdGenerator( - new IdGenerator( - name, - JandexHelper.getValue( generator, "strategy", String.class ), - parameterMap - ) - ); - LOG.tracef( "Add generic generator with name: %s", name ); - } - - private static void bindSequenceGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM ); - boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - GenerationType.SEQUENCE, - useNewIdentifierGenerators - ); - if ( useNewIdentifierGenerators ) { - addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG ); - addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA ); - parameterMap.put( - SequenceStyleGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) ) - ); - parameterMap.put( - SequenceStyleGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class ) ) - ); - } - else { - if ( JandexHelper.getValue( generator, "initialValue", Integer.class ) != 1 ) { - LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); - } - parameterMap.put( - SequenceHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) - ); - } - metadata.addIdGenerator( new IdGenerator( name, strategy, parameterMap ) ); - LOG.tracef( "Add sequence generator with name: %s", name ); - } - - private static void bindTableGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG ); - addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA ); - boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - GenerationType.TABLE, - useNewIdentifierGenerators - ); - if ( useNewIdentifierGenerators ) { - parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); - addStringParameter( generator, "table", parameterMap, TableGenerator.TABLE_PARAM ); - addStringParameter( generator, "pkColumnName", parameterMap, TableGenerator.SEGMENT_COLUMN_PARAM ); - addStringParameter( generator, "pkColumnValue", parameterMap, TableGenerator.SEGMENT_VALUE_PARAM ); - addStringParameter( generator, "valueColumnName", parameterMap, TableGenerator.VALUE_COLUMN_PARAM ); - parameterMap.put( - TableGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", String.class ) ) - ); - parameterMap.put( - TableGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValue( generator, "initialValue", String.class ) + 1 ) - ); - } - else { - addStringParameter( generator, "table", parameterMap, MultipleHiLoPerTableGenerator.ID_TABLE ); - addStringParameter( generator, "pkColumnName", parameterMap, MultipleHiLoPerTableGenerator.PK_COLUMN_NAME ); - addStringParameter( generator, "pkColumnValue", parameterMap, MultipleHiLoPerTableGenerator.PK_VALUE_NAME ); - addStringParameter( generator, "valueColumnName", parameterMap, MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME ); - parameterMap.put( - TableHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) - ); - } - if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class ).length > 0 ) { - LOG.ignoringTableGeneratorConstraints( name ); - } - metadata.addIdGenerator( new IdGenerator( name, strategy, parameterMap ) ); - LOG.tracef( "Add table generator with name: %s", name ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java deleted file mode 100644 index a7bbd8e1fc..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import javax.persistence.NamedNativeQueries; -import javax.persistence.NamedNativeQuery; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; - -import org.hibernate.AnnotationException; -import org.hibernate.CacheMode; -import org.hibernate.FlushMode; -import org.hibernate.LockMode; -import org.hibernate.annotations.QueryHints; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; -import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.logging.Logger; - -/** - * Binds {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, - * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, - * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries}. - * - * @author Hardy Ferentschik - */ -public class QueryBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - QueryBinder.class.getName() - ); - - private QueryBinder() { - } - - /** - * Binds all {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, - * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, - * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries} - * annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - } - } - - /** - * Binds {@link javax.persistence.NamedQuery} as well as {@link org.hibernate.annotations.NamedQuery}. - * - * @param metadata the current metadata - * @param annotation the named query annotation - */ - private static void bindNamedQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValue( annotation, "name", String.class ); - if ( StringHelper.isEmpty( name ) ) { - throw new AnnotationException( "A named query must have a name when used in class or package level" ); - } - - String query = JandexHelper.getValue( annotation, "query", String.class ); - - AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); - - String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); - if ( StringHelper.isEmpty( cacheRegion ) ) { - cacheRegion = null; - } - - Integer timeout = getTimeout( hints, query ); - if ( timeout != null && timeout < 0 ) { - timeout = null; - } - - Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name ); - if ( fetchSize != null && fetchSize < 0 ) { - fetchSize = null; - } - - String comment = getString( hints, QueryHints.COMMENT ); - if ( StringHelper.isEmpty( comment ) ) { - comment = null; - } - - metadata.addNamedQuery( - new NamedQueryDefinitionBuilder().setName( name ).setQuery( query ).setCacheable( - getBoolean( - hints, - QueryHints.CACHEABLE, - name - ) - ).setCacheRegion( cacheRegion ).setTimeout( timeout ).setFetchSize( fetchSize ).setFlushMode( - getFlushMode( hints, QueryHints.FLUSH_MODE, name ) - ).setCacheMode( getCacheMode( hints, QueryHints.CACHE_MODE, name ) ).setReadOnly( - getBoolean( - hints, - QueryHints.READ_ONLY, - name - ) - ).setComment( comment ).setParameterTypes( null ).createNamedQueryDefinition() - ); - LOG.debugf( "Binding named query: %s => %s", name, query ); - } - - private static void bindNamedNativeQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValue( annotation, "name", String.class ); - if ( StringHelper.isEmpty( name ) ) { - throw new AnnotationException( "A named native query must have a name when used in class or package level" ); - } - - String query = JandexHelper.getValue( annotation, "query", String.class ); - - String resultSetMapping = JandexHelper.getValue( annotation, "resultSetMapping", String.class ); - - AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); - - boolean cacheable = getBoolean( hints, "org.hibernate.cacheable", name ); - String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); - if ( StringHelper.isEmpty( cacheRegion ) ) { - cacheRegion = null; - } - - Integer timeout = getTimeout( hints, query ); - if ( timeout != null && timeout < 0 ) { - timeout = null; - } - - Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name ); - if ( fetchSize != null && fetchSize < 0 ) { - fetchSize = null; - } - - FlushMode flushMode = getFlushMode( hints, QueryHints.FLUSH_MODE, name ); - CacheMode cacheMode = getCacheMode( hints, QueryHints.CACHE_MODE, name ); - - boolean readOnly = getBoolean( hints, QueryHints.READ_ONLY, name ); - - String comment = getString( hints, QueryHints.COMMENT ); - if ( StringHelper.isEmpty( comment ) ) { - comment = null; - } - - boolean callable = getBoolean( hints, QueryHints.CALLABLE, name ); - NamedSQLQueryDefinition def; - if ( StringHelper.isNotEmpty( resultSetMapping ) ) { - def = new NamedSQLQueryDefinitionBuilder().setName( name ) - .setQuery( query ) - .setResultSetRef( - resultSetMapping - ) - .setQuerySpaces( null ) - .setCacheable( cacheable ) - .setCacheRegion( cacheRegion ) - .setTimeout( timeout ) - .setFetchSize( fetchSize ) - .setFlushMode( flushMode ) - .setCacheMode( cacheMode ) - .setReadOnly( readOnly ) - .setComment( comment ) - .setParameterTypes( null ) - .setCallable( callable ) - .createNamedQueryDefinition(); - } - else { - AnnotationValue annotationValue = annotation.value( "resultClass" ); - if ( annotationValue == null ) { - throw new NotYetImplementedException( "Pure native scalar queries are not yet supported" ); - } - NativeSQLQueryRootReturn queryRoots[] = new NativeSQLQueryRootReturn[] { - new NativeSQLQueryRootReturn( - "alias1", - annotationValue.asString(), - new HashMap(), - LockMode.READ - ) - }; - def = new NamedSQLQueryDefinitionBuilder().setName( name ) - .setQuery( query ) - .setQueryReturns( queryRoots ) - .setQuerySpaces( null ) - .setCacheable( cacheable ) - .setCacheRegion( cacheRegion ) - .setTimeout( timeout ) - .setFetchSize( fetchSize ) - .setFlushMode( flushMode ) - .setCacheMode( cacheMode ) - .setReadOnly( readOnly ) - .setComment( comment ) - .setParameterTypes( null ) - .setCallable( callable ) - .createNamedQueryDefinition(); - } - metadata.addNamedNativeQuery( def ); - LOG.debugf( "Binding named native query: %s => %s", name, query ); - } - - private static boolean getBoolean(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null || val.equalsIgnoreCase( "false" ) ) { - return false; - } - if ( val.equalsIgnoreCase( "true" ) ) { - return true; - } - throw new AnnotationException( "Not a boolean in hint: " + query + ":" + element ); - } - - private static CacheMode getCacheMode(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - if ( val.equalsIgnoreCase( CacheMode.GET.toString() ) ) { - return CacheMode.GET; - } - if ( val.equalsIgnoreCase( CacheMode.IGNORE.toString() ) ) { - return CacheMode.IGNORE; - } - if ( val.equalsIgnoreCase( CacheMode.NORMAL.toString() ) ) { - return CacheMode.NORMAL; - } - if ( val.equalsIgnoreCase( CacheMode.PUT.toString() ) ) { - return CacheMode.PUT; - } - if ( val.equalsIgnoreCase( CacheMode.REFRESH.toString() ) ) { - return CacheMode.REFRESH; - } - throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element ); - } - - private static FlushMode getFlushMode(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - if ( val.equalsIgnoreCase( FlushMode.ALWAYS.toString() ) ) { - return FlushMode.ALWAYS; - } - else if ( val.equalsIgnoreCase( FlushMode.AUTO.toString() ) ) { - return FlushMode.AUTO; - } - else if ( val.equalsIgnoreCase( FlushMode.COMMIT.toString() ) ) { - return FlushMode.COMMIT; - } - else if ( val.equalsIgnoreCase( FlushMode.NEVER.toString() ) ) { - return FlushMode.MANUAL; - } - else if ( val.equalsIgnoreCase( FlushMode.MANUAL.toString() ) ) { - return FlushMode.MANUAL; - } - else { - throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + element ); - } - } - - private static Integer getInteger(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - try { - return Integer.decode( val ); - } - catch ( NumberFormatException nfe ) { - throw new AnnotationException( "Not an integer in hint: " + query + ":" + element, nfe ); - } - } - - private static String getString(AnnotationInstance[] hints, String element) { - for ( AnnotationInstance hint : hints ) { - if ( element.equals( JandexHelper.getValue( hint, "name", String.class ) ) ) { - return JandexHelper.getValue( hint, "value", String.class ); - } - } - return null; - } - - private static Integer getTimeout(AnnotationInstance[] hints, String query) { - Integer timeout = getInteger( hints, QueryHints.TIMEOUT_JPA, query ); - if ( timeout == null ) { - return getInteger( hints, QueryHints.TIMEOUT_HIBERNATE, query ); // timeout is already in seconds - } - return ( ( timeout + 500 ) / 1000 ); // convert milliseconds to seconds (rounded) - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java deleted file mode 100644 index 72c0511e32..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.List; - -import org.hibernate.AnnotationException; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.ObjectName; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds table related information. This binder is called after the entities are bound. - * - * @author Hardy Ferentschik - */ -public class TableBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - TableBinder.class.getName() - ); - - private TableBinder() { - } - - /** - * Binds {@link org.hibernate.annotations.Tables} and {@link org.hibernate.annotations.Table} annotations to the supplied - * metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLE ); - for ( AnnotationInstance tableAnnotation : annotations ) { - bind( bindingContext.getMetadataImplementor(), tableAnnotation ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLES ); - for ( AnnotationInstance tables : annotations ) { - for ( AnnotationInstance table : JandexHelper.getValue( tables, "value", AnnotationInstance[].class ) ) { - bind( bindingContext.getMetadataImplementor(), table ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance tableAnnotation) { - String tableName = JandexHelper.getValue( tableAnnotation, "appliesTo", String.class ); - ObjectName objectName = new ObjectName( tableName ); - Schema schema = metadata.getDatabase().getSchema( objectName.getSchema(), objectName.getCatalog() ); - Table table = schema.locateTable( objectName.getName() ); - if ( table != null ) { - bindHibernateTableAnnotation( table, tableAnnotation ); - } - } - - private static void bindHibernateTableAnnotation(Table table, AnnotationInstance tableAnnotation) { - for ( AnnotationInstance indexAnnotation : JandexHelper.getValue( - tableAnnotation, - "indexes", - AnnotationInstance[].class - ) ) { - bindIndexAnnotation( table, indexAnnotation ); - } - String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class ); - if ( StringHelper.isNotEmpty( comment ) ) { - table.addComment( comment.trim() ); - } - } - - private static void bindIndexAnnotation(Table table, AnnotationInstance indexAnnotation) { - String indexName = JandexHelper.getValue( indexAnnotation, "appliesTo", String.class ); - String[] columnNames = JandexHelper.getValue( indexAnnotation, "columnNames", String[].class ); - if ( columnNames == null ) { - LOG.noColumnsSpecifiedForIndex( indexName, table.toLoggableString() ); - return; - } - org.hibernate.metamodel.relational.Index index = table.getOrCreateIndex( indexName ); - for ( String columnName : columnNames ) { - Column column = findColumn( table, columnName ); - if ( column == null ) { - throw new AnnotationException( "@Index references a unknown column: " + columnName ); - } - index.addColumn( column ); - } - } - - private static Column findColumn(Table table, String columnName) { - Column column = null; - for ( SimpleValue value : table.values() ) { - if ( value instanceof Column && ( (Column) value ).getColumnName().getName().equals( columnName ) ) { - column = (Column) value; - break; - } - } - return column; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java deleted file mode 100644 index 9031f036ea..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AnnotationException; -import org.hibernate.annotations.TypeDefs; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link org.hibernate.annotations.TypeDef} and {@link TypeDefs}. - * - * @author Hardy Ferentschik - */ -public class TypeDefBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - TypeDefBinder.class.getName() - ); - - /** - * Binds all {@link org.hibernate.annotations.TypeDef} and {@link TypeDefs} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEF ); - for ( AnnotationInstance typeDef : annotations ) { - bind( bindingContext.getMetadataImplementor(), typeDef ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEFS ); - for ( AnnotationInstance typeDefs : annotations ) { - AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue( - typeDefs, - "value", - AnnotationInstance[].class - ); - for ( AnnotationInstance typeDef : typeDefAnnotations ) { - bind( bindingContext.getMetadataImplementor(), typeDef ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance typeDefAnnotation) { - String name = JandexHelper.getValue( typeDefAnnotation, "name", String.class ); - String defaultForType = JandexHelper.getValue( typeDefAnnotation, "defaultForType", String.class ); - String typeClass = JandexHelper.getValue( typeDefAnnotation, "typeClass", String.class ); - - boolean noName = StringHelper.isEmpty( name ); - boolean noDefaultForType = defaultForType == null || defaultForType.equals( void.class.getName() ); - - if ( noName && noDefaultForType ) { - throw new AnnotationException( - "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass " - + typeClass - ); - } - - Map parameterMaps = new HashMap(); - AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( - typeDefAnnotation, - "parameters", - AnnotationInstance[].class - ); - for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { - parameterMaps.put( - JandexHelper.getValue( parameterAnnotation, "name", String.class ), - JandexHelper.getValue( parameterAnnotation, "value", String.class ) - ); - } - - if ( !noName ) { - bind( name, typeClass, parameterMaps, metadata ); - } - if ( !noDefaultForType ) { - bind( defaultForType, typeClass, parameterMaps, metadata ); - } - } - - private static void bind( - String name, - String typeClass, - Map prms, - MetadataImplementor metadata) { - LOG.debugf( "Binding type definition: %s", name ); - metadata.addTypeDefinition( new TypeDef( name, typeClass, prms ) ); - } - - private TypeDefBinder() { - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java deleted file mode 100644 index d695b7ad82..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class AttributesBuilder extends AbstractAttributesBuilder { - private JaxbAttributes attributes; - - AttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbAttributes attributes) { - super( indexBuilder, classInfo, defaults ); - this.attributes = attributes; - } - - @Override - List getBasic() { - return attributes.getBasic(); - } - - @Override - List getId() { - return attributes.getId(); - } - - @Override - List getTransient() { - return attributes.getTransient(); - } - - @Override - List getVersion() { - return attributes.getVersion(); - } - - @Override - List getElementCollection() { - return attributes.getElementCollection(); - } - - @Override - List getEmbedded() { - return attributes.getEmbedded(); - } - - @Override - List getManyToMany() { - return attributes.getManyToMany(); - } - - @Override - List getManyToOne() { - return attributes.getManyToOne(); - } - - @Override - List getOneToMany() { - return attributes.getOneToMany(); - } - - @Override - List getOneToOne() { - return attributes.getOneToOne(); - } - - @Override - JaxbEmbeddedId getEmbeddedId() { - return attributes.getEmbeddedId(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java deleted file mode 100644 index c3692bb7d6..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.Collections; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddableAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class EmbeddableAttributesBuilder extends AbstractAttributesBuilder { - private JaxbEmbeddableAttributes attributes; - - EmbeddableAttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbEmbeddableAttributes embeddableAttributes) { - super( indexBuilder, classInfo, defaults ); - this.attributes = embeddableAttributes; - } - - @Override - List getBasic() { - return attributes.getBasic(); - } - - @Override - List getId() { - return Collections.emptyList(); - } - - @Override - List getTransient() { - return attributes.getTransient(); - } - - @Override - List getVersion() { - return Collections.emptyList(); - } - - @Override - List getElementCollection() { - return attributes.getElementCollection(); - } - - @Override - List getEmbedded() { - return attributes.getEmbedded(); - } - - @Override - List getManyToMany() { - return attributes.getManyToMany(); - } - - @Override - List getManyToOne() { - return attributes.getManyToOne(); - } - - @Override - List getOneToMany() { - return attributes.getOneToMany(); - } - - @Override - List getOneToOne() { - return attributes.getOneToOne(); - } - - @Override - JaxbEmbeddedId getEmbeddedId() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java deleted file mode 100644 index d276b6d1aa..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbCollectionTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSecondaryTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; - -/** - * @author Strong Liu - */ -interface SchemaAware { - String getSchema(); - - void setSchema(String schema); - - String getCatalog(); - - void setCatalog(String catalog); - - static class SecondaryTableSchemaAware implements SchemaAware { - private JaxbSecondaryTable table; - - SecondaryTableSchemaAware(JaxbSecondaryTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class TableSchemaAware implements SchemaAware { - private JaxbTable table; - - public TableSchemaAware(JaxbTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class JoinTableSchemaAware implements SchemaAware { - private JaxbJoinTable table; - - public JoinTableSchemaAware(JaxbJoinTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class CollectionTableSchemaAware implements SchemaAware { - private JaxbCollectionTable table; - - public CollectionTableSchemaAware(JaxbCollectionTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java deleted file mode 100644 index 2e5e2c84d3..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.beans.BeanInfoHelper; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.AttributeBindingContainer; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.BasicCollectionElement; -import org.hibernate.metamodel.binding.CollectionElementNature; -import org.hibernate.metamodel.binding.CollectionLaziness; -import org.hibernate.metamodel.binding.ComponentAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.binding.ManyToOneAttributeBinding; -import org.hibernate.metamodel.binding.MetaAttribute; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.domain.Component; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.Identifier; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.relational.Tuple; -import org.hibernate.metamodel.relational.UniqueKey; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.hbm.Helper; -import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.tuple.entity.EntityTuplizer; - -/** - * The common binder shared between annotations and {@code hbm.xml} processing. - *

- * The API consists of {@link #Binder(MetadataImplementor, List)} and {@link #processEntityHierarchy(EntityHierarchy)} - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class Binder { - private final MetadataImplementor metadata; - private final List processedEntityNames; - - private InheritanceType currentInheritanceType; - private EntityMode currentHierarchyEntityMode; - private LocalBindingContext currentBindingContext; - - public Binder(MetadataImplementor metadata, List processedEntityNames) { - this.metadata = metadata; - this.processedEntityNames = processedEntityNames; - } - - /** - * Process an entity hierarchy. - * - * @param entityHierarchy THe hierarchy to process. - */ - public void processEntityHierarchy(EntityHierarchy entityHierarchy) { - currentInheritanceType = entityHierarchy.getHierarchyInheritanceType(); - EntityBinding rootEntityBinding = createEntityBinding( entityHierarchy.getRootEntitySource(), null ); - if ( currentInheritanceType != InheritanceType.NO_INHERITANCE ) { - processHierarchySubEntities( entityHierarchy.getRootEntitySource(), rootEntityBinding ); - } - currentHierarchyEntityMode = null; - } - - private void processHierarchySubEntities(SubclassEntityContainer subclassEntitySource, EntityBinding superEntityBinding) { - for ( SubclassEntitySource subEntity : subclassEntitySource.subclassEntitySources() ) { - EntityBinding entityBinding = createEntityBinding( subEntity, superEntityBinding ); - processHierarchySubEntities( subEntity, entityBinding ); - } - } - - - // Entities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private EntityBinding createEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - if ( processedEntityNames.contains( entitySource.getEntityName() ) ) { - return metadata.getEntityBinding( entitySource.getEntityName() ); - } - - currentBindingContext = entitySource.getLocalBindingContext(); - try { - final EntityBinding entityBinding = doCreateEntityBinding( entitySource, superEntityBinding ); - - metadata.addEntity( entityBinding ); - processedEntityNames.add( entityBinding.getEntity().getName() ); - - processFetchProfiles( entitySource, entityBinding ); - - return entityBinding; - } - finally { - currentBindingContext = null; - } - } - - private EntityBinding doCreateEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = createBasicEntityBinding( entitySource, superEntityBinding ); - - bindSecondaryTables( entitySource, entityBinding ); - bindAttributes( entitySource, entityBinding ); - - bindTableUniqueConstraints( entitySource, entityBinding ); - - return entityBinding; - } - - private EntityBinding createBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - if ( superEntityBinding == null ) { - return makeRootEntityBinding( (RootEntitySource) entitySource ); - } - else { - switch ( currentInheritanceType ) { - case SINGLE_TABLE: - return makeDiscriminatedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - case JOINED: - return makeJoinedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - case TABLE_PER_CLASS: - return makeUnionedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - default: - // extreme internal error! - throw new AssertionFailure( "Internal condition failure" ); - } - } - } - - private EntityBinding makeRootEntityBinding(RootEntitySource entitySource) { - currentHierarchyEntityMode = entitySource.getEntityMode(); - - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, null ); - - bindPrimaryTable( entitySource, entityBinding ); - - bindIdentifier( entitySource, entityBinding ); - bindVersion( entityBinding, entitySource ); - bindDiscriminator( entitySource, entityBinding ); - - entityBinding.getHierarchyDetails().setCaching( entitySource.getCaching() ); - entityBinding.getHierarchyDetails().setExplicitPolymorphism( entitySource.isExplicitPolymorphism() ); - entityBinding.getHierarchyDetails().setOptimisticLockStyle( entitySource.getOptimisticLockStyle() ); - - entityBinding.setMutable( entitySource.isMutable() ); - entityBinding.setWhereFilter( entitySource.getWhere() ); - entityBinding.setRowId( entitySource.getRowId() ); - - return entityBinding; - } - - private EntityBinding buildBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = superEntityBinding == null - ? new EntityBinding( currentInheritanceType, currentHierarchyEntityMode ) - : new EntityBinding( superEntityBinding ); - - final String entityName = entitySource.getEntityName(); - final String className = currentHierarchyEntityMode == EntityMode.POJO ? entitySource.getClassName() : null; - - final Entity entity = new Entity( - entityName, - className, - currentBindingContext.makeClassReference( className ), - superEntityBinding == null ? null : superEntityBinding.getEntity() - ); - entityBinding.setEntity( entity ); - - entityBinding.setJpaEntityName( entitySource.getJpaEntityName() ); - - if ( currentHierarchyEntityMode == EntityMode.POJO ) { - final String proxy = entitySource.getProxy(); - if ( proxy != null ) { - entityBinding.setProxyInterfaceType( - currentBindingContext.makeClassReference( - currentBindingContext.qualifyClassName( proxy ) - ) - ); - entityBinding.setLazy( true ); - } - else if ( entitySource.isLazy() ) { - entityBinding.setProxyInterfaceType( entityBinding.getEntity().getClassReferenceUnresolved() ); - entityBinding.setLazy( true ); - } - } - else { - entityBinding.setProxyInterfaceType( null ); - entityBinding.setLazy( entitySource.isLazy() ); - } - - final String customTuplizerClassName = entitySource.getCustomTuplizerClassName(); - if ( customTuplizerClassName != null ) { - entityBinding.setCustomEntityTuplizerClass( - currentBindingContext.locateClassByName( - customTuplizerClassName - ) - ); - } - - final String customPersisterClassName = entitySource.getCustomPersisterClassName(); - if ( customPersisterClassName != null ) { - entityBinding.setCustomEntityPersisterClass( - currentBindingContext.locateClassByName( - customPersisterClassName - ) - ); - } - - entityBinding.setMetaAttributeContext( buildMetaAttributeContext( entitySource ) ); - - entityBinding.setDynamicUpdate( entitySource.isDynamicUpdate() ); - entityBinding.setDynamicInsert( entitySource.isDynamicInsert() ); - entityBinding.setBatchSize( entitySource.getBatchSize() ); - entityBinding.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() ); - entityBinding.setAbstract( entitySource.isAbstract() ); - - entityBinding.setCustomLoaderName( entitySource.getCustomLoaderName() ); - entityBinding.setCustomInsert( entitySource.getCustomSqlInsert() ); - entityBinding.setCustomUpdate( entitySource.getCustomSqlUpdate() ); - entityBinding.setCustomDelete( entitySource.getCustomSqlDelete() ); - - if ( entitySource.getSynchronizedTableNames() != null ) { - entityBinding.addSynchronizedTableNames( entitySource.getSynchronizedTableNames() ); - } - - entityBinding.setJpaCallbackClasses(entitySource.getJpaCallbackClasses()); - - return entityBinding; - } - - private EntityBinding makeDiscriminatedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - entityBinding.setPrimaryTable( superEntityBinding.getPrimaryTable() ); - entityBinding.setPrimaryTableName( superEntityBinding.getPrimaryTableName() ); - bindDiscriminatorValue( entitySource, entityBinding ); - - return entityBinding; - } - - private EntityBinding makeJoinedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - bindPrimaryTable( entitySource, entityBinding ); - - // todo : join - - return entityBinding; - } - - private EntityBinding makeUnionedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - bindPrimaryTable( entitySource, entityBinding ); - - // todo : ?? - - return entityBinding; - } - - // Attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private void bindIdentifier(RootEntitySource entitySource, EntityBinding entityBinding) { - if ( entitySource.getIdentifierSource() == null ) { - throw new AssertionFailure( "Expecting identifier information on root entity descriptor" ); - } - switch ( entitySource.getIdentifierSource().getNature() ) { - case SIMPLE: { - bindSimpleIdentifier( (SimpleIdentifierSource) entitySource.getIdentifierSource(), entityBinding ); - break; - } - case AGGREGATED_COMPOSITE: { - // composite id with an actual component class - break; - } - case COMPOSITE: { - // what we used to term an "embedded composite identifier", which is not tobe confused with the JPA - // term embedded. Specifically a composite id where there is no component class, though there may - // be a @IdClass :/ - break; - } - } - } - - private void bindSimpleIdentifier(SimpleIdentifierSource identifierSource, EntityBinding entityBinding) { - final BasicAttributeBinding idAttributeBinding = doBasicSingularAttributeBindingCreation( - identifierSource.getIdentifierAttributeSource(), entityBinding - ); - - entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( idAttributeBinding ); - IdGenerator generator = identifierSource.getIdentifierGeneratorDescriptor(); - if ( generator == null ) { - Map params = new HashMap(); - params.put( IdentifierGenerator.ENTITY_NAME, entityBinding.getEntity().getName() ); - generator = new IdGenerator( "default_assign_identity_generator", "assigned", params ); - } - entityBinding.getHierarchyDetails() - .getEntityIdentifier() - .setIdGenerator( generator ); - - final org.hibernate.metamodel.relational.Value relationalValue = idAttributeBinding.getValue(); - - if ( SimpleValue.class.isInstance( relationalValue ) ) { - if ( !Column.class.isInstance( relationalValue ) ) { - // this should never ever happen.. - throw new AssertionFailure( "Simple-id was not a column." ); - } - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( relationalValue ) ); - } - else { - for ( SimpleValue subValue : ( (Tuple) relationalValue ).values() ) { - if ( Column.class.isInstance( subValue ) ) { - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( subValue ) ); - } - } - } - } - - private void bindVersion(EntityBinding entityBinding, RootEntitySource entitySource) { - final SingularAttributeSource versioningAttributeSource = entitySource.getVersioningAttributeSource(); - if ( versioningAttributeSource == null ) { - return; - } - - BasicAttributeBinding attributeBinding = doBasicSingularAttributeBindingCreation( - versioningAttributeSource, entityBinding - ); - entityBinding.getHierarchyDetails().setVersioningAttributeBinding( attributeBinding ); - } - - private void bindDiscriminator(RootEntitySource entitySource, EntityBinding entityBinding) { - final DiscriminatorSource discriminatorSource = entitySource.getDiscriminatorSource(); - if ( discriminatorSource == null ) { - return; - } - - EntityDiscriminator discriminator = new EntityDiscriminator(); - SimpleValue relationalValue = makeSimpleValue( - entityBinding, - discriminatorSource.getDiscriminatorRelationalValueSource() - ); - discriminator.setBoundValue( relationalValue ); - - discriminator.getExplicitHibernateTypeDescriptor().setExplicitTypeName( - discriminatorSource.getExplicitHibernateTypeName() != null - ? discriminatorSource.getExplicitHibernateTypeName() - : "string" - ); - - discriminator.setInserted( discriminatorSource.isInserted() ); - discriminator.setForced( discriminatorSource.isForced() ); - - entityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator ); - entityBinding.setDiscriminatorMatchValue( entitySource.getDiscriminatorMatchValue() ); - } - - private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBinding entityBinding) { - final String discriminatorValue = entitySource.getDiscriminatorMatchValue(); - if ( discriminatorValue == null ) { - return; - } - entityBinding.setDiscriminatorMatchValue( discriminatorValue ); - } - - private void bindAttributes(AttributeSourceContainer attributeSourceContainer, AttributeBindingContainer attributeBindingContainer) { - // todo : we really need the notion of a Stack here for the table from which the columns come for binding these attributes. - // todo : adding the concept (interface) of a source of attribute metadata would allow reuse of this method for entity, component, unique-key, etc - // for now, simply assume all columns come from the base table.... - - for ( AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) { - if ( attributeSource.isSingular() ) { - final SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; - if ( singularAttributeSource.getNature() == SingularAttributeNature.COMPONENT ) { - bindComponent( (ComponentAttributeSource) singularAttributeSource, attributeBindingContainer ); - } - else { - doBasicSingularAttributeBindingCreation( singularAttributeSource, attributeBindingContainer ); - } - } - else { - bindPersistentCollection( (PluralAttributeSource) attributeSource, attributeBindingContainer ); - } - } - } - - private void bindComponent(ComponentAttributeSource attributeSource, AttributeBindingContainer container) { - final String attributeName = attributeSource.getName(); - SingularAttribute attribute = container.getAttributeContainer().locateComponentAttribute( attributeName ); - if ( attribute == null ) { - final Component component = new Component( - attributeSource.getPath(), - attributeSource.getClassName(), - attributeSource.getClassReference(), - null // component inheritance not YET supported - ); - attribute = container.getAttributeContainer().createComponentAttribute( attributeName, component ); - } - ComponentAttributeBinding componentAttributeBinding = container.makeComponentAttributeBinding( attribute ); - - if ( StringHelper.isNotEmpty( attributeSource.getParentReferenceAttributeName() ) ) { - final SingularAttribute parentReferenceAttribute = - componentAttributeBinding.getComponent() - .createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); - componentAttributeBinding.setParentReference( parentReferenceAttribute ); - } - - componentAttributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( attributeSource.metaAttributes(), container.getMetaAttributeContext() ) - ); - - bindAttributes( attributeSource, componentAttributeBinding ); - } - - private void bindPersistentCollection(PluralAttributeSource attributeSource, AttributeBindingContainer attributeBindingContainer) { - final PluralAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() - .locatePluralAttribute( attributeSource.getName() ); - final AbstractPluralAttributeBinding pluralAttributeBinding; - - if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) { - final PluralAttribute attribute = existingAttribute != null - ? existingAttribute - : attributeBindingContainer.getAttributeContainer().createBag( attributeSource.getName() ); - pluralAttributeBinding = attributeBindingContainer.makeBagAttributeBinding( - attribute, - convert( attributeSource.getElementSource().getNature() ) - ); - } - else if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.SET ) { - final PluralAttribute attribute = existingAttribute != null - ? existingAttribute - : attributeBindingContainer.getAttributeContainer().createSet( attributeSource.getName() ); - pluralAttributeBinding = attributeBindingContainer.makeSetAttributeBinding( - attribute, - convert( attributeSource.getElementSource().getNature() ) - ); - } - else { - // todo : implement other collection types - throw new NotYetImplementedException( "Collections other than bag and set not yet implemented :(" ); - } - - doBasicPluralAttributeBinding( attributeSource, pluralAttributeBinding ); - - bindCollectionTable( attributeSource, pluralAttributeBinding ); - bindSortingAndOrdering( attributeSource, pluralAttributeBinding ); - - bindCollectionKey( attributeSource, pluralAttributeBinding ); - bindCollectionElement( attributeSource, pluralAttributeBinding ); - bindCollectionIndex( attributeSource, pluralAttributeBinding ); - - metadata.addCollection( pluralAttributeBinding ); - } - - private void doBasicPluralAttributeBinding(PluralAttributeSource source, AbstractPluralAttributeBinding binding) { - binding.setFetchTiming( source.getFetchTiming() ); - binding.setFetchStyle( source.getFetchStyle() ); - binding.setCascadeStyles( source.getCascadeStyles() ); - - binding.setCaching( source.getCaching() ); - - binding.getHibernateTypeDescriptor().setJavaTypeName( - source.getPluralAttributeNature().reportedJavaType().getName() - ); - binding.getHibernateTypeDescriptor().setExplicitTypeName( source.getTypeInformation().getName() ); - binding.getHibernateTypeDescriptor().getTypeParameters().putAll( source.getTypeInformation().getParameters() ); - - if ( StringHelper.isNotEmpty( source.getCustomPersisterClassName() ) ) { - binding.setCollectionPersisterClass( - currentBindingContext.locateClassByName( source.getCustomPersisterClassName() ) - ); - } - - if ( source.getCustomPersisterClassName() != null ) { - binding.setCollectionPersisterClass( - metadata.locateClassByName( source.getCustomPersisterClassName() ) - ); - } - - binding.setCustomLoaderName( source.getCustomLoaderName() ); - binding.setCustomSqlInsert( source.getCustomSqlInsert() ); - binding.setCustomSqlUpdate( source.getCustomSqlUpdate() ); - binding.setCustomSqlDelete( source.getCustomSqlDelete() ); - binding.setCustomSqlDeleteAll( source.getCustomSqlDeleteAll() ); - - binding.setMetaAttributeContext( - buildMetaAttributeContext( - source.metaAttributes(), - binding.getContainer().getMetaAttributeContext() - ) - ); - - doBasicAttributeBinding( source, binding ); - } - - private CollectionLaziness interpretLaziness(String laziness) { - if ( laziness == null ) { - laziness = Boolean.toString( metadata.getMappingDefaults().areAssociationsLazy() ); - } - - if ( "extra".equals( laziness ) ) { - return CollectionLaziness.EXTRA; - } - else if ( "false".equals( laziness ) ) { - return CollectionLaziness.NOT; - } - else if ( "true".equals( laziness ) ) { - return CollectionLaziness.LAZY; - } - - throw new MappingException( - String.format( "Unexpected collection laziness value %s", laziness ), - currentBindingContext.getOrigin() - ); - } - - private void bindCollectionTable( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( attributeSource.getElementSource().getNature() == PluralAttributeElementNature.ONE_TO_MANY ) { - return; - } - - final Schema.Name schemaName = Helper.determineDatabaseSchemaName( - attributeSource.getExplicitSchemaName(), - attributeSource.getExplicitCatalogName(), - currentBindingContext - ); - final Schema schema = metadata.getDatabase().locateSchema( schemaName ); - - final String tableName = attributeSource.getExplicitCollectionTableName(); - if ( StringHelper.isNotEmpty( tableName ) ) { - final Identifier tableIdentifier = Identifier.toIdentifier( - currentBindingContext.getNamingStrategy().tableName( tableName ) - ); - Table collectionTable = schema.locateTable( tableIdentifier ); - if ( collectionTable == null ) { - collectionTable = schema.createTable( tableIdentifier ); - } - pluralAttributeBinding.setCollectionTable( collectionTable ); - } - else { - // todo : not sure wel have all the needed info here in all cases, specifically when needing to know the "other side" - final EntityBinding owner = pluralAttributeBinding.getContainer().seekEntityBinding(); - final String ownerTableLogicalName = Table.class.isInstance( owner.getPrimaryTable() ) - ? Table.class.cast( owner.getPrimaryTable() ).getTableName().getName() - : null; - String collectionTableName = currentBindingContext.getNamingStrategy().collectionTableName( - owner.getEntity().getName(), - ownerTableLogicalName, - null, // todo : here - null, // todo : and here - pluralAttributeBinding.getContainer().getPathBase() + '.' + attributeSource.getName() - ); - collectionTableName = quoteIdentifier( collectionTableName ); - pluralAttributeBinding.setCollectionTable( - schema.locateOrCreateTable( - Identifier.toIdentifier( - collectionTableName - ) - ) - ); - } - - if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableComment() ) ) { - pluralAttributeBinding.getCollectionTable().addComment( attributeSource.getCollectionTableComment() ); - } - - if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableCheck() ) ) { - pluralAttributeBinding.getCollectionTable().addCheckConstraint( attributeSource.getCollectionTableCheck() ); - } - - pluralAttributeBinding.setWhere( attributeSource.getWhere() ); - } - - private void bindCollectionKey( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - pluralAttributeBinding.getCollectionKey().prepareForeignKey( - attributeSource.getKeySource().getExplicitForeignKeyName(), - null // todo : handle secondary table names - ); - pluralAttributeBinding.getCollectionKey().getForeignKey().setDeleteRule( - attributeSource.getKeySource().getOnDeleteAction() - ); - // todo : need to bind "relational values", account for property-ref - } - - private void bindCollectionElement( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - final PluralAttributeElementSource elementSource = attributeSource.getElementSource(); - if ( elementSource.getNature() == PluralAttributeElementNature.BASIC ) { - final BasicPluralAttributeElementSource basicElementSource = (BasicPluralAttributeElementSource) elementSource; - final BasicCollectionElement basicCollectionElement = (BasicCollectionElement) pluralAttributeBinding.getCollectionElement(); - resolveTypeInformation( - basicElementSource.getExplicitHibernateTypeSource(), - pluralAttributeBinding.getAttribute(), - basicCollectionElement - ); - // todo : temp - return; - } - // todo : implement - throw new NotYetImplementedException( - String.format( - "Support for collection elements of type %s not yet implemented", - elementSource.getNature() - ) - ); - } - - private void bindCollectionIndex( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( attributeSource.getPluralAttributeNature() != PluralAttributeNature.LIST - && attributeSource.getPluralAttributeNature() != PluralAttributeNature.MAP ) { - return; - } - - // todo : implement - throw new NotYetImplementedException(); - } - - private void bindSortingAndOrdering( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( Sortable.class.isInstance( attributeSource ) ) { - final Sortable sortable = Sortable.class.cast( attributeSource ); - if ( sortable.isSorted() ) { - // todo : handle setting comparator - - // and then return because sorting and ordering are mutually exclusive - return; - } - } - - if ( Orderable.class.isInstance( attributeSource ) ) { - final Orderable orderable = Orderable.class.cast( attributeSource ); - if ( orderable.isOrdered() ) { - // todo : handle setting ordering - } - } - } - - private void doBasicAttributeBinding(AttributeSource attributeSource, AttributeBinding attributeBinding) { - attributeBinding.setPropertyAccessorName( attributeSource.getPropertyAccessorName() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - } - - private CollectionElementNature convert(PluralAttributeElementNature pluralAttributeElementNature) { - return CollectionElementNature.valueOf( pluralAttributeElementNature.name() ); - } - - private BasicAttributeBinding doBasicSingularAttributeBindingCreation( - SingularAttributeSource attributeSource, - AttributeBindingContainer attributeBindingContainer) { - final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() - .locateSingularAttribute( attributeSource.getName() ); - final SingularAttribute attribute; - if ( existingAttribute != null ) { - attribute = existingAttribute; - } - else if ( attributeSource.isVirtualAttribute() ) { - attribute = attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( - attributeSource.getName() - ); - } - else { - attribute = attributeBindingContainer.getAttributeContainer() - .createSingularAttribute( attributeSource.getName() ); - } - - final BasicAttributeBinding attributeBinding; - if ( attributeSource.getNature() == SingularAttributeNature.BASIC ) { - attributeBinding = attributeBindingContainer.makeBasicAttributeBinding( attribute ); - resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); - } - else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) { - attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( attribute ); - resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); - resolveToOneInformation( - (ToOneAttributeSource) attributeSource, - (ManyToOneAttributeBinding) attributeBinding - ); - } - else { - throw new NotYetImplementedException(); - } - - attributeBinding.setGeneration( attributeSource.getGeneration() ); - attributeBinding.setLazy( attributeSource.isLazy() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - - attributeBinding.setPropertyAccessorName( - Helper.getPropertyAccessorName( - attributeSource.getPropertyAccessorName(), - false, - currentBindingContext.getMappingDefaults().getPropertyAccessorName() - ) - ); - - bindRelationalValues( attributeSource, attributeBinding ); - - attributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( - attributeSource.metaAttributes(), - attributeBindingContainer.getMetaAttributeContext() - ) - ); - - return attributeBinding; - } - - private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, BasicAttributeBinding attributeBinding) { - final Class attributeJavaType = determineJavaType( attributeBinding.getAttribute() ); - if ( attributeJavaType != null ) { - attributeBinding.getAttribute() - .resolveType( currentBindingContext.makeJavaType( attributeJavaType.getName() ) ); - } - - resolveTypeInformation( typeSource, attributeBinding.getHibernateTypeDescriptor(), attributeJavaType ); - } - - private void resolveTypeInformation( - ExplicitHibernateTypeSource typeSource, - PluralAttribute attribute, - BasicCollectionElement collectionElement) { - final Class attributeJavaType = determineJavaType( attribute ); - resolveTypeInformation( typeSource, collectionElement.getHibernateTypeDescriptor(), attributeJavaType ); - } - - private void resolveTypeInformation( - ExplicitHibernateTypeSource typeSource, - HibernateTypeDescriptor hibernateTypeDescriptor, - Class discoveredJavaType) { - if ( discoveredJavaType != null ) { - hibernateTypeDescriptor.setJavaTypeName( discoveredJavaType.getName() ); - } - - final String explicitTypeName = typeSource.getName(); - if ( explicitTypeName != null ) { - final TypeDef typeDef = currentBindingContext.getMetadataImplementor() - .getTypeDefinition( explicitTypeName ); - if ( typeDef != null ) { - hibernateTypeDescriptor.setExplicitTypeName( typeDef.getTypeClass() ); - hibernateTypeDescriptor.getTypeParameters().putAll( typeDef.getParameters() ); - } - else { - hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName ); - } - final Map parameters = typeSource.getParameters(); - if ( parameters != null ) { - hibernateTypeDescriptor.getTypeParameters().putAll( parameters ); - } - } - else { - if ( discoveredJavaType == null ) { - // we will have problems later determining the Hibernate Type to use. Should we throw an - // exception now? Might be better to get better contextual info - } - } - } - - /** - * @param attribute the domain attribute - * - * @return Returns the Java type of the attribute using reflection or {@code null} if the type cannot be discovered - */ - private Class determineJavaType(final SingularAttribute attribute) { - try { - final Class ownerClass = attribute.getAttributeContainer().getClassReference(); - AttributeJavaTypeDeterminerDelegate delegate = new AttributeJavaTypeDeterminerDelegate( attribute.getName() ); - BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); - return delegate.javaType; - } - catch ( Exception ignore ) { - // todo : log it? - } - return null; - } - - private Class determineJavaType(PluralAttribute attribute) { - try { - final Class ownerClass = attribute.getAttributeContainer().getClassReference(); - PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate( - ownerClass, - attribute.getName() - ); - BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); - return delegate.javaType; - } - catch ( Exception ignore ) { - // todo : log it? - } - return null; - } - - private class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { - private final Class ownerClass; - private final String attributeName; - - private Class javaType = null; - - private PluralAttributeJavaTypeDeterminerDelegate(Class ownerClass, String attributeName) { - this.ownerClass = ownerClass; - this.attributeName = attributeName; - } - - @Override - public void processBeanInfo(BeanInfo beanInfo) throws Exception { - for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { - if ( propertyDescriptor.getName().equals( attributeName ) ) { - javaType = extractCollectionComponentType( beanInfo, propertyDescriptor ); - break; - } - } - } - - @SuppressWarnings( { "unchecked" }) - private Class extractCollectionComponentType(BeanInfo beanInfo, PropertyDescriptor propertyDescriptor) { - final java.lang.reflect.Type collectionAttributeType; - if ( propertyDescriptor.getReadMethod() != null ) { - collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType(); - } - else if ( propertyDescriptor.getWriteMethod() != null ) { - collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0]; - } - else { - // we need to look for the field and look at it... - try { - collectionAttributeType = ownerClass.getField( propertyDescriptor.getName() ).getGenericType(); - } - catch ( Exception e ) { - return null; - } - } - - if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) { - final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments(); - if ( types == null ) { - return null; - } - else if ( types.length == 1 ) { - return (Class) types[0]; - } - else if ( types.length == 2 ) { - // Map - return (Class) types[1]; - } - } - return null; - } - } - - private void resolveToOneInformation(ToOneAttributeSource attributeSource, ManyToOneAttributeBinding attributeBinding) { - final String referencedEntityName = attributeSource.getReferencedEntityName() != null - ? attributeSource.getReferencedEntityName() - : attributeBinding.getAttribute().getSingularAttributeType().getClassName(); - attributeBinding.setReferencedEntityName( referencedEntityName ); - // todo : we should consider basing references on columns instead of property-ref, which would require a resolution (later) of property-ref to column names - attributeBinding.setReferencedAttributeName( attributeSource.getReferencedEntityAttributeName() ); - - attributeBinding.setCascadeStyles( attributeSource.getCascadeStyles() ); - attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); - attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); - } - - private MetaAttributeContext buildMetaAttributeContext(EntitySource entitySource) { - return buildMetaAttributeContext( - entitySource.metaAttributes(), - true, - currentBindingContext.getMetadataImplementor().getGlobalMetaAttributeContext() - ); - } - - private static MetaAttributeContext buildMetaAttributeContext( - Iterable metaAttributeSources, - MetaAttributeContext parentContext) { - return buildMetaAttributeContext( metaAttributeSources, false, parentContext ); - } - - private static MetaAttributeContext buildMetaAttributeContext( - Iterable metaAttributeSources, - boolean onlyInheritable, - MetaAttributeContext parentContext) { - final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); - - for ( MetaAttributeSource metaAttributeSource : metaAttributeSources ) { - if ( onlyInheritable & !metaAttributeSource.isInheritable() ) { - continue; - } - - final String name = metaAttributeSource.getName(); - final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); - MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); - if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { - metaAttribute = new MetaAttribute( name ); - subContext.add( metaAttribute ); - } - metaAttribute.addValue( metaAttributeSource.getValue() ); - } - - return subContext; - } - - // Relational ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private void bindPrimaryTable(EntitySource entitySource, EntityBinding entityBinding) { - final TableSource tableSource = entitySource.getPrimaryTable(); - final Table table = createTable( entityBinding, tableSource ); - entityBinding.setPrimaryTable( table ); - entityBinding.setPrimaryTableName( table.getTableName().getName() ); - } - - private void bindSecondaryTables(EntitySource entitySource, EntityBinding entityBinding) { - for ( TableSource secondaryTableSource : entitySource.getSecondaryTables() ) { - final Table table = createTable( entityBinding, secondaryTableSource ); - entityBinding.addSecondaryTable( secondaryTableSource.getLogicalName(), table ); - } - } - - private Table createTable(EntityBinding entityBinding, TableSource tableSource) { - String tableName = tableSource.getExplicitTableName(); - if ( StringHelper.isEmpty( tableName ) ) { - tableName = currentBindingContext.getNamingStrategy() - .classToTableName( entityBinding.getEntity().getClassName() ); - } - else { - tableName = currentBindingContext.getNamingStrategy().tableName( tableName ); - } - tableName = quoteIdentifier( tableName ); - - final Schema.Name databaseSchemaName = Helper.determineDatabaseSchemaName( - tableSource.getExplicitSchemaName(), - tableSource.getExplicitCatalogName(), - currentBindingContext - ); - return currentBindingContext.getMetadataImplementor() - .getDatabase() - .locateSchema( databaseSchemaName ) - .locateOrCreateTable( Identifier.toIdentifier( tableName ) ); - } - - private void bindTableUniqueConstraints(EntitySource entitySource, EntityBinding entityBinding) { - for ( ConstraintSource constraintSource : entitySource.getConstraints() ) { - if ( constraintSource instanceof UniqueConstraintSource ) { - TableSpecification table = entityBinding.locateTable( constraintSource.getTableName() ); - if ( table == null ) { - // throw exception !? - } - String constraintName = constraintSource.name(); - if ( constraintName == null ) { - // create a default name - } - - UniqueKey uniqueKey = table.getOrCreateUniqueKey( constraintName ); - for ( String columnName : constraintSource.columnNames() ) { - uniqueKey.addColumn( table.locateOrCreateColumn( quoteIdentifier( columnName ) ) ); - } - } - } - } - - private void bindRelationalValues( - RelationalValueSourceContainer relationalValueSourceContainer, - SingularAttributeBinding attributeBinding) { - - List valueBindings = new ArrayList(); - - if ( !relationalValueSourceContainer.relationalValueSources().isEmpty() ) { - for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) { - final TableSpecification table = attributeBinding.getContainer() - .seekEntityBinding() - .locateTable( valueSource.getContainingTableName() ); - - if ( ColumnSource.class.isInstance( valueSource ) ) { - final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); - final Column column = makeColumn( (ColumnSource) valueSource, table ); - valueBindings.add( - new SimpleValueBinding( - column, - columnSource.isIncludedInInsert(), - columnSource.isIncludedInUpdate() - ) - ); - } - else { - valueBindings.add( - new SimpleValueBinding( - makeDerivedValue( ( (DerivedValueSource) valueSource ), table ) - ) - ); - } - } - } - else { - String name = metadata.getOptions() - .getNamingStrategy() - .propertyToColumnName( attributeBinding.getAttribute().getName() ); - name = quoteIdentifier( name ); - Column column = attributeBinding.getContainer() - .seekEntityBinding() - .getPrimaryTable() - .locateOrCreateColumn( name ); - column.setNullable( relationalValueSourceContainer.areValuesNullableByDefault() ); - valueBindings.add( - new SimpleValueBinding( - column, - relationalValueSourceContainer.areValuesIncludedInInsertByDefault(), - relationalValueSourceContainer.areValuesIncludedInUpdateByDefault() - ) - ); - } - attributeBinding.setSimpleValueBindings( valueBindings ); - } - - private String quoteIdentifier(String identifier) { - return currentBindingContext.isGloballyQuotedIdentifiers() ? StringHelper.quote( identifier ) : identifier; - } - - private SimpleValue makeSimpleValue( - EntityBinding entityBinding, - RelationalValueSource valueSource) { - final TableSpecification table = entityBinding.locateTable( valueSource.getContainingTableName() ); - - if ( ColumnSource.class.isInstance( valueSource ) ) { - return makeColumn( (ColumnSource) valueSource, table ); - } - else { - return makeDerivedValue( (DerivedValueSource) valueSource, table ); - } - } - - private Column makeColumn(ColumnSource columnSource, TableSpecification table) { - String name = columnSource.getName(); - name = metadata.getOptions().getNamingStrategy().columnName( name ); - name = quoteIdentifier( name ); - final Column column = table.locateOrCreateColumn( name ); - column.setNullable( columnSource.isNullable() ); - column.setDefaultValue( columnSource.getDefaultValue() ); - column.setSqlType( columnSource.getSqlType() ); - column.setSize( columnSource.getSize() ); - column.setDatatype( columnSource.getDatatype() ); - column.setReadFragment( columnSource.getReadFragment() ); - column.setWriteFragment( columnSource.getWriteFragment() ); - column.setUnique( columnSource.isUnique() ); - column.setCheckCondition( columnSource.getCheckCondition() ); - column.setComment( columnSource.getComment() ); - return column; - } - - private DerivedValue makeDerivedValue(DerivedValueSource derivedValueSource, TableSpecification table) { - return table.locateOrCreateDerivedValue( derivedValueSource.getExpression() ); - } - - private void processFetchProfiles(EntitySource entitySource, EntityBinding entityBinding) { - // todo : process the entity-local fetch-profile declaration - } - - private static class AttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { - private final String attributeName; - private Class javaType = null; - - private AttributeJavaTypeDeterminerDelegate(String attributeName) { - this.attributeName = attributeName; - } - - @Override - public void processBeanInfo(BeanInfo beanInfo) throws Exception { - for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { - if ( propertyDescriptor.getName().equals( attributeName ) ) { - javaType = propertyDescriptor.getPropertyType(); - break; - } - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java deleted file mode 100644 index 32877a0385..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbAnyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbBagElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbIdbagElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbListElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbMapElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSetElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSynchronizeElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public abstract class AbstractEntitySourceImpl implements EntitySource { - private final MappingDocument sourceMappingDocument; - private final EntityElement entityElement; - - private List subclassEntitySources = new ArrayList(); - - protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { - this.sourceMappingDocument = sourceMappingDocument; - this.entityElement = entityElement; - } - - protected EntityElement entityElement() { - return entityElement; - } - - protected MappingDocument sourceMappingDocument() { - return sourceMappingDocument; - } - - @Override - public Origin getOrigin() { - return sourceMappingDocument.getOrigin(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return sourceMappingDocument.getMappingLocalBindingContext(); - } - - @Override - public String getEntityName() { - return StringHelper.isNotEmpty( entityElement.getEntityName() ) - ? entityElement.getEntityName() - : getClassName(); - } - - @Override - public String getClassName() { - return getLocalBindingContext().qualifyClassName( entityElement.getName() ); - } - - @Override - public String getJpaEntityName() { - return null; - } - - @Override - public boolean isAbstract() { - return Helper.getBooleanValue( entityElement.isAbstract(), false ); - } - - @Override - public boolean isLazy() { - return Helper.getBooleanValue( entityElement.isAbstract(), true ); - } - - @Override - public String getProxy() { - return entityElement.getProxy(); - } - - @Override - public int getBatchSize() { - return Helper.getIntValue( entityElement.getBatchSize(), -1 ); - } - - @Override - public boolean isDynamicInsert() { - return entityElement.isDynamicInsert(); - } - - @Override - public boolean isDynamicUpdate() { - return entityElement.isDynamicUpdate(); - } - - @Override - public boolean isSelectBeforeUpdate() { - return entityElement.isSelectBeforeUpdate(); - } - - protected EntityMode determineEntityMode() { - return StringHelper.isNotEmpty( getClassName() ) ? EntityMode.POJO : EntityMode.MAP; - } - - @Override - public String getCustomTuplizerClassName() { - if ( entityElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = determineEntityMode(); - for ( JaxbTuplizerElement tuplizerElement : entityElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public String getCustomPersisterClassName() { - return getLocalBindingContext().qualifyClassName( entityElement.getPersister() ); - } - - @Override - public String getCustomLoaderName() { - return entityElement.getLoader() != null ? entityElement.getLoader().getQueryRef() : null; - } - - @Override - public CustomSQL getCustomSqlInsert() { - return Helper.buildCustomSql( entityElement.getSqlInsert() ); - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return Helper.buildCustomSql( entityElement.getSqlUpdate() ); - } - - @Override - public CustomSQL getCustomSqlDelete() { - return Helper.buildCustomSql( entityElement.getSqlDelete() ); - } - - @Override - public List getSynchronizedTableNames() { - List tableNames = new ArrayList(); - for ( JaxbSynchronizeElement synchronizeElement : entityElement.getSynchronize() ) { - tableNames.add( synchronizeElement.getTable() ); - } - return tableNames; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( entityElement.getMeta() ); - } - - @Override - public String getPath() { - return sourceMappingDocument.getMappingLocalBindingContext().determineEntityName( entityElement ); - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attributeElement : entityElement.getPropertyOrManyToOneOrOneToOne() ) { - if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new PropertyAttributeSourceImpl( - JaxbPropertyElement.class.cast( attributeElement ), - sourceMappingDocument().getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ComponentAttributeSourceImpl( - (JaxbComponentElement) attributeElement, - this, - sourceMappingDocument.getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ManyToOneAttributeSourceImpl( - JaxbManyToOneElement.class.cast( attributeElement ), - sourceMappingDocument().getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbBagElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new BagAttributeSourceImpl( - JaxbBagElement.class.cast( attributeElement ), - this - ) - ); - } - else if ( JaxbIdbagElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbSetElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new SetAttributeSourceImpl( - JaxbSetElement.class.cast( attributeElement ), - this - ) - ); - } - else if ( JaxbListElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbMapElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else { - throw new AssertionFailure( "Unexpected attribute element type encountered : " + attributeElement.getClass() ); - } - } - return attributeSources; - } - - private EntityHierarchyImpl entityHierarchy; - - public void injectHierarchy(EntityHierarchyImpl entityHierarchy) { - this.entityHierarchy = entityHierarchy; - } - - @Override - public void add(SubclassEntitySource subclassEntitySource) { - add( (SubclassEntitySourceImpl) subclassEntitySource ); - } - - public void add(SubclassEntitySourceImpl subclassEntitySource) { - entityHierarchy.processSubclass( subclassEntitySource ); - subclassEntitySources.add( subclassEntitySource ); - } - - @Override - public Iterable subclassEntitySources() { - return subclassEntitySources; - } - - @Override - public String getDiscriminatorMatchValue() { - return null; - } - - @Override - public Iterable getConstraints() { - return Collections.emptySet(); - } - - @Override - public Iterable getSecondaryTables() { - return Collections.emptySet(); - } - - @Override - public List getJpaCallbackClasses() { - return Collections.EMPTY_LIST; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java deleted file mode 100644 index b091df0f2f..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbAnyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToManyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToManyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.ComponentAttributeSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; - -/** - * @author Steve Ebersole - */ -public class ComponentAttributeSourceImpl implements ComponentAttributeSource { - private final JaxbComponentElement componentElement; - private final AttributeSourceContainer parentContainer; - - private final ValueHolder> componentClassReference; - private final String path; - - public ComponentAttributeSourceImpl( - JaxbComponentElement componentElement, - AttributeSourceContainer parentContainer, - LocalBindingContext bindingContext) { - this.componentElement = componentElement; - this.parentContainer = parentContainer; - - this.componentClassReference = bindingContext.makeClassReference( - bindingContext.qualifyClassName( componentElement.getClazz() ) - ); - this.path = parentContainer.getPath() + '.' + componentElement.getName(); - } - - @Override - public String getClassName() { - return componentElement.getClazz(); - } - - @Override - public ValueHolder> getClassReference() { - return componentClassReference; - } - - @Override - public String getPath() { - return path; - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return parentContainer.getLocalBindingContext(); - } - - @Override - public String getParentReferenceAttributeName() { - return componentElement.getParent() == null ? null : componentElement.getParent().getName(); - } - - @Override - public String getExplicitTuplizerClassName() { - if ( componentElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = StringHelper.isEmpty( componentElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; - for ( JaxbTuplizerElement tuplizerElement : componentElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attributeElement : componentElement.getPropertyOrManyToOneOrOneToOne() ) { - if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new PropertyAttributeSourceImpl( - JaxbPropertyElement.class.cast( attributeElement ), - getLocalBindingContext() - ) - ); - } - else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ComponentAttributeSourceImpl( - (JaxbComponentElement) attributeElement, - this, - getLocalBindingContext() - ) - ); - } - else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ManyToOneAttributeSourceImpl( - JaxbManyToOneElement.class.cast( attributeElement ), - getLocalBindingContext() - ) - ); - } - else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbOneToManyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbManyToManyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - } - return attributeSources; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.COMPONENT; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - // does not support type information. - return null; - } - - @Override - public String getName() { - return componentElement.getName(); - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public String getPropertyAccessorName() { - return componentElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return componentElement.isInsert(); - } - - @Override - public boolean isUpdatable() { - return componentElement.isUpdate(); - } - - @Override - public PropertyGeneration getGeneration() { - // todo : is this correct here? - return null; - } - - @Override - public boolean isLazy() { - return componentElement.isLazy(); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return componentElement.isOptimisticLock(); - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( componentElement.getMeta() ); - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return isInsertable(); - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return isUpdatable(); - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public List relationalValueSources() { - // none, they are defined on the simple sub-attributes - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java deleted file mode 100644 index 50181f6380..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCompositeElementElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.CompositePluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; - -/** - * @author Steve Ebersole - */ -public class CompositePluralAttributeElementSourceImpl implements CompositePluralAttributeElementSource { - private final JaxbCompositeElementElement compositeElement; - private final LocalBindingContext bindingContext; - - public CompositePluralAttributeElementSourceImpl( - JaxbCompositeElementElement compositeElement, - LocalBindingContext bindingContext) { - this.compositeElement = compositeElement; - this.bindingContext = bindingContext; - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.COMPONENT; - } - - @Override - public String getClassName() { - return bindingContext.qualifyClassName( compositeElement.getClazz() ); - } - - @Override - public ValueHolder> getClassReference() { - return bindingContext.makeClassReference( getClassName() ); - } - - @Override - public String getParentReferenceAttributeName() { - return compositeElement.getParent() != null - ? compositeElement.getParent().getName() - : null; - } - - @Override - public String getExplicitTuplizerClassName() { - if ( compositeElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = StringHelper.isEmpty( compositeElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; - for ( JaxbTuplizerElement tuplizerElement : compositeElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public String getPath() { - // todo : implementing this requires passing in the collection source and being able to resolve the collection's role - return null; - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attribute : compositeElement.getPropertyOrManyToOneOrAny() ) { - - } - return attributeSources; - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return bindingContext; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java deleted file mode 100644 index c35775989d..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.binder.Binder; - -/** - * The {@link org.hibernate.metamodel.source.MetadataSourceProcessor} implementation responsible for processing {@code hbm.xml} sources. - * - * @author Steve Ebersole - */ -public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor { - private final MetadataImplementor metadata; - - private List processors = new ArrayList(); - private List entityHierarchies; - - public HbmMetadataSourceProcessorImpl(MetadataImplementor metadata) { - this.metadata = metadata; - } - - @Override - @SuppressWarnings( {"unchecked"}) - public void prepare(MetadataSources sources) { - final HierarchyBuilder hierarchyBuilder = new HierarchyBuilder(); - - for ( JaxbRoot jaxbRoot : sources.getJaxbRootList() ) { - if ( ! JaxbHibernateMapping.class.isInstance( jaxbRoot.getRoot() ) ) { - continue; - } - - final MappingDocument mappingDocument = new MappingDocument( jaxbRoot, metadata ); - processors.add( new HibernateMappingProcessor( metadata, mappingDocument ) ); - - hierarchyBuilder.processMappingDocument( mappingDocument ); - } - - this.entityHierarchies = hierarchyBuilder.groupEntityHierarchies(); - } - - @Override - public void processIndependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processIndependentMetadata(); - } - } - - @Override - public void processTypeDependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processTypeDependentMetadata(); - } - } - - @Override - public void processMappingMetadata(MetadataSources sources, List processedEntityNames) { - Binder binder = new Binder( metadata, processedEntityNames ); - for ( EntityHierarchyImpl entityHierarchy : entityHierarchies ) { - binder.processEntityHierarchy( entityHierarchy ); - } - } - - @Override - public void processMappingDependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processMappingDependentMetadata(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java deleted file mode 100644 index aa10976d26..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.MappingException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbMetaElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbParamElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.binding.MetaAttribute; -import org.hibernate.metamodel.relational.Identifier; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.service.ServiceRegistry; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class Helper { - public static final ExplicitHibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - return null; - } - - @Override - public Map getParameters() { - return null; - } - }; - - public static InheritanceType interpretInheritanceType(EntityElement entityElement) { - if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.SINGLE_TABLE; - } - else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.JOINED; - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.TABLE_PER_CLASS; - } - else { - return InheritanceType.NO_INHERITANCE; - } - } - - /** - * Given a user-specified description of how to perform custom SQL, build the {@link CustomSQL} representation. - * - * @param customSqlElement User-specified description of how to perform custom SQL - * - * @return The {@link CustomSQL} representation - */ - public static CustomSQL buildCustomSql(CustomSqlElement customSqlElement) { - if ( customSqlElement == null ) { - return null; - } - final ExecuteUpdateResultCheckStyle checkStyle = customSqlElement.getCheck() == null - ? customSqlElement.isCallable() - ? ExecuteUpdateResultCheckStyle.NONE - : ExecuteUpdateResultCheckStyle.COUNT - : ExecuteUpdateResultCheckStyle.fromExternalName( customSqlElement.getCheck().value() ); - return new CustomSQL( customSqlElement.getValue(), customSqlElement.isCallable(), checkStyle ); - } - - /** - * Given the user-specified entity mapping, determine the appropriate entity name - * - * @param entityElement The user-specified entity mapping - * @param unqualifiedClassPackage The package to use for unqualified class names - * - * @return The appropriate entity name - */ - public static String determineEntityName(EntityElement entityElement, String unqualifiedClassPackage) { - return entityElement.getEntityName() != null - ? entityElement.getEntityName() - : qualifyIfNeeded( entityElement.getName(), unqualifiedClassPackage ); - } - - /** - * Qualify a (supposed class) name with the unqualified-class package name if it is not already qualified - * - * @param name The name - * @param unqualifiedClassPackage The unqualified-class package name - * - * @return {@code null} if the incoming name was {@code null}; or the qualified name. - */ - public static String qualifyIfNeeded(String name, String unqualifiedClassPackage) { - if ( name == null ) { - return null; - } - if ( name.indexOf( '.' ) < 0 && unqualifiedClassPackage != null ) { - return unqualifiedClassPackage + '.' + name; - } - return name; - } - - public static String getPropertyAccessorName(String access, boolean isEmbedded, String defaultAccess) { - return getStringValue( access, isEmbedded ? "embedded" : defaultAccess ); - } - - public static MetaAttributeContext extractMetaAttributeContext( - List metaElementList, - boolean onlyInheritable, - MetaAttributeContext parentContext) { - final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); - - for ( JaxbMetaElement metaElement : metaElementList ) { - if ( onlyInheritable & !metaElement.isInherit() ) { - continue; - } - - final String name = metaElement.getAttribute(); - final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); - MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); - if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { - metaAttribute = new MetaAttribute( name ); - subContext.add( metaAttribute ); - } - metaAttribute.addValue( metaElement.getValue() ); - } - - return subContext; - } - - public static String getStringValue(String value, String defaultValue) { - return value == null ? defaultValue : value; - } - - public static int getIntValue(String value, int defaultValue) { - return value == null ? defaultValue : Integer.parseInt( value ); - } - - public static long getLongValue(String value, long defaultValue) { - return value == null ? defaultValue : Long.parseLong( value ); - } - - public static boolean getBooleanValue(Boolean value, boolean defaultValue) { - return value == null ? defaultValue : value; - } - - public static Iterable interpretCascadeStyles(String cascades, LocalBindingContext bindingContext) { - final Set cascadeStyles = new HashSet(); - if ( StringHelper.isEmpty( cascades ) ) { - cascades = bindingContext.getMappingDefaults().getCascadeStyle(); - } - for ( String cascade : StringHelper.split( ",", cascades ) ) { - cascadeStyles.add( CascadeStyles.getCascadeStyle( cascade ) ); - } - return cascadeStyles; - } - - public static Map extractParameters(List xmlParamElements) { - if ( xmlParamElements == null || xmlParamElements.isEmpty() ) { - return null; - } - final HashMap params = new HashMap(); - for ( JaxbParamElement paramElement : xmlParamElements ) { - params.put( paramElement.getName(), paramElement.getValue() ); - } - return params; - } - - public static Iterable buildMetaAttributeSources(List metaElements) { - ArrayList result = new ArrayList(); - if ( metaElements == null || metaElements.isEmpty() ) { - // do nothing - } - else { - for ( final JaxbMetaElement metaElement : metaElements ) { - result.add( - new MetaAttributeSource() { - @Override - public String getName() { - return metaElement.getAttribute(); - } - - @Override - public String getValue() { - return metaElement.getValue(); - } - - @Override - public boolean isInheritable() { - return metaElement.isInherit(); - } - } - ); - } - } - return result; - } - - public static Schema.Name determineDatabaseSchemaName( - String explicitSchemaName, - String explicitCatalogName, - LocalBindingContext bindingContext) { - return new Schema.Name( - resolveIdentifier( - explicitSchemaName, - bindingContext.getMappingDefaults().getSchemaName(), - bindingContext.isGloballyQuotedIdentifiers() - ), - resolveIdentifier( - explicitCatalogName, - bindingContext.getMappingDefaults().getCatalogName(), - bindingContext.isGloballyQuotedIdentifiers() - ) - ); - } - - public static Identifier resolveIdentifier(String explicitName, String defaultName, boolean globalQuoting) { - String name = StringHelper.isNotEmpty( explicitName ) ? explicitName : defaultName; - if ( globalQuoting ) { - name = StringHelper.quote( name ); - } - return Identifier.toIdentifier( name ); - } - - public static class ValueSourcesAdapter { - public String getContainingTableName() { - return null; - } - - public boolean isIncludedInInsertByDefault() { - return false; - } - - public boolean isIncludedInUpdateByDefault() { - return false; - } - - public String getColumnAttribute() { - return null; - } - - public String getFormulaAttribute() { - return null; - } - - public List getColumnOrFormulaElements() { - return null; - } - - public boolean isForceNotNull() { - return false; - } - } - - public static List buildValueSources( - ValueSourcesAdapter valueSourcesAdapter, - LocalBindingContext bindingContext) { - List result = new ArrayList(); - - if ( StringHelper.isNotEmpty( valueSourcesAdapter.getColumnAttribute() ) ) { - if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - throw new org.hibernate.metamodel.source.MappingException( - "column/formula attribute may not be used together with / subelement", - bindingContext.getOrigin() - ); - } - if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { - throw new org.hibernate.metamodel.source.MappingException( - "column and formula attributes may not be used together", - bindingContext.getOrigin() - ); - } - result.add( - new ColumnAttributeSourceImpl( - valueSourcesAdapter.getContainingTableName(), - valueSourcesAdapter.getColumnAttribute(), - valueSourcesAdapter.isIncludedInInsertByDefault(), - valueSourcesAdapter.isIncludedInUpdateByDefault(), - valueSourcesAdapter.isForceNotNull() - ) - ); - } - else if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { - if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - throw new org.hibernate.metamodel.source.MappingException( - "column/formula attribute may not be used together with / subelement", - bindingContext.getOrigin() - ); - } - // column/formula attribute combo checked already - result.add( - new FormulaImpl( - valueSourcesAdapter.getContainingTableName(), - valueSourcesAdapter.getFormulaAttribute() - ) - ); - } - else if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - for ( Object columnOrFormulaElement : valueSourcesAdapter.getColumnOrFormulaElements() ) { - if ( JaxbColumnElement.class.isInstance( columnOrFormulaElement ) ) { - result.add( - new ColumnSourceImpl( - valueSourcesAdapter.getContainingTableName(), - (JaxbColumnElement) columnOrFormulaElement, - valueSourcesAdapter.isIncludedInInsertByDefault(), - valueSourcesAdapter.isIncludedInUpdateByDefault(), - valueSourcesAdapter.isForceNotNull() - ) - ); - } - else { - result.add( - new FormulaImpl( - valueSourcesAdapter.getContainingTableName(), - (String) columnOrFormulaElement - ) - ); - } - } - } - return result; - } - - // todo : remove this once the state objects are cleaned up - - public static Class classForName(String className, ServiceRegistry serviceRegistry) { - ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - try { - return classLoaderService.classForName( className ); - } - catch ( ClassLoadingException e ) { - throw new MappingException( "Could not find class: " + className ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java deleted file mode 100644 index b03c33ab7b..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbParamElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbQueryElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSqlQueryElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject; -import org.hibernate.metamodel.relational.BasicAuxiliaryDatabaseObjectImpl; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.type.Type; - -/** - * Responsible for processing a {@code } element. Allows processing to be coordinated across - * all hbm files in an ordered fashion. The order is essentially the same as defined in - * {@link org.hibernate.metamodel.source.MetadataSourceProcessor} - * - * @author Steve Ebersole - */ -public class HibernateMappingProcessor { - private final MetadataImplementor metadata; - private final MappingDocument mappingDocument; - - private ValueHolder classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return metadata.getServiceRegistry().getService( ClassLoaderService.class ); - } - } - ); - - public HibernateMappingProcessor(MetadataImplementor metadata, MappingDocument mappingDocument) { - this.metadata = metadata; - this.mappingDocument = mappingDocument; - } - - private JaxbHibernateMapping mappingRoot() { - return mappingDocument.getMappingRoot(); - } - - private Origin origin() { - return mappingDocument.getOrigin(); - } - - private HbmBindingContext bindingContext() { - return mappingDocument.getMappingLocalBindingContext(); - } - - private Class classForName(String name) { - return classLoaderService.getValue().classForName( bindingContext().qualifyClassName( name ) ); - } - - public void processIndependentMetadata() { - processDatabaseObjectDefinitions(); - processTypeDefinitions(); - } - - private void processDatabaseObjectDefinitions() { - if ( mappingRoot().getDatabaseObject() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbDatabaseObject databaseObjectElement : mappingRoot().getDatabaseObject() ) { - final AuxiliaryDatabaseObject auxiliaryDatabaseObject; - if ( databaseObjectElement.getDefinition() != null ) { - final String className = databaseObjectElement.getDefinition().getClazz(); - try { - auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classForName( className ).newInstance(); - } - catch (ClassLoadingException e) { - throw e; - } - catch (Exception e) { - throw new MappingException( - "could not instantiate custom database object class [" + className + "]", - origin() - ); - } - } - else { - Set dialectScopes = new HashSet(); - if ( databaseObjectElement.getDialectScope() != null ) { - for ( JaxbHibernateMapping.JaxbDatabaseObject.JaxbDialectScope dialectScope : databaseObjectElement.getDialectScope() ) { - dialectScopes.add( dialectScope.getName() ); - } - } - auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl( - metadata.getDatabase().getDefaultSchema(), - databaseObjectElement.getCreate(), - databaseObjectElement.getDrop(), - dialectScopes - ); - } - metadata.getDatabase().addAuxiliaryDatabaseObject( auxiliaryDatabaseObject ); - } - } - - private void processTypeDefinitions() { - if ( mappingRoot().getTypedef() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbTypedef typedef : mappingRoot().getTypedef() ) { - final Map parameters = new HashMap(); - for ( JaxbParamElement paramElement : typedef.getParam() ) { - parameters.put( paramElement.getName(), paramElement.getValue() ); - } - metadata.addTypeDefinition( - new TypeDef( - typedef.getName(), - typedef.getClazz(), - parameters - ) - ); - } - } - - public void processTypeDependentMetadata() { - processFilterDefinitions(); - processIdentifierGenerators(); - } - - private void processFilterDefinitions() { - if ( mappingRoot().getFilterDef() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbFilterDef filterDefinition : mappingRoot().getFilterDef() ) { - final String name = filterDefinition.getName(); - final Map parameters = new HashMap(); - String condition = null; - for ( Object o : filterDefinition.getContent() ) { - if ( o instanceof String ) { - // represents the condition - if ( condition != null ) { - // log? - } - condition = (String) o; - } - else if ( o instanceof JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam ) { - final JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam paramElement = - JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam.class.cast( o ); - // todo : should really delay this resolution until later to allow typedef names - parameters.put( - paramElement.getName(), - metadata.getTypeResolver().heuristicType( paramElement.getType() ) - ); - } - else { - throw new MappingException( "Unrecognized nested filter content", origin() ); - } - } - if ( condition == null ) { - condition = filterDefinition.getCondition(); - } - metadata.addFilterDefinition( new FilterDefinition( name, condition, parameters ) ); - } - } - - private void processIdentifierGenerators() { - if ( mappingRoot().getIdentifierGenerator() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbIdentifierGenerator identifierGeneratorElement : mappingRoot().getIdentifierGenerator() ) { - metadata.registerIdentifierGenerator( - identifierGeneratorElement.getName(), - identifierGeneratorElement.getClazz() - ); - } - } - - public void processMappingDependentMetadata() { - processFetchProfiles(); - processImports(); - processResultSetMappings(); - processNamedQueries(); - } - - private void processFetchProfiles(){ - if ( mappingRoot().getFetchProfile() == null ) { - return; - } - - processFetchProfiles( mappingRoot().getFetchProfile(), null ); - } - - public void processFetchProfiles(List fetchProfiles, String containingEntityName) { - for ( JaxbFetchProfileElement fetchProfile : fetchProfiles ) { - String profileName = fetchProfile.getName(); - Set fetches = new HashSet(); - for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfile.getFetch() ) { - String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity(); - if ( entityName == null ) { - throw new MappingException( - "could not determine entity for fetch-profile fetch [" + profileName + "]:[" + - fetch.getAssociation() + "]", - origin() - ); - } - fetches.add( new FetchProfile.Fetch( entityName, fetch.getAssociation(), fetch.getStyle() ) ); - } - metadata.addFetchProfile( new FetchProfile( profileName, fetches ) ); - } - } - - private void processImports() { - if ( mappingRoot().getImport() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbImport importValue : mappingRoot().getImport() ) { - String className = mappingDocument.getMappingLocalBindingContext().qualifyClassName( importValue.getClazz() ); - String rename = importValue.getRename(); - rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename; - metadata.addImport( className, rename ); - } - } - - private void processResultSetMappings() { - if ( mappingRoot().getResultset() == null ) { - return; - } - -// bindResultSetMappingDefinitions( element, null, mappings ); - } - - private void processNamedQueries() { - if ( mappingRoot().getQueryOrSqlQuery() == null ) { - return; - } - - for ( Object queryOrSqlQuery : mappingRoot().getQueryOrSqlQuery() ) { - if ( JaxbQueryElement.class.isInstance( queryOrSqlQuery ) ) { -// bindNamedQuery( element, null, mappings ); - } - else if ( JaxbSqlQueryElement.class.isInstance( queryOrSqlQuery ) ) { -// bindNamedSQLQuery( element, null, mappings ); - } - else { - throw new MappingException( - "unknown type of query: " + - queryOrSqlQuery.getClass().getName(), origin() - ); - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java deleted file mode 100644 index 2582a8b32f..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.hibernate.MappingException; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement; -import org.hibernate.metamodel.source.binder.SubclassEntityContainer; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - -/** - * @author Steve Ebersole - */ -public class HierarchyBuilder { - private final List entityHierarchies = new ArrayList(); - - // process state - private final Map subEntityContainerMap = new HashMap(); - private final List extendsQueue = new ArrayList(); - - // mapping file specific state - private MappingDocument currentMappingDocument; - - public void processMappingDocument(MappingDocument mappingDocument) { - this.currentMappingDocument = mappingDocument; - try { - processCurrentMappingDocument(); - } - finally { - this.currentMappingDocument = null; - } - } - - private void processCurrentMappingDocument() { - for ( Object entityElementO : currentMappingDocument.getMappingRoot().getClazzOrSubclassOrJoinedSubclass() ) { - final EntityElement entityElement = (EntityElement) entityElementO; - if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) { - // we can immediately handle elements in terms of creating the hierarchy entry - final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement; - final RootEntitySourceImpl rootEntitySource = new RootEntitySourceImpl( currentMappingDocument, - jaxbClass - ); - final EntityHierarchyImpl hierarchy = new EntityHierarchyImpl( rootEntitySource ); - - entityHierarchies.add( hierarchy ); - subEntityContainerMap.put( rootEntitySource.getEntityName(), rootEntitySource ); - - processSubElements( entityElement, rootEntitySource ); - } - else { - // we have to see if this things super-type has been found yet, and if not add it to the - // extends queue - final SubclassEntitySourceImpl subClassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, entityElement ); - final String entityName = subClassEntitySource.getEntityName(); - subEntityContainerMap.put( entityName, subClassEntitySource ); - final String entityItExtends = currentMappingDocument.getMappingLocalBindingContext().qualifyClassName( - ((SubEntityElement) entityElement).getExtends() - ); - processSubElements( entityElement, subClassEntitySource ); - final SubclassEntityContainer container = subEntityContainerMap.get( entityItExtends ); - if ( container != null ) { - // we already have this entity's super, attach it and continue - container.add( subClassEntitySource ); - } - else { - // we do not yet have the super and have to wait, so add it fto the extends queue - extendsQueue.add( new ExtendsQueueEntry( subClassEntitySource, entityItExtends ) ); - } - } - } - } - - public List groupEntityHierarchies() { - while ( ! extendsQueue.isEmpty() ) { - // set up a pass over the queue - int numberOfMappingsProcessed = 0; - Iterator iterator = extendsQueue.iterator(); - while ( iterator.hasNext() ) { - final ExtendsQueueEntry entry = iterator.next(); - final SubclassEntityContainer container = subEntityContainerMap.get( entry.entityItExtends ); - if ( container != null ) { - // we now have this entity's super, attach it and remove entry from extends queue - container.add( entry.subClassEntitySource ); - iterator.remove(); - numberOfMappingsProcessed++; - } - } - - if ( numberOfMappingsProcessed == 0 ) { - // todo : we could log the waiting dependencies... - throw new MappingException( "Unable to process extends dependencies in hbm files" ); - } - } - - return entityHierarchies; - } - - private void processSubElements(EntityElement entityElement, SubclassEntityContainer container) { - if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) { - final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement; - processElements( jaxbClass.getJoinedSubclass(), container ); - processElements( jaxbClass.getSubclass(), container ); - processElements( jaxbClass.getUnionSubclass(), container ); - } - else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { - final JaxbSubclassElement jaxbSubclass = (JaxbSubclassElement) entityElement; - processElements( jaxbSubclass.getSubclass(), container ); - } - else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { - final JaxbJoinedSubclassElement jaxbJoinedSubclass = (JaxbJoinedSubclassElement) entityElement; - processElements( jaxbJoinedSubclass.getJoinedSubclass(), container ); - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { - final JaxbUnionSubclassElement jaxbUnionSubclass = (JaxbUnionSubclassElement) entityElement; - processElements( jaxbUnionSubclass.getUnionSubclass(), container ); - } - } - - private void processElements(List subElements, SubclassEntityContainer container) { - for ( Object subElementO : subElements ) { - final SubEntityElement subElement = (SubEntityElement) subElementO; - final SubclassEntitySourceImpl subclassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, subElement ); - container.add( subclassEntitySource ); - final String subEntityName = subclassEntitySource.getEntityName(); - subEntityContainerMap.put( subEntityName, subclassEntitySource ); - } - } - - private static class ExtendsQueueEntry { - private final SubclassEntitySource subClassEntitySource; - private final String entityItExtends; - - private ExtendsQueueEntry(SubclassEntitySource subClassEntitySource, String entityItExtends) { - this.subClassEntitySource = subClassEntitySource; - this.entityItExtends = entityItExtends; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java deleted file mode 100644 index e4618e76cf..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.FetchMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToManyElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ManyToManyPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; -import org.hibernate.metamodel.source.binder.RelationalValueSource; - -/** - * @author Steve Ebersole - */ -public class ManyToManyPluralAttributeElementSourceImpl implements ManyToManyPluralAttributeElementSource { - private final JaxbManyToManyElement manyToManyElement; - private final LocalBindingContext bindingContext; - - private final List valueSources; - - public ManyToManyPluralAttributeElementSourceImpl( - final JaxbManyToManyElement manyToManyElement, - final LocalBindingContext bindingContext) { - this.manyToManyElement = manyToManyElement; - this.bindingContext = bindingContext; - - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return true; - } - - @Override - public String getColumnAttribute() { - return manyToManyElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return manyToManyElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return manyToManyElement.getColumnOrFormula(); - } - }, - bindingContext - ); - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.MANY_TO_MANY; - } - - @Override - public String getReferencedEntityName() { - return StringHelper.isNotEmpty( manyToManyElement.getEntityName() ) - ? manyToManyElement.getEntityName() - : bindingContext.qualifyClassName( manyToManyElement.getClazz() ); - } - - @Override - public String getReferencedEntityAttributeName() { - return manyToManyElement.getPropertyRef(); - } - - @Override - public List getValueSources() { - return valueSources; - } - - @Override - public boolean isNotFoundAnException() { - return manyToManyElement.getNotFound() == null - || ! "ignore".equals( manyToManyElement.getNotFound().value() ); - } - - @Override - public String getExplicitForeignKeyName() { - return manyToManyElement.getForeignKey(); - } - - @Override - public boolean isUnique() { - return manyToManyElement.isUnique(); - } - - @Override - public String getOrderBy() { - return manyToManyElement.getOrderBy(); - } - - @Override - public String getWhere() { - return manyToManyElement.getWhere(); - } - - @Override - public FetchMode getFetchMode() { - return null; - } - - @Override - public boolean fetchImmediately() { - if ( manyToManyElement.getLazy() != null ) { - if ( "false".equals( manyToManyElement.getLazy().value() ) ) { - return true; - } - } - - if ( manyToManyElement.getOuterJoin() == null ) { - return ! bindingContext.getMappingDefaults().areAssociationsLazy(); - } - else { - final String value = manyToManyElement.getOuterJoin().value(); - if ( "auto".equals( value ) ) { - return ! bindingContext.getMappingDefaults().areAssociationsLazy(); - } - return "true".equals( value ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java deleted file mode 100644 index 902bec8dfd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.ToOneAttributeSource; - -/** - * Implementation for {@code mappings} - * - * @author Steve Ebersole - */ -class ManyToOneAttributeSourceImpl implements ToOneAttributeSource { - private final JaxbManyToOneElement manyToOneElement; - private final LocalBindingContext bindingContext; - private final List valueSources; - - ManyToOneAttributeSourceImpl(final JaxbManyToOneElement manyToOneElement, LocalBindingContext bindingContext) { - this.manyToOneElement = manyToOneElement; - this.bindingContext = bindingContext; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return manyToOneElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return manyToOneElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return manyToOneElement.getColumnOrFormula(); - } - - @Override - public String getContainingTableName() { - // todo : need to implement this... - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return manyToOneElement.isUpdate(); - } - }, - bindingContext - ); - } - - @Override - public String getName() { - return manyToOneElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return Helper.TO_ONE_ATTRIBUTE_TYPE_SOURCE; - } - - @Override - public String getPropertyAccessorName() { - return manyToOneElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean isUpdatable() { - return manyToOneElement.isUpdate(); - } - - @Override - public PropertyGeneration getGeneration() { - return PropertyGeneration.NEVER; - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return manyToOneElement.isOptimisticLock(); - } - - @Override - public Iterable getCascadeStyles() { - return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext ); - } - - @Override - public FetchTiming getFetchTiming() { - final String fetchSelection = manyToOneElement.getFetch() != null - ? manyToOneElement.getFetch().value() - : null; - final String lazySelection = manyToOneElement.getLazy() != null - ? manyToOneElement.getLazy().value() - : null; - final String outerJoinSelection = manyToOneElement.getOuterJoin() != null - ? manyToOneElement.getOuterJoin().value() - : null; - - if ( lazySelection == null ) { - if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { - return FetchTiming.IMMEDIATE; - } - else if ( "false".equals( outerJoinSelection ) ) { - return FetchTiming.DELAYED; - } - else { - return bindingContext.getMappingDefaults().areAssociationsLazy() - ? FetchTiming.DELAYED - : FetchTiming.IMMEDIATE; - } - } - else if ( "extra".equals( lazySelection ) ) { - return FetchTiming.EXTRA_LAZY; - } - else if ( "true".equals( lazySelection ) ) { - return FetchTiming.DELAYED; - } - else if ( "false".equals( lazySelection ) ) { - return FetchTiming.IMMEDIATE; - } - - throw new MappingException( - String.format( - "Unexpected lazy selection [%s] on '%s'", - lazySelection, - manyToOneElement.getName() - ), - bindingContext.getOrigin() - ); - } - - @Override - public FetchStyle getFetchStyle() { - // todo : handle batch fetches? - - final String fetchSelection = manyToOneElement.getFetch() != null - ? manyToOneElement.getFetch().value() - : null; - final String outerJoinSelection = manyToOneElement.getOuterJoin() != null - ? manyToOneElement.getOuterJoin().value() - : null; - - if ( fetchSelection == null ) { - if ( outerJoinSelection == null ) { - return FetchStyle.SELECT; - } - else { - if ( "auto".equals( outerJoinSelection ) ) { - return bindingContext.getMappingDefaults().areAssociationsLazy() - ? FetchStyle.SELECT - : FetchStyle.JOIN; - } - else { - return "true".equals( outerJoinSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - } - else { - return "join".equals( fetchSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - - @Override - public FetchMode getFetchMode() { - return manyToOneElement.getFetch() == null - ? FetchMode.DEFAULT - : FetchMode.valueOf( manyToOneElement.getFetch().value() ); - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.MANY_TO_ONE; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return manyToOneElement.isUpdate(); - } - - @Override - public boolean areValuesNullableByDefault() { - return ! Helper.getBooleanValue( manyToOneElement.isNotNull(), false ); - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( manyToOneElement.getMeta() ); - } - - @Override - public String getReferencedEntityName() { - return manyToOneElement.getClazz() != null - ? manyToOneElement.getClazz() - : manyToOneElement.getEntityName(); - } - - @Override - public String getReferencedEntityAttributeName() { - return manyToOneElement.getPropertyRef(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java deleted file mode 100644 index d184a4898d..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.EntityMode; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.IdentifierSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - */ -public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements RootEntitySource { - protected RootEntitySourceImpl(MappingDocument sourceMappingDocument, JaxbHibernateMapping.JaxbClass entityElement) { - super( sourceMappingDocument, entityElement ); - } - - @Override - protected JaxbHibernateMapping.JaxbClass entityElement() { - return (JaxbHibernateMapping.JaxbClass) super.entityElement(); - } - - @Override - public IdentifierSource getIdentifierSource() { - if ( entityElement().getId() != null ) { - return new SimpleIdentifierSource() { - @Override - public SingularAttributeSource getIdentifierAttributeSource() { - return new SingularIdentifierAttributeSourceImpl( - entityElement().getId(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - - @Override - public IdGenerator getIdentifierGeneratorDescriptor() { - if ( entityElement().getId().getGenerator() != null ) { - final String generatorName = entityElement().getId().getGenerator().getClazz(); - IdGenerator idGenerator = sourceMappingDocument().getMappingLocalBindingContext() - .getMetadataImplementor() - .getIdGenerator( generatorName ); - if ( idGenerator == null ) { - idGenerator = new IdGenerator( - getEntityName() + generatorName, - generatorName, - Helper.extractParameters( entityElement().getId().getGenerator().getParam() ) - ); - } - return idGenerator; - } - return null; - } - - @Override - public Nature getNature() { - return Nature.SIMPLE; - } - }; - } - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public SingularAttributeSource getVersioningAttributeSource() { - if ( entityElement().getVersion() != null ) { - return new VersionAttributeSourceImpl( - entityElement().getVersion(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - else if ( entityElement().getTimestamp() != null ) { - return new TimestampAttributeSourceImpl( - entityElement().getTimestamp(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - return null; - } - - @Override - public EntityMode getEntityMode() { - return determineEntityMode(); - } - - @Override - public boolean isMutable() { - return entityElement().isMutable(); - } - - - @Override - public boolean isExplicitPolymorphism() { - return "explicit".equals( entityElement().getPolymorphism() ); - } - - @Override - public String getWhere() { - return entityElement().getWhere(); - } - - @Override - public String getRowId() { - return entityElement().getRowid(); - } - - @Override - public OptimisticLockStyle getOptimisticLockStyle() { - final String optimisticLockModeString = Helper.getStringValue( entityElement().getOptimisticLock(), "version" ); - try { - return OptimisticLockStyle.valueOf( optimisticLockModeString.toUpperCase() ); - } - catch ( Exception e ) { - throw new MappingException( - "Unknown optimistic-lock value : " + optimisticLockModeString, - sourceMappingDocument().getOrigin() - ); - } - } - - @Override - public Caching getCaching() { - final JaxbCacheElement cache = entityElement().getCache(); - if ( cache == null ) { - return null; - } - final String region = cache.getRegion() != null ? cache.getRegion() : getEntityName(); - final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); - final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); - return new Caching( region, accessType, cacheLazyProps ); - } - - @Override - public TableSource getPrimaryTable() { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return entityElement().getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return entityElement().getCatalog(); - } - - @Override - public String getExplicitTableName() { - return entityElement().getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - - @Override - public String getDiscriminatorMatchValue() { - return entityElement().getDiscriminatorValue(); - } - - @Override - public DiscriminatorSource getDiscriminatorSource() { - final JaxbHibernateMapping.JaxbClass.JaxbDiscriminator discriminatorElement = entityElement().getDiscriminator(); - if ( discriminatorElement == null ) { - return null; - } - - return new DiscriminatorSource() { - @Override - public RelationalValueSource getDiscriminatorRelationalValueSource() { - if ( StringHelper.isNotEmpty( discriminatorElement.getColumnAttribute() ) ) { - return new ColumnAttributeSourceImpl( - null, // root table - discriminatorElement.getColumnAttribute(), - discriminatorElement.isInsert(), - discriminatorElement.isInsert() - ); - } - else if ( StringHelper.isNotEmpty( discriminatorElement.getFormulaAttribute() ) ) { - return new FormulaImpl( null, discriminatorElement.getFormulaAttribute() ); - } - else if ( discriminatorElement.getColumn() != null ) { - return new ColumnSourceImpl( - null, // root table - discriminatorElement.getColumn(), - discriminatorElement.isInsert(), - discriminatorElement.isInsert() - ); - } - else if ( StringHelper.isNotEmpty( discriminatorElement.getFormula() ) ) { - return new FormulaImpl( null, discriminatorElement.getFormula() ); - } - else { - throw new MappingException( "could not determine source of discriminator mapping", getOrigin() ); - } - } - - @Override - public String getExplicitHibernateTypeName() { - return discriminatorElement.getType(); - } - - @Override - public boolean isForced() { - return discriminatorElement.isForce(); - } - - @Override - public boolean isInserted() { - return discriminatorElement.isInsert(); - } - }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java deleted file mode 100644 index 473d8075fd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - */ -public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource { - protected SubclassEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { - super( sourceMappingDocument, entityElement ); - } - - @Override - public TableSource getPrimaryTable() { - if ( JaxbJoinedSubclassElement.class.isInstance( entityElement() ) ) { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getCatalog(); - } - - @Override - public String getExplicitTableName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement() ) ) { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getCatalog(); - } - - @Override - public String getExplicitTableName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - return null; - } - - @Override - public String getDiscriminatorMatchValue() { - return JaxbSubclassElement.class.isInstance( entityElement() ) - ? ( (JaxbSubclassElement) entityElement() ).getDiscriminatorValue() - : null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java deleted file mode 100644 index e0af68dd40..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SingularAssociationAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; - -/** - * @author Gail Badner - */ -class AssociationResolver { - private final MetadataImplementor metadata; - - AssociationResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - for ( SingularAssociationAttributeBinding attributeBinding : entityBinding.getEntityReferencingAttributeBindings() ) { - resolve( attributeBinding ); - } - } - } - - private void resolve(SingularAssociationAttributeBinding attributeBinding) { - if ( attributeBinding.getReferencedEntityName() == null ) { - throw new IllegalArgumentException( - "attributeBinding has null entityName: " + attributeBinding.getAttribute().getName() - ); - } - EntityBinding entityBinding = metadata.getEntityBinding( attributeBinding.getReferencedEntityName() ); - if ( entityBinding == null ) { - throw new org.hibernate.MappingException( - String.format( - "Attribute [%s] refers to unknown entity: [%s]", - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedEntityName() - ) - ); - } - AttributeBinding referencedAttributeBinding = - attributeBinding.isPropertyReference() ? - entityBinding.locateAttributeBinding( attributeBinding.getReferencedAttributeName() ) : - entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - if ( referencedAttributeBinding == null ) { - // TODO: does attribute name include path w/ entity name? - throw new org.hibernate.MappingException( - String.format( - "Attribute [%s] refers to unknown attribute: [%s]", - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedEntityName() - ) - ); - } - attributeBinding.resolveReference( referencedAttributeBinding ); - referencedAttributeBinding.addEntityReferencingAttributeBinding( attributeBinding ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java deleted file mode 100644 index 80572f327b..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.util.Properties; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.AbstractCollectionElement; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicCollectionElement; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Value; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.type.Type; -import org.hibernate.type.TypeFactory; - -/** - * This is a TEMPORARY way to initialize Hibernate types. - * This class will be removed when types are resolved properly. - * - * @author Gail Badner - */ -class HibernateTypeResolver { - - private final MetadataImplementor metadata; - - HibernateTypeResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - if ( entityBinding.getHierarchyDetails().getEntityDiscriminator() != null ) { - resolveDiscriminatorTypeInformation( entityBinding.getHierarchyDetails().getEntityDiscriminator() ); - } - for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { - if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { - resolveSingularAttributeTypeInformation( - SingularAttributeBinding.class.cast( attributeBinding ) - ); - } - else if ( AbstractPluralAttributeBinding.class.isInstance( attributeBinding ) ) { - resolvePluralAttributeTypeInformation( - AbstractPluralAttributeBinding.class.cast( attributeBinding ) - ); - } - else { - throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() ); - } - } - } - } - - // perform any needed type resolutions for discriminator - private void resolveDiscriminatorTypeInformation(EntityDiscriminator discriminator) { - // perform any needed type resolutions for discriminator - Type resolvedHibernateType = determineSingularTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() ); - if ( resolvedHibernateType != null ) { - pushHibernateTypeInformationDownIfNeeded( - discriminator.getExplicitHibernateTypeDescriptor(), - discriminator.getBoundValue(), - resolvedHibernateType - ); - } - } - - private Type determineSingularTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { - if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { - return hibernateTypeDescriptor.getResolvedTypeMapping(); - } - String typeName = determineTypeName( hibernateTypeDescriptor ); - Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); - return getHeuristicType( typeName, typeParameters ); - } - - private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) { - return hibernateTypeDescriptor.getExplicitTypeName() != null - ? hibernateTypeDescriptor.getExplicitTypeName() - : hibernateTypeDescriptor.getJavaTypeName(); - } - - private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) { - Properties typeParameters = new Properties( ); - if ( hibernateTypeDescriptor.getTypeParameters() != null ) { - typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() ); - } - return typeParameters; - } - - // perform any needed type resolutions for SingularAttributeBinding - private void resolveSingularAttributeTypeInformation(SingularAttributeBinding attributeBinding) { - if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { - return; - } - // we can determine the Hibernate Type if either: - // 1) the user explicitly named a Type in a HibernateTypeDescriptor - // 2) we know the java type of the attribute - Type resolvedType; - resolvedType = determineSingularTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() ); - if ( resolvedType == null ) { - if ( ! attributeBinding.getAttribute().isSingular() ) { - throw new AssertionFailure( "SingularAttributeBinding object has a plural attribute: " + attributeBinding.getAttribute().getName() ); - } - final SingularAttribute singularAttribute = ( SingularAttribute ) attributeBinding.getAttribute(); - if ( singularAttribute.getSingularAttributeType() != null ) { - resolvedType = getHeuristicType( - singularAttribute.getSingularAttributeType().getClassName(), new Properties() - ); - } - } - if ( resolvedType != null ) { - pushHibernateTypeInformationDownIfNeeded( attributeBinding, resolvedType ); - } - } - - // perform any needed type resolutions for PluralAttributeBinding - private void resolvePluralAttributeTypeInformation(AbstractPluralAttributeBinding attributeBinding) { - if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { - return; - } - Type resolvedType; - // do NOT look at java type... - //String typeName = determineTypeName( attributeBinding.getHibernateTypeDescriptor() ); - String typeName = attributeBinding.getHibernateTypeDescriptor().getExplicitTypeName(); - if ( typeName != null ) { - resolvedType = - metadata.getTypeResolver() - .getTypeFactory() - .customCollection( - typeName, - getTypeParameters( attributeBinding.getHibernateTypeDescriptor() ), - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - else { - resolvedType = determineDefaultCollectionInformation( attributeBinding ); - } - if ( resolvedType != null ) { - pushHibernateTypeInformationDownIfNeeded( - attributeBinding.getHibernateTypeDescriptor(), - null, - resolvedType ); - } - resolveCollectionElementTypeInformation( attributeBinding.getCollectionElement() ); - } - - private Type determineDefaultCollectionInformation(AbstractPluralAttributeBinding attributeBinding) { - final TypeFactory typeFactory = metadata.getTypeResolver().getTypeFactory(); - switch ( attributeBinding.getAttribute().getNature() ) { - case SET: { - return typeFactory.set( - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - case BAG: { - return typeFactory.bag( - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - default: { - throw new UnsupportedOperationException( - "Collection type not supported yet:" + attributeBinding.getAttribute().getNature() - ); - } - } - } - - private void resolveCollectionElementTypeInformation(AbstractCollectionElement collectionElement) { - switch ( collectionElement.getCollectionElementNature() ) { - case BASIC: { - resolveBasicCollectionElement( BasicCollectionElement.class.cast( collectionElement ) ); - break; - } - case COMPOSITE: - case ONE_TO_MANY: - case MANY_TO_MANY: - case MANY_TO_ANY: { - throw new UnsupportedOperationException( "Collection element nature not supported yet: " + collectionElement.getCollectionElementNature() ); - } - default: { - throw new AssertionFailure( "Unknown collection element nature : " + collectionElement.getCollectionElementNature() ); - } - } - } - - private void resolveBasicCollectionElement(BasicCollectionElement basicCollectionElement) { - Type resolvedHibernateType = determineSingularTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() ); - if ( resolvedHibernateType != null ) { - pushHibernateTypeInformationDownIfNeeded( - basicCollectionElement.getHibernateTypeDescriptor(), - basicCollectionElement.getElementValue(), - resolvedHibernateType - ); - } - } - - private Type getHeuristicType(String typeName, Properties typeParameters) { - if ( typeName != null ) { - try { - return metadata.getTypeResolver().heuristicType( typeName, typeParameters ); - } - catch (Exception ignore) { - } - } - - return null; - } - - private void pushHibernateTypeInformationDownIfNeeded(SingularAttributeBinding attributeBinding, Type resolvedHibernateType) { - - final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); - final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); - final Value value = attributeBinding.getValue(); - if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { - singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); - } - - // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - this.pushHibernateTypeInformationDownIfNeeded( - hibernateTypeDescriptor, value, resolvedHibernateType - ); - } - - private void pushHibernateTypeInformationDownIfNeeded( - HibernateTypeDescriptor hibernateTypeDescriptor, - Value value, - Type resolvedHibernateType) { - if ( resolvedHibernateType == null ) { - return; - } - if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) { - hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType ); - } - - // java type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - if ( hibernateTypeDescriptor.getJavaTypeName() == null ) { - hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() ); - } - - // todo : this can be made a lot smarter, but for now this will suffice. currently we only handle single value bindings - - if ( SimpleValue.class.isInstance( value ) ) { - SimpleValue simpleValue = ( SimpleValue ) value; - if ( simpleValue.getDatatype() == null ) { - simpleValue.setDatatype( - new Datatype( - resolvedHibernateType.sqlTypes( metadata )[0], - resolvedHibernateType.getName(), - resolvedHibernateType.getReturnedClass() - ) - ); - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java deleted file mode 100644 index 1b69367031..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; -import java.util.Properties; - -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.cfg.ObjectNameNormalizer; -import org.hibernate.engine.config.spi.ConfigurationService; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; - -/** - * @author Gail Badner - */ -public class IdentifierGeneratorResolver { - - private final MetadataImplementor metadata; - - IdentifierGeneratorResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - // IdentifierGeneratorResolver.resolve() must execute after AttributeTypeResolver.resolve() - // to ensure that identifier type is resolved. - @SuppressWarnings( {"unchecked"} ) - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - if ( entityBinding.isRoot() ) { - Properties properties = new Properties( ); - properties.putAll( - metadata.getServiceRegistry() - .getService( ConfigurationService.class ) - .getSettings() - ); - //TODO: where should these be added??? - if ( ! properties.contains( AvailableSettings.PREFER_POOLED_VALUES_LO ) ) { - properties.put( AvailableSettings.PREFER_POOLED_VALUES_LO, "false" ); - } - if ( ! properties.contains( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER ) ) { - properties.put( - PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, - new ObjectNameNormalizerImpl( metadata ) - ); - } - entityBinding.getHierarchyDetails().getEntityIdentifier().createIdentifierGenerator( - metadata.getIdentifierGeneratorFactory(), - properties - ); - } - } - } - - private static class ObjectNameNormalizerImpl extends ObjectNameNormalizer implements Serializable { - private final boolean useQuotedIdentifiersGlobally; - private final NamingStrategy namingStrategy; - - private ObjectNameNormalizerImpl(MetadataImplementor metadata ) { - this.useQuotedIdentifiersGlobally = metadata.isGloballyQuotedIdentifiers(); - this.namingStrategy = metadata.getNamingStrategy(); - } - - @Override - protected boolean isUseQuotedIdentifiersGlobally() { - return useQuotedIdentifiersGlobally; - } - - @Override - protected NamingStrategy getNamingStrategy() { - return namingStrategy; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java deleted file mode 100644 index 44f9874fcd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.internal; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.ValidationEvent; -import javax.xml.bind.ValidationEventHandler; -import javax.xml.bind.ValidationEventLocator; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.XsdException; - -import org.jboss.logging.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * Helper class for unmarshalling xml configuration using StAX and JAXB. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class JaxbHelper { - private static final Logger log = Logger.getLogger( JaxbHelper.class ); - - public static final String ASSUMED_ORM_XSD_VERSION = "2.0"; - - private final MetadataSources metadataSources; - - public JaxbHelper(MetadataSources metadataSources) { - this.metadataSources = metadataSources; - } - - public JaxbRoot unmarshal(InputStream stream, Origin origin) { - try { - XMLEventReader staxReader = staxFactory().createXMLEventReader( stream ); - try { - return unmarshal( staxReader, origin ); - } - finally { - try { - staxReader.close(); - } - catch ( Exception ignore ) { - } - } - } - catch ( XMLStreamException e ) { - throw new MappingException( "Unable to create stax reader", e, origin ); - } - } - - private XMLInputFactory staxFactory; - - private XMLInputFactory staxFactory() { - if ( staxFactory == null ) { - staxFactory = buildStaxFactory(); - } - return staxFactory; - } - - @SuppressWarnings( { "UnnecessaryLocalVariable" }) - private XMLInputFactory buildStaxFactory() { - XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - return staxFactory; - } - - private static final QName ORM_VERSION_ATTRIBUTE_QNAME = new QName( "version" ); - - @SuppressWarnings( { "unchecked" }) - private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) { - XMLEvent event; - try { - event = staxEventReader.peek(); - while ( event != null && !event.isStartElement() ) { - staxEventReader.nextEvent(); - event = staxEventReader.peek(); - } - } - catch ( Exception e ) { - throw new MappingException( "Error accessing stax stream", e, origin ); - } - - if ( event == null ) { - throw new MappingException( "Could not locate root element", origin ); - } - - final Schema validationSchema; - final Class jaxbTarget; - - final String elementName = event.asStartElement().getName().getLocalPart(); - - if ( "entity-mappings".equals( elementName ) ) { - final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME ); - final String explicitVersion = attribute == null ? null : attribute.getValue(); - validationSchema = resolveSupportedOrmXsd( explicitVersion ); - jaxbTarget = JaxbEntityMappings.class; - } - else { - validationSchema = hbmSchema(); - jaxbTarget = JaxbHibernateMapping.class; - } - - final Object target; - final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); - try { - JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( validationSchema ); - unmarshaller.setEventHandler( handler ); - target = unmarshaller.unmarshal( staxEventReader ); - } - - catch ( JAXBException e ) { - StringBuilder builder = new StringBuilder(); - builder.append( "Unable to perform unmarshalling at line number " ); - builder.append( handler.getLineNumber() ); - builder.append( " and column " ); - builder.append( handler.getColumnNumber() ); - builder.append( ". Message: " ); - builder.append( handler.getMessage() ); - throw new MappingException( builder.toString(), e, origin ); - } - - return new JaxbRoot( target, origin ); - } - - @SuppressWarnings( { "unchecked" }) - public JaxbRoot unmarshal(Document document, Origin origin) { - Element rootElement = document.getDocumentElement(); - if ( rootElement == null ) { - throw new MappingException( "No root element found", origin ); - } - - final Schema validationSchema; - final Class jaxbTarget; - - if ( "entity-mappings".equals( rootElement.getNodeName() ) ) { - final String explicitVersion = rootElement.getAttribute( "version" ); - validationSchema = resolveSupportedOrmXsd( explicitVersion ); - jaxbTarget = JaxbEntityMappings.class; - } - else { - validationSchema = hbmSchema(); - jaxbTarget = JaxbHibernateMapping.class; - } - - final Object target; - try { - JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( validationSchema ); - target = unmarshaller.unmarshal( new DOMSource( document ) ); - } - catch ( JAXBException e ) { - throw new MappingException( "Unable to perform unmarshalling", e, origin ); - } - - return new JaxbRoot( target, origin ); - } - - private Schema resolveSupportedOrmXsd(String explicitVersion) { - final String xsdVersionString = explicitVersion == null ? ASSUMED_ORM_XSD_VERSION : explicitVersion; - if ( "1.0".equals( xsdVersionString ) ) { - return orm1Schema(); - } - else if ( "2.0".equals( xsdVersionString ) ) { - return orm2Schema(); - } - throw new IllegalArgumentException( "Unsupported orm.xml XSD version encountered [" + xsdVersionString + "]" ); - } - - public static final String HBM_SCHEMA_NAME = "org/hibernate/hibernate-mapping-4.0.xsd"; - public static final String ORM_1_SCHEMA_NAME = "org/hibernate/jpa/orm_1_0.xsd"; - public static final String ORM_2_SCHEMA_NAME = "org/hibernate/jpa/orm_2_0.xsd"; - - private Schema hbmSchema; - - private Schema hbmSchema() { - if ( hbmSchema == null ) { - hbmSchema = resolveLocalSchema( HBM_SCHEMA_NAME ); - } - return hbmSchema; - } - - private Schema orm1Schema; - - private Schema orm1Schema() { - if ( orm1Schema == null ) { - orm1Schema = resolveLocalSchema( ORM_1_SCHEMA_NAME ); - } - return orm1Schema; - } - - private Schema orm2Schema; - - private Schema orm2Schema() { - if ( orm2Schema == null ) { - orm2Schema = resolveLocalSchema( ORM_2_SCHEMA_NAME ); - } - return orm2Schema; - } - - private Schema resolveLocalSchema(String schemaName) { - return resolveLocalSchema( schemaName, XMLConstants.W3C_XML_SCHEMA_NS_URI ); - } - - private Schema resolveLocalSchema(String schemaName, String schemaLanguage) { - URL url = metadataSources.getServiceRegistry() - .getService( ClassLoaderService.class ) - .locateResource( schemaName ); - if ( url == null ) { - throw new XsdException( "Unable to locate schema [" + schemaName + "] via classpath", schemaName ); - } - try { - InputStream schemaStream = url.openStream(); - try { - StreamSource source = new StreamSource( url.openStream() ); - SchemaFactory schemaFactory = SchemaFactory.newInstance( schemaLanguage ); - return schemaFactory.newSchema( source ); - } - catch ( SAXException e ) { - throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName ); - } - catch ( IOException e ) { - throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName ); - } - finally { - try { - schemaStream.close(); - } - catch ( IOException e ) { - log.debugf( "Problem closing schema stream [%s]", e.toString() ); - } - } - } - catch ( IOException e ) { - throw new XsdException( "Stream error handling schema url [" + url.toExternalForm() + "]", schemaName ); - } - } - - static class ContextProvidingValidationEventHandler implements ValidationEventHandler { - private int lineNumber; - private int columnNumber; - private String message; - - @Override - public boolean handleEvent(ValidationEvent validationEvent) { - ValidationEventLocator locator = validationEvent.getLocator(); - lineNumber = locator.getLineNumber(); - columnNumber = locator.getColumnNumber(); - message = validationEvent.getMessage(); - return false; - } - - public int getLineNumber() { - return lineNumber; - } - - public int getColumnNumber() { - return columnNumber; - } - - public String getMessage() { - return message; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java deleted file mode 100644 index 8de41ed465..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.DuplicateMappingException; -import org.hibernate.MappingException; -import org.hibernate.SessionFactory; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cache.spi.RegionFactory; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.NamedQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.MetadataSourceProcessingOrder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.domain.BasicType; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.relational.Database; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.annotations.AnnotationMetadataSourceProcessorImpl; -import org.hibernate.metamodel.source.hbm.HbmMetadataSourceProcessorImpl; -import org.hibernate.persister.spi.PersisterClassResolver; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.TypeResolver; - -import org.jboss.logging.Logger; - -/** - * Container for configuration data collected during binding the metamodel. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - * @author Gail Badner - */ -public class MetadataImpl implements MetadataImplementor, Serializable { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - MetadataImpl.class.getName() - ); - - private final ServiceRegistry serviceRegistry; - private final Options options; - - private final ValueHolder classLoaderService; - private final ValueHolder persisterClassResolverService; - - private TypeResolver typeResolver = new TypeResolver(); - - private final MutableIdentifierGeneratorFactory identifierGeneratorFactory; - - private final Database database; - - private final MappingDefaults mappingDefaults; - - /** - * Maps the fully qualified class name of an entity to its entity binding - */ - private Map entityBindingMap = new HashMap(); - - private Map collectionBindingMap = new HashMap(); - private Map fetchProfiles = new HashMap(); - private Map imports = new HashMap(); - private Map typeDefs = new HashMap(); - private Map idGenerators = new HashMap(); - private Map namedQueryDefs = new HashMap(); - private Map namedNativeQueryDefs = new HashMap(); - private Map resultSetMappings = new HashMap(); - private Map filterDefs = new HashMap(); - - private boolean globallyQuotedIdentifiers = false; - - public MetadataImpl(MetadataSources metadataSources, Options options) { - this.serviceRegistry = options.getServiceRegistry(); - this.options = options; - this.identifierGeneratorFactory = serviceRegistry.getService( MutableIdentifierGeneratorFactory.class ); - //new DefaultIdentifierGeneratorFactory( dialect ); - this.database = new Database( options ); - - this.mappingDefaults = new MappingDefaultsImpl(); - - final MetadataSourceProcessor[] metadataSourceProcessors; - if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) { - metadataSourceProcessors = new MetadataSourceProcessor[] { - new HbmMetadataSourceProcessorImpl( this ), - new AnnotationMetadataSourceProcessorImpl( this ) - }; - } - else { - metadataSourceProcessors = new MetadataSourceProcessor[] { - new AnnotationMetadataSourceProcessorImpl( this ), - new HbmMetadataSourceProcessorImpl( this ) - }; - } - - this.classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return serviceRegistry.getService( ClassLoaderService.class ); - } - } - ); - this.persisterClassResolverService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public PersisterClassResolver initialize() { - return serviceRegistry.getService( PersisterClassResolver.class ); - } - } - ); - - - final ArrayList processedEntityNames = new ArrayList(); - - prepare( metadataSourceProcessors, metadataSources ); - bindIndependentMetadata( metadataSourceProcessors, metadataSources ); - bindTypeDependentMetadata( metadataSourceProcessors, metadataSources ); - bindMappingMetadata( metadataSourceProcessors, metadataSources, processedEntityNames ); - bindMappingDependentMetadata( metadataSourceProcessors, metadataSources ); - - // todo : remove this by coordinated ordering of entity processing - new AssociationResolver( this ).resolve(); - new HibernateTypeResolver( this ).resolve(); - // IdentifierGeneratorResolver.resolve() must execute after AttributeTypeResolver.resolve() - new IdentifierGeneratorResolver( this ).resolve(); - } - - private void prepare(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.prepare( metadataSources ); - } - } - - private void bindIndependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processIndependentMetadata( metadataSources ); - } - } - - private void bindTypeDependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processTypeDependentMetadata( metadataSources ); - } - } - - private void bindMappingMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources, List processedEntityNames) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processMappingMetadata( metadataSources, processedEntityNames ); - } - } - - private void bindMappingDependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processMappingDependentMetadata( metadataSources ); - } - } - - @Override - public void addFetchProfile(FetchProfile profile) { - if ( profile == null || profile.getName() == null ) { - throw new IllegalArgumentException( "Fetch profile object or name is null: " + profile ); - } - fetchProfiles.put( profile.getName(), profile ); - } - - @Override - public void addFilterDefinition(FilterDefinition def) { - if ( def == null || def.getFilterName() == null ) { - throw new IllegalArgumentException( "Filter definition object or name is null: " + def ); - } - filterDefs.put( def.getFilterName(), def ); - } - - public Iterable getFilterDefinitions() { - return filterDefs.values(); - } - - @Override - public void addIdGenerator(IdGenerator generator) { - if ( generator == null || generator.getName() == null ) { - throw new IllegalArgumentException( "ID generator object or name is null." ); - } - idGenerators.put( generator.getName(), generator ); - } - - @Override - public IdGenerator getIdGenerator(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid generator name" ); - } - return idGenerators.get( name ); - } - @Override - public void registerIdentifierGenerator(String name, String generatorClassName) { - identifierGeneratorFactory.register( name, classLoaderService().classForName( generatorClassName ) ); - } - - @Override - public void addNamedNativeQuery(NamedSQLQueryDefinition def) { - if ( def == null || def.getName() == null ) { - throw new IllegalArgumentException( "Named native query definition object or name is null: " + def.getQueryString() ); - } - namedNativeQueryDefs.put( def.getName(), def ); - } - - public NamedSQLQueryDefinition getNamedNativeQuery(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid native query name" ); - } - return namedNativeQueryDefs.get( name ); - } - - @Override - public Iterable getNamedNativeQueryDefinitions() { - return namedNativeQueryDefs.values(); - } - - @Override - public void addNamedQuery(NamedQueryDefinition def) { - if ( def == null ) { - throw new IllegalArgumentException( "Named query definition is null" ); - } - else if ( def.getName() == null ) { - throw new IllegalArgumentException( "Named query definition name is null: " + def.getQueryString() ); - } - namedQueryDefs.put( def.getName(), def ); - } - - public NamedQueryDefinition getNamedQuery(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid query name" ); - } - return namedQueryDefs.get( name ); - } - - @Override - public Iterable getNamedQueryDefinitions() { - return namedQueryDefs.values(); - } - - @Override - public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition) { - if ( resultSetMappingDefinition == null || resultSetMappingDefinition.getName() == null ) { - throw new IllegalArgumentException( "Result-set mapping object or name is null: " + resultSetMappingDefinition ); - } - resultSetMappings.put( resultSetMappingDefinition.getName(), resultSetMappingDefinition ); - } - - @Override - public Iterable getResultSetMappingDefinitions() { - return resultSetMappings.values(); - } - - @Override - public void addTypeDefinition(TypeDef typeDef) { - if ( typeDef == null ) { - throw new IllegalArgumentException( "Type definition is null" ); - } - else if ( typeDef.getName() == null ) { - throw new IllegalArgumentException( "Type definition name is null: " + typeDef.getTypeClass() ); - } - final TypeDef previous = typeDefs.put( typeDef.getName(), typeDef ); - if ( previous != null ) { - LOG.debugf( "Duplicate typedef name [%s] now -> %s", typeDef.getName(), typeDef.getTypeClass() ); - } - } - - @Override - public Iterable getTypeDefinitions() { - return typeDefs.values(); - } - - @Override - public TypeDef getTypeDefinition(String name) { - return typeDefs.get( name ); - } - - private ClassLoaderService classLoaderService() { - return classLoaderService.getValue(); - } - - private PersisterClassResolver persisterClassResolverService() { - return persisterClassResolverService.getValue(); - } - - @Override - public Options getOptions() { - return options; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - @SuppressWarnings( {"unchecked"}) - public Class locateClassByName(String name) { - return classLoaderService().classForName( name ); - } - - @Override - public Type makeJavaType(String className) { - // todo : have this perform some analysis of the incoming type name to determine appropriate return - return new BasicType( className, makeClassReference( className ) ); - } - - @Override - public ValueHolder> makeClassReference(final String className) { - return new ValueHolder>( - new ValueHolder.DeferredInitializer>() { - @Override - public Class initialize() { - return classLoaderService.getValue().classForName( className ); - } - } - ); - } - - @Override - public String qualifyClassName(String name) { - return name; - } - - @Override - public Database getDatabase() { - return database; - } - - public EntityBinding getEntityBinding(String entityName) { - return entityBindingMap.get( entityName ); - } - - @Override - public EntityBinding getRootEntityBinding(String entityName) { - EntityBinding binding = entityBindingMap.get( entityName ); - if ( binding == null ) { - throw new IllegalStateException( "Unknown entity binding: " + entityName ); - } - - do { - if ( binding.isRoot() ) { - return binding; - } - binding = binding.getSuperEntityBinding(); - } while ( binding != null ); - - throw new AssertionFailure( "Entity binding has no root: " + entityName ); - } - - public Iterable getEntityBindings() { - return entityBindingMap.values(); - } - - public void addEntity(EntityBinding entityBinding) { - final String entityName = entityBinding.getEntity().getName(); - if ( entityBindingMap.containsKey( entityName ) ) { - throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName ); - } - entityBindingMap.put( entityName, entityBinding ); - } - - public PluralAttributeBinding getCollection(String collectionRole) { - return collectionBindingMap.get( collectionRole ); - } - - @Override - public Iterable getCollectionBindings() { - return collectionBindingMap.values(); - } - - public void addCollection(PluralAttributeBinding pluralAttributeBinding) { - final String owningEntityName = pluralAttributeBinding.getContainer().getPathBase(); - final String attributeName = pluralAttributeBinding.getAttribute().getName(); - final String collectionRole = owningEntityName + '.' + attributeName; - if ( collectionBindingMap.containsKey( collectionRole ) ) { - throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, collectionRole ); - } - collectionBindingMap.put( collectionRole, pluralAttributeBinding ); - } - - public void addImport(String importName, String entityName) { - if ( importName == null || entityName == null ) { - throw new IllegalArgumentException( "Import name or entity name is null" ); - } - LOG.tracev( "Import: {0} -> {1}", importName, entityName ); - String old = imports.put( importName, entityName ); - if ( old != null ) { - LOG.debug( "import name [" + importName + "] overrode previous [{" + old + "}]" ); - } - } - - @Override - public Iterable> getImports() { - return imports.entrySet(); - } - - @Override - public Iterable getFetchProfiles() { - return fetchProfiles.values(); - } - - public TypeResolver getTypeResolver() { - return typeResolver; - } - - @Override - public SessionFactoryBuilder getSessionFactoryBuilder() { - return new SessionFactoryBuilderImpl( this ); - } - - @Override - public SessionFactory buildSessionFactory() { - return getSessionFactoryBuilder().build(); - } - - @Override - public NamingStrategy getNamingStrategy() { - return options.getNamingStrategy(); - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return globallyQuotedIdentifiers || getOptions().isGloballyQuotedIdentifiers(); - } - - public void setGloballyQuotedIdentifiers(boolean globallyQuotedIdentifiers){ - this.globallyQuotedIdentifiers = globallyQuotedIdentifiers; - } - - @Override - public MappingDefaults getMappingDefaults() { - return mappingDefaults; - } - - private final MetaAttributeContext globalMetaAttributeContext = new MetaAttributeContext(); - - @Override - public MetaAttributeContext getGlobalMetaAttributeContext() { - return globalMetaAttributeContext; - } - - @Override - public MetadataImplementor getMetadataImplementor() { - return this; - } - - private static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id"; - private static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class"; - private static final String DEFAULT_CASCADE = "none"; - private static final String DEFAULT_PROPERTY_ACCESS = "property"; - - @Override - public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return identifierGeneratorFactory; - } - - @Override - public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - return entityBinding - .getHierarchyDetails() - .getEntityIdentifier() - .getValueBinding() - .getHibernateTypeDescriptor() - .getResolvedTypeMapping(); - } - - @Override - public String getIdentifierPropertyName(String entityName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - return idBinding == null ? null : idBinding.getAttribute().getName(); - } - - @Override - public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - // TODO: should this call EntityBinding.getReferencedAttributeBindingString), which does not exist yet? - AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( propertyName ); - if ( attributeBinding == null ) { - throw new MappingException( "unknown property: " + entityName + '.' + propertyName ); - } - return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); - } - - private class MappingDefaultsImpl implements MappingDefaults { - - @Override - public String getPackageName() { - return null; - } - - @Override - public String getSchemaName() { - return options.getDefaultSchemaName(); - } - - @Override - public String getCatalogName() { - return options.getDefaultCatalogName(); - } - - @Override - public String getIdColumnName() { - return DEFAULT_IDENTIFIER_COLUMN_NAME; - } - - @Override - public String getDiscriminatorColumnName() { - return DEFAULT_DISCRIMINATOR_COLUMN_NAME; - } - - @Override - public String getCascadeStyle() { - return DEFAULT_CASCADE; - } - - @Override - public String getPropertyAccessorName() { - return DEFAULT_PROPERTY_ACCESS; - } - - @Override - public boolean areAssociationsLazy() { - return true; - } - - private final ValueHolder regionFactorySpecifiedDefaultAccessType = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public AccessType initialize() { - final RegionFactory regionFactory = getServiceRegistry().getService( RegionFactory.class ); - return regionFactory.getDefaultAccessType(); - } - } - ); - - @Override - public AccessType getCacheAccessType() { - return options.getDefaultAccessType() != null - ? options.getDefaultAccessType() - : regionFactorySpecifiedDefaultAccessType.getValue(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java deleted file mode 100644 index 85a700a8af..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; - -import org.hibernate.EmptyInterceptor; -import org.hibernate.Interceptor; -import org.hibernate.ObjectNotFoundException; -import org.hibernate.SessionFactory; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.internal.SessionFactoryImpl; -import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.proxy.EntityNotFoundDelegate; - -/** - * @author Gail Badner - */ -public class SessionFactoryBuilderImpl implements SessionFactoryBuilder { - SessionFactoryOptionsImpl options; - - private final MetadataImplementor metadata; - - /* package-protected */ - SessionFactoryBuilderImpl(MetadataImplementor metadata) { - this.metadata = metadata; - options = new SessionFactoryOptionsImpl( metadata.getOptions().getServiceRegistry() ); - } - - @Override - public SessionFactoryBuilder with(Interceptor interceptor) { - this.options.interceptor = interceptor; - return this; - } - - @Override - public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate) { - this.options.entityNotFoundDelegate = entityNotFoundDelegate; - return this; - } - - @Override - public SessionFactory build() { - return new SessionFactoryImpl(metadata, options, null ); - } - - private static class SessionFactoryOptionsImpl implements SessionFactory.SessionFactoryOptions { - private final StandardServiceRegistry serviceRegistry; - private Interceptor interceptor = EmptyInterceptor.INSTANCE; - - public SessionFactoryOptionsImpl(StandardServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; - } - - // TODO: should there be a DefaultEntityNotFoundDelegate.INSTANCE? - private EntityNotFoundDelegate entityNotFoundDelegate = new EntityNotFoundDelegate() { - public void handleEntityNotFound(String entityName, Serializable id) { - throw new ObjectNotFoundException( id, entityName ); - } - }; - - @Override - public StandardServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - public Interceptor getInterceptor() { - return interceptor; - } - - @Override - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - return entityNotFoundDelegate; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java new file mode 100644 index 0000000000..253ee41a96 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.List; + +import org.jboss.jandex.IndexView; + +import org.hibernate.jaxb.spi.JaxbRoot; + +/** + * Contract for integrations that wish to provide additional mappings (in the form of {@link JaxbRoot}. This hook + * is performed after all other mappings, annotations, etc have completed processing. + * + * @author Steve Ebersole + */ +public interface AdditionalJaxbRootProducer { + /** + * Produce and return the list of additional mappings to be processed. + * + * @param metadata The metadata (for access to binding information). + * @param jandexIndex The Jandex annotation index + * + * @return List of additional mappings + */ + public List produceRoots(MetadataImplementor metadata, IndexView jandexIndex); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java new file mode 100644 index 0000000000..c243ba7d7e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.jboss.jandex.IndexView; + +/** + * Contract for contributing MetadataSources. This hook occurs just after all processing of + * {@link org.hibernate.metamodel.MetadataSources} has completed (and just before {@link AdditionalJaxbRootProducer}). + * + * @author Steve Ebersole + */ +public interface MetadataContributor { + /** + * Perform the contributions. + * + * @param metadata The metadata + * @param jandexIndex The Jandex index + */ + public void contribute(MetadataImplementor metadata, IndexView jandexIndex); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java new file mode 100644 index 0000000000..7296149152 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.engine.spi.Mapping; +import org.hibernate.engine.spi.NamedQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.source.BindingContext; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.type.TypeResolver; + +/** + * @author Steve Ebersole + */ +public interface MetadataImplementor extends Metadata, BindingContext, Mapping { + + Database getDatabase(); + + TypeResolver getTypeResolver(); + + ObjectNameNormalizer getObjectNameNormalizer(); + + void addImport(String entityName, String entityName1); + + void addEntity(EntityBinding entityBinding); + + void addSecondaryTable(SecondaryTable secondaryTable); + + void addCollection(PluralAttributeBinding collectionBinding); + + void addFetchProfile(FetchProfile profile); + + void addTypeDefinition(TypeDefinition typeDefinition); + + void addFilterDefinition(FilterDefinition filterDefinition); + + void addIdGenerator(IdentifierGeneratorDefinition generator); + + void registerIdentifierGenerator(String name, String clazz); + + void addNamedNativeQuery(NamedSQLQueryDefinition def); + + void addNamedEntityGraph(NamedEntityGraphDefinition def); + + void addNamedQuery(NamedQueryDefinition def); + + void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition); + + void setGloballyQuotedIdentifiers(boolean b); + + MetaAttributeContext getGlobalMetaAttributeContext(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java index 985d28aac0..d3d837031a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java @@ -21,11 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi; -import java.util.List; - -import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.FilterDefinitionSource; +import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource; +import org.hibernate.metamodel.spi.source.TypeDescriptorSource; /** * Handles the processing of metadata sources in a dependency-ordered manner. @@ -34,48 +35,36 @@ import org.hibernate.metamodel.MetadataSources; */ public interface MetadataSourceProcessor { /** - * Prepare for processing the given sources. + * Retrieve the sources pertaining to type descriptors. * - * @param sources The metadata sources. + * @return The type descriptor sources. */ - public void prepare(MetadataSources sources); + Iterable extractTypeDefinitionSources(); /** - * Process the independent metadata. These have no dependency on other types of metadata being processed. + * Retrieve the sources pertaining to filter defs. * - * @param sources The metadata sources. - * - * @see #prepare + * @return The filter def sources. */ - public void processIndependentMetadata(MetadataSources sources); + Iterable extractFilterDefinitionSources(); /** - * Process the parts of the metadata that depend on type information (type definitions) having been processed - * and available. + * Retrieve the sources of "global" identifier generator specifications. * - * @param sources The metadata sources. - * - * @see #processIndependentMetadata + * @return The identifier generator sources. */ - public void processTypeDependentMetadata(MetadataSources sources); + Iterable extractGlobalIdentifierGeneratorSources(); /** - * Process the mapping (entities, et al) metadata. + * Retrieve the entity hierarchies. * - * @param sources The metadata sources. - * @param processedEntityNames Collection of any already processed entity names. - * - * @see #processTypeDependentMetadata + * @return The entity hierarchies */ - public void processMappingMetadata(MetadataSources sources, List processedEntityNames); + Iterable extractEntityHierarchies(); /** * Process the parts of the metadata that depend on mapping (entities, et al) information having been * processed and available. - * - * @param sources The metadata sources. - * - * @see #processMappingMetadata */ - public void processMappingDependentMetadata(MetadataSources sources); + void processMappingDependentMetadata(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java new file mode 100644 index 0000000000..5a08cd7692 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + + +import org.jboss.jandex.IndexView; + +import org.hibernate.metamodel.MetadataSources; + +/** + * Contract for contributing sources to MetadataSources. + * + * @author Steve Ebersole + */ +public interface MetadataSourcesContributor { + /** + * Perform the process of contributing to MetadataSources. + * + * @param metadataSources + * @param jandexIndex The Jandex index + */ + public void contribute(MetadataSources metadataSources, IndexView jandexIndex); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java index 4a04173faa..004caef5e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java @@ -29,9 +29,6 @@ import org.hibernate.service.ServiceRegistry; * Contract for contributing types. * * @author Steve Ebersole - * - * NOTE: Cherry-pick of HHH-7998 from metamodel. For merging simplicity, just - * keep it in the o.h.metamodel.spi package. */ public interface TypeContributor { /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java similarity index 73% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java index 4ae33f270a..50b1d8e45e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java @@ -21,14 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.source.MetaAttributeContext; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * Basic support for {@link AttributeBinding} implementors @@ -42,17 +43,33 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); private final Set entityReferencingAttributeBindings = new HashSet(); - private boolean includedInOptimisticLocking; + private final String propertyAccessorName; + private final boolean includedInOptimisticLocking; - private boolean isLazy; - private String propertyAccessorName; private boolean isAlternateUniqueKey; - private MetaAttributeContext metaAttributeContext; + private final MetaAttributeContext metaAttributeContext; + private final ValueHolder roleHolder; - protected AbstractAttributeBinding(AttributeBindingContainer container, Attribute attribute) { + protected AbstractAttributeBinding( + AttributeBindingContainer container, + Attribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { this.container = container; this.attribute = attribute; + this.propertyAccessorName = propertyAccessorName; + this.includedInOptimisticLocking = includedInOptimisticLocking; + this.metaAttributeContext = metaAttributeContext; + this.roleHolder = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public String initialize() { + return getContainer().getPathBase() + '.' + getAttribute().getName(); + } + } + ); } @Override @@ -65,11 +82,20 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { return attribute; } + protected String getRole() { + return roleHolder.getValue(); + } + @Override public HibernateTypeDescriptor getHibernateTypeDescriptor() { return hibernateTypeDescriptor; } + @Override + public boolean isBackRef() { + return false; + } + @Override public boolean isBasicPropertyAccessor() { return propertyAccessorName == null || "property".equals( propertyAccessorName ); @@ -80,30 +106,19 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { return propertyAccessorName; } - public void setPropertyAccessorName(String propertyAccessorName) { - this.propertyAccessorName = propertyAccessorName; - } - @Override public boolean isIncludedInOptimisticLocking() { return includedInOptimisticLocking; } - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - @Override public MetaAttributeContext getMetaAttributeContext() { return metaAttributeContext; } - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - @Override public boolean isAlternateUniqueKey() { + // todo : is this the same as "part of natural id"? return isAlternateUniqueKey; } @@ -111,15 +126,6 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { this.isAlternateUniqueKey = alternateUniqueKey; } - @Override - public boolean isLazy() { - return isLazy; - } - - public void setLazy(boolean isLazy) { - this.isLazy = isLazy; - } - public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding referencingAttributeBinding) { entityReferencingAttributeBindings.add( referencingAttributeBinding ); } @@ -135,4 +141,13 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { // can a unique attribute be used as a target? if so, does it need to be non-null? } } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "AbstractAttributeBinding" ); + sb.append( "{attribute=" ).append( attribute.getName() ); + sb.append( '}' ); + return sb.toString(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java new file mode 100644 index 0000000000..68a3dbf59e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java @@ -0,0 +1,323 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; +import java.util.Map; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * @author Gail Badner + */ +public abstract class AbstractAttributeBindingContainer implements AttributeBindingContainer { + + protected abstract Map attributeBindingMapInternal(); + + @Override + public AttributeBinding locateAttributeBinding(String name) { + return attributeBindingMapInternal().get( name ); + } + + @Override + public SingularAttributeBinding locateAttributeBinding(TableSpecification table, List values) { + for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) { + if ( !attributeBinding.getAttribute().isSingular() ) { + continue; + } + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + if ( hasEqualValues( table, values, singularAttributeBinding.getRelationalValueBindings() ) ) { + return singularAttributeBinding; + } + } + return null; + } + + private static boolean hasEqualValues( + TableSpecification table, + List values, + List relationalValueBindings) { + if ( values.size() != relationalValueBindings.size() ) { + return false; + } + for ( int i = 0 ; i < values.size() ; i++ ) { + final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( i ); + if ( !table.equals( relationalValueBinding.getTable() ) || + !values.get( i ).equals( relationalValueBinding.getValue() ) ) { + return false; + } + } + return true; + } + + @Override + public Class getClassReference() { + return getAttributeContainer().getClassReference(); + } + + + @Override + public int attributeBindingSpan() { + return attributeBindingMapInternal().size(); + } + + @Override + public Iterable attributeBindings() { + return attributeBindingMapInternal().values(); + } + + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + for ( AttributeBinding subAttributeBinding : attributeBindings() ) { + if ( AbstractSingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + ( (AbstractSingularAttributeBinding) subAttributeBinding ).collectRelationalValueBindings( relationalValueBindingContainer ); + } + } + } + + @Override + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { + final BasicAttributeBinding binding = new BasicAttributeBinding( + this, + attribute, + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + generation + ); + registerAttributeBinding( binding ); + return binding; + } + + protected void registerAttributeBinding(AttributeBinding attributeBinding) { + // todo : hook this into the EntityBinding notion of "entity referencing attribute bindings" + attributeBindingMapInternal().put( attributeBinding.getAttribute().getName(), attributeBinding ); + } + + @Override + public CompositeAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext) { + final CompositeAttributeBinding binding = + CompositeAttributeBinding.createAggregatedCompositeAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + parentReferenceAttribute + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + final OneToOneAttributeBinding binding = new OneToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding, + isConstrained + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isNotFoundAnException, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isNotFoundAnException, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + Helper.checkPluralAttributeNature( attribute, PluralAttribute.Nature.BAG ); + final BagBinding binding = new BagBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + Helper.checkPluralAttributeNature( attribute, PluralAttribute.Nature.LIST ); + final ListBinding binding = new ListBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + Helper.checkPluralAttributeNature( attribute, PluralAttribute.Nature.ARRAY ); + final ArrayBinding binding = new ArrayBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature elementNature, + PluralAttributeIndexBinding.Nature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + Helper.checkPluralAttributeNature( attribute, PluralAttribute.Nature.MAP ); + final MapBinding binding = new MapBinding( + this, + attribute, + elementNature, + indexNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + Helper.checkPluralAttributeNature( attribute, PluralAttribute.Nature.SET ); + final SetBinding binding = new SetBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + registerAttributeBinding( binding ); + return binding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java new file mode 100644 index 0000000000..745775f81e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java @@ -0,0 +1,320 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * A container for attribute bindings that make up composite grouping + * + * @author Gail Badner + */ +public abstract class AbstractCompositeAttributeBindingContainer + extends AbstractAttributeBindingContainer + implements CompositeAttributeBindingContainer { + private final EntityBinding entityBinding; + private final AttributeContainer attributeContainer; + private final TableSpecification primaryTable; + private final String path; + private final MetaAttributeContext metaAttributeContext; + private final SingularAttribute parentReference; + + protected AbstractCompositeAttributeBindingContainer( + EntityBinding entityBinding, + AttributeContainer attributeContainer, + TableSpecification primaryTable, + String path, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference) { + this.entityBinding = entityBinding; + this.attributeContainer = attributeContainer; + this.primaryTable = primaryTable; + this.path = path; + this.metaAttributeContext = metaAttributeContext; + this.parentReference = parentReference; + } + + public SingularAttribute getParentReference() { + return parentReference; + } + + @Override + public String getPathBase() { + return path; + } + + @Override + public AttributeContainer getAttributeContainer() { + return attributeContainer; + } + + @Override + public EntityBinding seekEntityBinding() { + return entityBinding; + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + @Override + public TableSpecification getPrimaryTable() { + return primaryTable; + } + + @Override + public Class getCustomTuplizerClass() { + return null; + } + + protected abstract boolean isModifiable(); + + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + final RelationalValueBindingContainer bindingContainer = new RelationalValueBindingContainer(); + collectRelationalValueBindings( bindingContainer ); + return bindingContainer; + } + + @Override + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + generation + ); + } + + @Override + public CompositeAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeAggregatedCompositeAttributeBinding( + attribute, + parentReferenceAttribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext + ); + } + + @Override + public OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeOneToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding, + isConstrained + ); + } + + @Override + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isNotFoundAnException, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isNotFoundAnException, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding + ); + } + + @Override + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeBagAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } + + @Override + public ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeListAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base + ); + } + + @Override + public ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeArrayAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base + ); + } + + @Override + public MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature elementNature, + PluralAttributeIndexBinding.Nature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeMapAttributeBinding( + attribute, + elementNature, + indexNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } + + @Override + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeSetAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java new file mode 100644 index 0000000000..0cca131bdf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.FetchMode; +import org.hibernate.engine.spi.CascadeStyle; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeAssociationElementBinding + extends AbstractPluralAttributeElementBinding + implements PluralAttributeAssociationElementBinding { + + private CascadeStyle cascadeStyle; + + AbstractPluralAttributeAssociationElementBinding(AbstractPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding ); + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } + + @Override + public FetchMode getFetchMode() { + return getPluralAttributeBinding().getFetchMode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java new file mode 100644 index 0000000000..54d3216652 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java @@ -0,0 +1,309 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.persister.collection.CollectionPersister; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBinding implements PluralAttributeBinding { + private final PluralAttributeKeyBinding pluralAttributeKeyBinding; + private final AbstractPluralAttributeElementBinding pluralAttributeElementBinding; + + private FetchTiming fetchTiming; + private FetchStyle fetchStyle; + + private int batchSize = -1; + + private Caching caching; + + private boolean mutable = true; + + private Class explicitPersisterClass; + + private String where; + private String orderBy; + private boolean sorted; + private Comparator< ? > comparator; + + private String customLoaderName; + private CustomSQL customSqlInsert; + private CustomSQL customSqlUpdate; + private CustomSQL customSqlDelete; + private CustomSQL customSqlDeleteAll; + + private String referencedPropertyName; + + private List filterConfigurations = new ArrayList(); + + // private final java.util.Set synchronizedTables = new HashSet(); + + protected AbstractPluralAttributeBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + this.pluralAttributeKeyBinding = new PluralAttributeKeyBinding( this, referencedAttributeBinding ); + this.pluralAttributeElementBinding = interpretNature( pluralAttributeElementNature ); + this.referencedPropertyName = referencedAttributeBinding.getAttribute().getName(); + } + + private AbstractPluralAttributeElementBinding interpretNature(PluralAttributeElementBinding.Nature nature) { + switch ( nature ) { + case BASIC: { + return new BasicPluralAttributeElementBinding( this ); + } + case AGGREGATE: { + return new CompositePluralAttributeElementBinding( this ); + } + case ONE_TO_MANY: { + return new OneToManyPluralAttributeElementBinding( this ); + } + case MANY_TO_MANY: { + return new ManyToManyPluralAttributeElementBinding( this ); + } + case MANY_TO_ANY: { + return new ManyToAnyPluralAttributeElementBinding( this ); + } + default: { + throw new AssertionFailure( "Unknown collection element nature : " + nature ); + } + } + } + + @Override + public PluralAttribute getAttribute() { + return (PluralAttribute) super.getAttribute(); + } + + @Override + public boolean isAssociation() { + return pluralAttributeElementBinding.getNature().isAssociation(); + } + + @Override + public boolean isCascadeable() { + return pluralAttributeElementBinding.getNature().isCascadeable(); + } + + @Override + public PluralAttributeKeyBinding getPluralAttributeKeyBinding() { + return pluralAttributeKeyBinding; + } + + @Override + public AbstractPluralAttributeElementBinding getPluralAttributeElementBinding() { + return pluralAttributeElementBinding; + } + + @Override + public FetchTiming getFetchTiming() { + return fetchTiming; + } + + @Override + public void setFetchTiming(FetchTiming fetchTiming) { + this.fetchTiming = fetchTiming; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public void setFetchStyle(FetchStyle fetchStyle) { + this.fetchStyle = fetchStyle; + } + + @Override + public String getCustomLoaderName() { + return customLoaderName; + } + + public void setCustomLoaderName(String customLoaderName) { + this.customLoaderName = customLoaderName; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return customSqlInsert; + } + + public void setCustomSqlInsert(CustomSQL customSqlInsert) { + this.customSqlInsert = customSqlInsert; + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return customSqlUpdate; + } + + public void setCustomSqlUpdate(CustomSQL customSqlUpdate) { + this.customSqlUpdate = customSqlUpdate; + } + + @Override + public CustomSQL getCustomSqlDelete() { + return customSqlDelete; + } + + public void setCustomSqlDelete(CustomSQL customSqlDelete) { + this.customSqlDelete = customSqlDelete; + } + + @Override + public CustomSQL getCustomSqlDeleteAll() { + return customSqlDeleteAll; + } + + public void setCustomSqlDeleteAll(CustomSQL customSqlDeleteAll) { + this.customSqlDeleteAll = customSqlDeleteAll; + } + + @Override + public Class getExplicitPersisterClass() { + return explicitPersisterClass; + } + + public void setExplicitPersisterClass(Class explicitPersisterClass) { + this.explicitPersisterClass = explicitPersisterClass; + } + + public Caching getCaching() { + return caching; + } + + public void setCaching(Caching caching) { + this.caching = caching; + } + + @Override + public String getOrderBy() { + return orderBy; + } + + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + @Override + public String getWhere() { + return where; + } + + public void setWhere(String where) { + this.where = where; + } + + @Override + public boolean isMutable() { + return mutable; + } + + public void setMutable(boolean mutable) { + this.mutable = mutable; + } + @Override + public boolean hasIndex() { + return IndexedPluralAttributeBinding.class.isInstance( this ); + } + + @Override + public int getBatchSize() { + return batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + @Override + public String getReferencedPropertyName() { + return referencedPropertyName; + } + + @Override + public boolean isSorted() { + return sorted; + } + + public void setSorted(boolean sorted) { + this.sorted = sorted; + } + + @Override + public Comparator< ? > getComparator() { + return comparator; + } + + public void setComparator( Comparator< ? > comparator ) { + this.comparator = comparator; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + return filterConfigurations; + } + + @Override + public FetchMode getFetchMode() { + return getFetchStyle() == FetchStyle.JOIN ? FetchMode.JOIN : FetchMode.SELECT; + } + + @Override + public boolean isLazy() { + return fetchTiming != FetchTiming.IMMEDIATE; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java new file mode 100644 index 0000000000..4b0068710e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.FetchMode; +import org.hibernate.metamodel.spi.relational.Column; + +/** + * Basic contract describing the commonality between the various types of collection element mappings. + * + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeElementBinding implements PluralAttributeElementBinding { + private final AbstractPluralAttributeBinding pluralAttributeBinding; + private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + AbstractPluralAttributeElementBinding(AbstractPluralAttributeBinding pluralAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + } + + @Override + public AbstractPluralAttributeBinding getPluralAttributeBinding() { + return pluralAttributeBinding; + } + + @Override + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + protected abstract RelationalValueBindingContainer getRelationalValueContainer(); + + @Override + public List getRelationalValueBindings() { + return getRelationalValueContainer().relationalValueBindings(); + } + + @Override + public boolean isNullable() { + return getRelationalValueContainer().hasNullableRelationalValueBinding(); + } + + @Override + public boolean hasDerivedValue() { + return getRelationalValueContainer().hasDerivedValue(); + } + + @Override + public boolean hasNonNullableValue() { + return getRelationalValueContainer().hasNonNullableRelationalValueBinding(); + } + + @Override + public FetchMode getFetchMode() { + return getPluralAttributeBinding().getFetchMode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java new file mode 100644 index 0000000000..99dc9e3587 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute; +import org.hibernate.metamodel.spi.domain.Type; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralAttributeIndexBinding implements PluralAttributeIndexBinding { + + private final IndexedPluralAttributeBinding pluralAttributeBinding; + private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + public AbstractPluralAttributeIndexBinding( + IndexedPluralAttributeBinding pluralAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + } + + @Override + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + @Override + public IndexedPluralAttributeBinding getIndexedPluralAttributeBinding() { + return pluralAttributeBinding; + } + + @Override + public Type getPluralAttributeIndexType() { + return ( (IndexedPluralAttribute) getIndexedPluralAttributeBinding().getAttribute() ).getIndexType(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java new file mode 100644 index 0000000000..a5485685b7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java @@ -0,0 +1,188 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * @author Gail Badner + */ +public abstract class AbstractSingularAssociationAttributeBinding extends AbstractSingularAttributeBinding + implements SingularAssociationAttributeBinding { + private final EntityBinding referencedEntityBinding; + private final SingularAttributeBinding referencedAttributeBinding; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + private CascadeStyle cascadeStyle; + private FetchTiming fetchTiming; + private FetchStyle fetchStyle; + private boolean isUnWrapProxy; + private final boolean isNotFoundAnException; + + public AbstractSingularAssociationAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + boolean isNotFoundAnException, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + isLazy, + naturalIdMutability, + metaAttributeContext + ); + if ( referencedEntityBinding == null ) { + throw new IllegalArgumentException( "referencedEntityBinding must be non-null." ); + } + if ( referencedAttributeBinding == null ) { + throw new IllegalArgumentException( "referencedAttributeBinding must be non-null." ); + } + this.referencedEntityBinding = referencedEntityBinding; + this.referencedAttributeBinding = referencedAttributeBinding; + this.isNotFoundAnException = isNotFoundAnException; + } + + @Override + public boolean isNotFoundAnException() { + return isNotFoundAnException; + } + + @Override + public boolean isAssociation() { + return true; + } + + @Override + public final String getReferencedEntityName() { + return referencedEntityBinding.getEntity().getName(); + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } + + @Override + public FetchTiming getFetchTiming() { + return fetchTiming; + } + + @Override + public void setFetchTiming(FetchTiming fetchTiming) { + this.fetchTiming = fetchTiming; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public void setFetchStyle(FetchStyle fetchStyle) { + if ( fetchStyle == FetchStyle.SUBSELECT ) { + throw new AssertionFailure( "Subselect fetching not yet supported for singular associations" ); + } + this.fetchStyle = fetchStyle; + } + + @Override + public FetchMode getFetchMode() { + switch ( fetchStyle ){ + case JOIN: + return FetchMode.JOIN; + case SELECT: + return FetchMode.SELECT; + case BATCH: + // we need the subsequent select... + return FetchMode.SELECT; + default: + throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() ); + } + } + + @Override + public final EntityBinding getReferencedEntityBinding() { + return referencedEntityBinding; + } + + @Override + public SingularAttributeBinding getReferencedAttributeBinding() { + return referencedAttributeBinding; + } + + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + this.relationalValueBindingContainer = + new JoinRelationalValueBindingContainer( relationalValueBindings, foreignKey ); + } + + @Override + public TableSpecification getTable() { + return relationalValueBindingContainer.getTable(); + } + + @Override + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + + @Override + public List getValues() { + return getRelationalValueBindingContainer().values(); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return relationalValueBindingContainer; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + relationalValueBindingContainer.addRelationalValueBindings( this.relationalValueBindingContainer ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java new file mode 100644 index 0000000000..0bcd612781 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java @@ -0,0 +1,132 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractSingularAttributeBinding + extends AbstractAttributeBinding + implements SingularAttributeBinding { + + private final boolean isLazy; + private final NaturalIdMutability naturalIdMutability; + + protected AbstractSingularAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext) { + super( container, attribute, propertyAccessorName, includedInOptimisticLocking, metaAttributeContext ); + this.isLazy = isLazy; + this.naturalIdMutability = naturalIdMutability; + } + + protected abstract RelationalValueBindingContainer getRelationalValueBindingContainer(); + + @Override + public List getRelationalValueBindings() { + return getRelationalValueBindingContainer().relationalValueBindings(); + } + + @Override + public List getValues() { + return getRelationalValueBindingContainer().values(); + } + + @Override + public boolean hasDerivedValue() { + return getRelationalValueBindingContainer().hasDerivedValue(); + } + + @Override + public boolean isNullable() { + return !getRelationalValueBindingContainer().hasNonNullableRelationalValueBinding(); + } + + @Override + public boolean isOptional() { + final EntityBinding entityBinding = getContainer().seekEntityBinding(); + final TableSpecification entityPrimaryTable = entityBinding.getPrimaryTable(); + for (RelationalValueBinding relationalValueBinding : getRelationalValueBindings() ) { + final TableSpecification table = relationalValueBinding.getTable(); + if ( table.equals( entityPrimaryTable ) ) { + // primary table is not optional. + return false; + } + final SecondaryTable secondaryTable = entityBinding.getSecondaryTables().get( table.getLogicalName() ); + // a secondaryTable can be null if it is a non-joined, collection/association table + if ( secondaryTable == null || ! secondaryTable.isOptional() ) { + return false; + } + } + return true; + } + + @Override + public boolean isIncludedInInsert() { + return getRelationalValueBindingContainer().hasInsertableRelationalValueBinding(); + } + + @Override + public boolean isIncludedInUpdate() { + return getRelationalValueBindingContainer().hasUpdateableRelationalValueBinding(); + } + + @Override + public SingularAttribute getAttribute() { + return (SingularAttribute) super.getAttribute(); + } + + @Override + public boolean isCascadeable() { + return isAssociation(); + } + + @Override + public boolean isLazy() { + return isLazy; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + public void setAlternateUniqueKey(boolean isAlternateUniqueKey) { + super.setAlternateUniqueKey( isAlternateUniqueKey ); + } + + protected abstract void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java new file mode 100644 index 0000000000..935666cb2c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * @author Brett Meyer + */ +public class ArrayBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + private final int base; + + public ArrayBinding(AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, int base) { + super( container, attribute, pluralAttributeElementNature, + referencedAttributeBinding, propertyAccessorName, + includedInOptimisticLocking, metaAttributeContext ); + pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( + this + ); + this.base = base; + } + + public int base() { + return base; + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java similarity index 76% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java index 5d317cc01e..48bbd8ee2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java @@ -21,12 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import java.util.Set; - -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.source.MetaAttributeContext; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * The basic contract for binding a {@link #getAttribute() attribute} from the domain model to the relational model. @@ -51,8 +49,8 @@ public interface AttributeBinding { /** * Obtain the descriptor for the Hibernate {@link org.hibernate.type.Type} for this binding. *

- * For information about the Java type, query the {@link Attribute} obtained from {@link #getAttribute()} - * instead. + * For information about the Java type, query the {@link org.hibernate.metamodel.spi.domain.Attribute} + * obtained from {@link #getAttribute()} instead. * * @return The type descriptor */ @@ -60,16 +58,16 @@ public interface AttributeBinding { public boolean isAssociation(); + public boolean isCascadeable(); + + public boolean isBackRef(); + public boolean isBasicPropertyAccessor(); public String getPropertyAccessorName(); - public void setPropertyAccessorName(String propertyAccessorName); - public boolean isIncludedInOptimisticLocking(); - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking); - /** * Obtain the meta attributes associated with this binding * @@ -80,10 +78,4 @@ public interface AttributeBinding { public boolean isAlternateUniqueKey(); public boolean isLazy(); - - public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding attributeBinding); - - public Set getEntityReferencingAttributeBindings(); - - public void validate(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java new file mode 100644 index 0000000000..11dc089381 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java @@ -0,0 +1,334 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General License + * for more details. + * + * You should have received a copy of the GNU Lesser General License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.tuple.Tuplizer; + +/** + * Common contract for {@link EntityBinding} and {@link CompositeAttributeBinding} in so far as they are both + * containers for {@link AttributeBinding} descriptors + * + * @author Steve Ebersole + */ +public interface AttributeBindingContainer { + /** + * Obtain the path base of this container. Intended to help uniquely identify each attribute binding. + * + * @return The path base for this container. + */ + String getPathBase(); + + /** + * Obtain the underlying domain attribute container. + * + * @return The attribute container + */ + AttributeContainer getAttributeContainer(); + + /** + * Obtain all attribute bindings + * + * @return All attribute bindings + */ + Iterable attributeBindings(); + + /** + * Return the number of attribute bindings returned by + * {@link #attributeBindings()}. + * + * @return the number of attribute bindings returned by + * {@link #attributeBindings()}. + */ + int attributeBindingSpan(); + + /** + * Return the custom tuplizer class. + * @return + */ + Class getCustomTuplizerClass(); + + /** + * Locate a specific attribute binding, by its local name. + * + * @param name The name of the attribute, local to this container. + * + * @return The attribute binding or {@code null} if none could be found. + */ + AttributeBinding locateAttributeBinding(String name); + + /** + * Locate a specific attribute binding, by its values. + * + * @param table The table containing the values + * @param values The list of values + * + * @return The attribute binding or {@code null} if none could be found. + */ + SingularAttributeBinding locateAttributeBinding(TableSpecification table, List values); + + /** + * Seeks out the entity binding that is the root of this component path. + * + * @return The entity binding + */ + EntityBinding seekEntityBinding(); + + /** + * Obtain the {@link Class} reference for this attribute container. Generally this is used to perform reflection + * on the attributes. + * + * @return The {@link Class} reference + */ + Class getClassReference(); + + /** + * Obtain the meta-attribute context for this container. + * + * @return The meta-attribute context. + */ + MetaAttributeContext getMetaAttributeContext(); + + + /** + * Return the table specification for the relational values of attributes + * directly contained by this attribute binding container. + * + * @return the table specification. + */ + TableSpecification getPrimaryTable(); + + /** + * Factory method for basic attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param relationalValueBindings + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param generation + * + * @return The attribute binding instance. + */ + BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation); + + /** + * Factory method for component attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param parentReferenceAttribute + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + CompositeAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext); + + /** + * Factory method for one-to-one attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param referencedEntityBinding + * @param referencedAttributeBinding + * @param isConstrained + * @return The attribute binding instance. + */ + OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained); + + + /** + * Factory method for many-to-one attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param referencedEntityBinding + * @param referencedAttributeBinding + * + * @return The attribute binding instance. + */ + ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isNotFoundAnException, + SingularAttributeBinding.NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding); + + /** + * Factory method for bag attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext); + + /** + * Factory method for list attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * @param base + * + * @return The attribute binding instance. + */ + ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base); + + /** + * Factory method for array attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * @param base + * + * @return The attribute binding instance. + */ + ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base); + + /** + * Factory method for map attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param elementNature The nature of the collection elements. + * @param indexNature The nature of the collection indexes. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature elementNature, + PluralAttributeIndexBinding.Nature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext); + + /** + * Factory method for set attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java new file mode 100644 index 0000000000..e68f7017cc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; + +/** + * @author Gail Badner + */ +public class BackRefAttributeBinding extends BasicAttributeBinding { + + private final PluralAttributeBinding pluralAttributeBinding; + private final boolean isIndexBackRef; + + BackRefAttributeBinding( + EntityBinding entityBinding, + SingularAttribute attribute, + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + super( + entityBinding, + attribute, + createRelationalValueBindings( pluralAttributeBinding, isIndexBackRef ), + null, + false, + false, + NaturalIdMutability.NOT_NATURAL_ID, + null, + PropertyGeneration.NEVER + ); + this.pluralAttributeBinding = pluralAttributeBinding; + this.isIndexBackRef = isIndexBackRef; + } + + private static List createRelationalValueBindings( + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + List relationalValueBindings; + if ( isIndexBackRef ) { + PluralAttributeIndexBinding indexBinding = + ( (IndexedPluralAttributeBinding) pluralAttributeBinding).getPluralAttributeIndexBinding(); + relationalValueBindings = indexBinding.getRelationalValueBindings(); + + } + else { + relationalValueBindings = new ArrayList( ); + for ( RelationalValueBinding keyRelationalValueBinding : pluralAttributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings() ) { + Column keyColumn = (Column) keyRelationalValueBinding.getValue(); + relationalValueBindings.add( new RelationalValueBinding( keyRelationalValueBinding.getTable(), keyColumn, true, false ) ); + } + } + return relationalValueBindings; + } + + public String getCollectionRole() { + return pluralAttributeBinding.getAttribute().getRole(); + } + + public String getEntityName() { + return pluralAttributeBinding.getContainer().seekEntityBinding().getEntity().getName(); + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean isBackRef() { + return true; + } + + public boolean isIndexBackRef() { + return isIndexBackRef; + } + + @Override + public boolean isIncludedInUpdate() { + //TODO: should be able to rely on super method, but that seems broken currently. + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java index 1b922133cf..e9f78f543b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java @@ -21,31 +21,33 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import org.hibernate.metamodel.relational.Value; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** - * Basic contract describing the commonality between the various types of collection element mappings. + * TODO : javadoc * * @author Steve Ebersole */ -public abstract class AbstractCollectionElement { - private final AbstractPluralAttributeBinding collectionBinding; - - private Value elementValue; - - AbstractCollectionElement(AbstractPluralAttributeBinding collectionBinding) { - this.collectionBinding = collectionBinding; - } - - public abstract CollectionElementNature getCollectionElementNature(); - - public AbstractPluralAttributeBinding getCollectionBinding() { - return collectionBinding; - } - - public Value getElementValue() { - return elementValue; +public class BagBinding extends AbstractPluralAttributeBinding { + protected BagBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java new file mode 100644 index 0000000000..b7033d7741 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * TODO : this really needs an overhaul... mainly, get rid of the KeyValueBinding concept... + * + * @author Steve Ebersole + */ +public class BasicAttributeBinding + extends AbstractSingularAttributeBinding + implements SingularNonAssociationAttributeBinding { + + private final RelationalValueBindingContainer relationalValueBindingContainer; + private final PropertyGeneration generation; + + BasicAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext + ); + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings ); + this.generation = generation; + } + + @Override + public boolean isAssociation() { + return false; + } + + public PropertyGeneration getGeneration() { + return generation; + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return relationalValueBindingContainer; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + relationalValueBindingContainer.addRelationalValueBindings( this.relationalValueBindingContainer ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java new file mode 100644 index 0000000000..8ad5d3887b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.FetchMode; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#BASIC} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class BasicPluralAttributeElementBinding extends AbstractPluralAttributeElementBinding { + + private RelationalValueBindingContainer relationalValueBindingContainer; + + public BasicPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + @Override + public Nature getNature() { + return Nature.BASIC; + } + + @Override + public FetchMode getFetchMode() { + return FetchMode.SELECT; + } + + public void setRelationalValueBindings(List relationalValueBindings) { + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java new file mode 100644 index 0000000000..30d3acbfd3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; + +/** + * + */ +public class BasicPluralAttributeIndexBinding extends AbstractPluralAttributeIndexBinding { + + private RelationalValueBindingContainer relationalValueBindingContainer; + + public BasicPluralAttributeIndexBinding( + IndexedPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding ); + } + + @Override + public List getRelationalValueBindings() { + return relationalValueBindingContainer.relationalValueBindings(); + } + + public void setRelationalValueBindings(List relationalValueBindings) { + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." ); + } + if ( this.relationalValueBindingContainer != null ) { + throw new AssertionFailure( "Relational value bindings have already initialized" ); + } + this.relationalValueBindingContainer = + new RelationalValueBindingContainer( relationalValueBindings ); + } + + @Override + public Nature getNature() { + return Nature.BASIC; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java index e4a9e0ed12..941069c400 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.cache.spi.access.AccessType; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java similarity index 99% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java index 14a4f2aa0a..226b8568f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.HashMap; import java.util.Map; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java similarity index 72% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java index 8fd839220a..a0c253a826 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,18 +21,20 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.engine.spi.CascadeStyle; /** - * Unifying interface for {@link ColumnSource} and {@link DerivedValueSource}. - * * @author Steve Ebersole - * @see ColumnSource - * @see DerivedValueSource */ -public interface RelationalValueSource { +public interface Cascadeable { /** - * @return returns the name of the table that contains this value. + * Obtain the cascade style to be applied to this association. + * + * @return The cascade style. */ - public String getContainingTableName(); + public CascadeStyle getCascadeStyle(); + + public void setCascadeStyle(CascadeStyle cascadeStyle); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java index 72240474c9..ef4c1973b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java new file mode 100644 index 0000000000..4385f5a39e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java @@ -0,0 +1,556 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * A specialized binding contract for a singular attribute binding that + * contains other attribute bindings. + * + * @author Gail Badner + */ +public class CompositeAttributeBinding + extends AbstractSingularAttributeBinding + implements SingularNonAssociationAttributeBinding, CompositeAttributeBindingContainer, Cascadeable { + + private final AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer; + private Class customComponentTuplizerClass = null; + private CompositeAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext + ); + this.compositeAttributeBindingContainer = compositeAttributeBindingContainer; + } + + public static CompositeAttributeBinding createAggregatedCompositeAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference) { + AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer = + new AbstractCompositeAttributeBindingContainer( + container.seekEntityBinding(), + (AttributeContainer) attribute.getSingularAttributeType(), + container.getPrimaryTable(), + createContainerPath( container, attribute ), + metaAttributeContext, + parentReference) { + private final Map attributeBindingMap = + new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + if ( ! attribute.getSingularAttributeType().isAggregate() ) { + throw new IllegalArgumentException( + "Cannot create an aggregated CompositeAttributeBindingContainer with a non-aggregate attribute type" + ); + } + return new CompositeAttributeBinding( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + compositeAttributeBindingContainer + ); + } + + // TODO: Get rid of this when non-aggregated composite IDs is no longer modelled as a CompositeAttributeBinding. + public static CompositeAttributeBinding createNonAggregatedCompositeAttributeBinding( + AttributeBindingContainer container, + SingularAttribute syntheticAttribute, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + final List subAttributeBindings) { + AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer = + new AbstractCompositeAttributeBindingContainer( + container.seekEntityBinding(), + (AttributeContainer) syntheticAttribute.getSingularAttributeType(), + container.getPrimaryTable(), + createContainerPath( container, syntheticAttribute ), + metaAttributeContext, + null) { + private final Map attributeBindingMap = createUnmodifiableAttributeBindingMap( subAttributeBindings ); + + @Override + protected boolean isModifiable() { + return false; + } + + @Override + protected Map attributeBindingMapInternal() { + return this.attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return false; + } + }; + if ( syntheticAttribute.getSingularAttributeType().isAggregate() ) { + throw new IllegalArgumentException( + "Cannot create a non-aggregated CompositeAttributeBindingContainer with an aggregate attribute type" + ); + } + return new CompositeAttributeBinding( + container, + syntheticAttribute, + "embedded", // TODO: get rid of "magic" string. + false, + false, + naturalIdMutability, + metaAttributeContext, + compositeAttributeBindingContainer + ); + } + + private static Map createUnmodifiableAttributeBindingMap( + List subAttributeBindings) { + Map map = new LinkedHashMap( subAttributeBindings.size() ); + for ( AttributeBinding subAttributeBinding : subAttributeBindings ) { + map.put( subAttributeBinding.getAttribute().getName(), subAttributeBinding ); + } + return Collections.unmodifiableMap( map ); + } + + private static String createContainerPath(AttributeBindingContainer container, SingularAttribute attribute) { + return StringHelper.isEmpty( container.getPathBase() ) ? + attribute.getName() : + container.getPathBase() + '.' + attribute.getName(); + + } + + /** + * Can the composite attribute be mapped to a single entity + * attribute by means of an actual component class that aggregates + * the tuple values? + * + * @return true, if the attribute can be mapped to a single entity + * attribute by means of an actual component class that aggregates + * the tuple values; false, otherwise. + */ + public boolean isAggregated() { + return compositeAttributeBindingContainer.isAggregated(); + } + + public SingularAttribute getParentReference() { + return compositeAttributeBindingContainer.getParentReference(); + } + + @Override + public Class getCustomTuplizerClass() { + return customComponentTuplizerClass; + } + + public void setCustomComponentTuplizerClass(Class customComponentTuplizerClass) { + this.customComponentTuplizerClass = customComponentTuplizerClass; + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return compositeAttributeBindingContainer.getRelationalValueBindingContainer(); + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean hasDerivedValue() { + // todo : not sure this is even relevant for components + return false; + } + + @Override + public boolean isCascadeable() { + for ( AttributeBinding attributeBinding : attributeBindings() ) { + if ( attributeBinding.isCascadeable() ) { + return true; + } + } + return false; + } + + @Override + public CascadeStyle getCascadeStyle() { + for ( AttributeBinding attributeBinding : attributeBindings() ) { + if ( attributeBinding.isCascadeable() ) { + final Cascadeable cascadeable; + if ( attributeBinding.getAttribute().isSingular() ) { + cascadeable = Cascadeable.class.cast( attributeBinding ); + } + else { + cascadeable = Cascadeable.class.cast( ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding() ); + } + CascadeStyle cascadeStyle = cascadeable.getCascadeStyle(); + if ( cascadeStyle != CascadeStyles.NONE ) { + return CascadeStyles.ALL; + } + } + } + return CascadeStyles.NONE; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + throw new IllegalAccessError( "Composite attribute is not supposed to have cascade" ); + } + + @Override + public boolean isNullable() { + // return false if there are any singular attributes are non-nullable + for ( AttributeBinding attributeBinding : attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ! ( (SingularAttributeBinding) attributeBinding ).isNullable() ) { + return false; + } + } + return true; + } + + @Override + public boolean isIncludedInInsert() { + // if the attribute is synthetic, this attribute binding (as a whole) is not insertable; + if ( getAttribute().isSynthetic() ) { + return false; + } + // otherwise, return true if there are any singular attributes that are included in the insert. + for ( AttributeBinding attributeBinding : attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ( (SingularAttributeBinding) attributeBinding ).isIncludedInInsert() ) { + return true; + } + } + return false; + } + + @Override + public boolean isIncludedInUpdate() { + // if the attribute is synthetic, this attribute binding (as a whole) is not updateable; + if ( getAttribute().isSynthetic() ) { + return false; + } + // otherwise, return true if there are any singular attributes that are updatable; + for ( AttributeBinding attributeBinding : attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ( (SingularAttributeBinding) attributeBinding ).isIncludedInUpdate() ) { + return true; + } + } + return false; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + compositeAttributeBindingContainer.collectRelationalValueBindings( relationalValueBindingContainer ); + } + + @Override + public String getPathBase() { + return compositeAttributeBindingContainer.getPathBase(); + } + + @Override + public AttributeContainer getAttributeContainer() { + return compositeAttributeBindingContainer.getAttributeContainer(); + } + + @Override + public Iterable attributeBindings() { + return compositeAttributeBindingContainer.attributeBindings(); + } + + @Override + public int attributeBindingSpan() { + return compositeAttributeBindingContainer.attributeBindingSpan(); + } + + @Override + public AttributeBinding locateAttributeBinding(String name) { + return compositeAttributeBindingContainer.locateAttributeBinding( name ); + } + + @Override + public SingularAttributeBinding locateAttributeBinding( + TableSpecification table, + List values) { + return compositeAttributeBindingContainer.locateAttributeBinding( table, values ); + } + + @Override + public EntityBinding seekEntityBinding() { + return compositeAttributeBindingContainer.seekEntityBinding(); + } + + @Override + public Class getClassReference() { + return compositeAttributeBindingContainer.getClassReference(); + } + + @Override + public TableSpecification getPrimaryTable() { + return compositeAttributeBindingContainer.getPrimaryTable(); + } + + + + @Override + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { + return compositeAttributeBindingContainer.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + generation + ); + } + + @Override + public CompositeAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext) { + return compositeAttributeBindingContainer.makeAggregatedCompositeAttributeBinding( + attribute, + parentReferenceAttribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext + ); + } + + @Override + public OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + return compositeAttributeBindingContainer.makeOneToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding, + isConstrained + ); + } + + @Override + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isNotFoundAnException, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + return compositeAttributeBindingContainer.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isNotFoundAnException, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding + ); + } + + @Override + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + return compositeAttributeBindingContainer.makeBagAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } + + @Override + public ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + return compositeAttributeBindingContainer.makeListAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base + ); + } + + @Override + public ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + return compositeAttributeBindingContainer.makeArrayAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + base + ); + } + + @Override + public MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature elementNature, + PluralAttributeIndexBinding.Nature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + return compositeAttributeBindingContainer.makeMapAttributeBinding( + attribute, + elementNature, + indexNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } + + @Override + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementBinding.Nature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + return compositeAttributeBindingContainer.makeSetAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBindingContainer.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBindingContainer.java index e39886d055..99015c9ac2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBindingContainer.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,19 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.tuple.component.ComponentTuplizer; /** - * @author Steve Ebersole * @author Gail Badner */ -public class CompositeCollectionElement extends AbstractCollectionElement { - public CompositeCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } +public interface CompositeAttributeBindingContainer + extends AttributeBindingContainer { + boolean isAggregated(); + SingularAttribute getParentReference(); @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.COMPOSITE; - } + Class getCustomTuplizerClass(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeElementBinding.java new file mode 100644 index 0000000000..c5f762a35f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeElementBinding.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#AGGREGATE} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class CompositePluralAttributeElementBinding + extends AbstractPluralAttributeElementBinding + implements Cascadeable { + + // TODO: Come up with a more descriptive name for compositeAttributeBindingContainer. + private AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer; + private CascadeStyle cascadeStyle; + + public CompositePluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueContainer() { + return compositeAttributeBindingContainer.getRelationalValueBindingContainer(); + } + + @Override + public Nature getNature() { + return Nature.AGGREGATE; + } + + public CompositeAttributeBindingContainer createCompositeAttributeBindingContainer( + Aggregate aggregate, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference + ) { + compositeAttributeBindingContainer = + new AbstractCompositeAttributeBindingContainer( + getPluralAttributeBinding().getContainer().seekEntityBinding(), + aggregate, + getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + aggregate.getRoleBaseName(), + metaAttributeContext, + parentReference + ) { + final Map attributeBindingMap = new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + return compositeAttributeBindingContainer; + } + + public CompositeAttributeBindingContainer getCompositeAttributeBindingContainer() { + return compositeAttributeBindingContainer; + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java new file mode 100644 index 0000000000..06295cc52b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#AGGREGATE} elements + * + * @author Gail Badner + */ +public class CompositePluralAttributeIndexBinding extends AbstractPluralAttributeIndexBinding { + + // TODO: Come up with a more descriptive name for compositeAttributeBindingContainer. + private AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer; + + public CompositePluralAttributeIndexBinding(IndexedPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public Nature getNature() { + return Nature.AGGREGATE; + } + + public CompositeAttributeBindingContainer createCompositeAttributeBindingContainer( + Aggregate aggregate, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference + ) { + compositeAttributeBindingContainer = + new AbstractCompositeAttributeBindingContainer( + getIndexedPluralAttributeBinding().getContainer().seekEntityBinding(), + aggregate, + getIndexedPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + aggregate.getRoleBaseName(), + metaAttributeContext, + parentReference + ) { + final Map attributeBindingMap = new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + return compositeAttributeBindingContainer; + } + + public CompositeAttributeBindingContainer getCompositeAttributeBindingContainer() { + return compositeAttributeBindingContainer; + } + + @Override + public List getRelationalValueBindings() { + return compositeAttributeBindingContainer.getRelationalValueBindingContainer().relationalValueBindings(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java index 17cc349364..67da4cfcf2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java new file mode 100644 index 0000000000..22cdd70ca7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java @@ -0,0 +1,847 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.MappingException; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.property.PropertyAccessorFactory; +import org.hibernate.tuple.entity.EntityTuplizer; + +/** + * Provides the link between the domain and the relational model for an entity. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + * @author Strong Liu + */ +public class EntityBinding extends AbstractAttributeBindingContainer implements Filterable { + private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null"; + private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null"; + + private final EntityBinding superEntityBinding; + private final List subEntityBindings = new ArrayList(); + private final HierarchyDetails hierarchyDetails; + + private Entity entity; + private TableSpecification primaryTable; + private String primaryTableName; + private Map secondaryTables = new LinkedHashMap(); + + private ValueHolder> proxyInterfaceType; + + private String entityName; + private String jpaEntityName; + + private Class customEntityPersisterClass; + private Class customEntityTuplizerClass; + + private String discriminatorMatchValue; + + private List filterConfigurations = new ArrayList(); + + private MetaAttributeContext metaAttributeContext; + + private boolean lazy; + private boolean mutable; + private String whereFilter; + private String rowId; + + private boolean dynamicUpdate; + private boolean dynamicInsert; + + private int batchSize; + private boolean selectBeforeUpdate; + private boolean hasSubselectLoadableCollections; + + private Boolean isAbstract; + + private String customLoaderName; + private CustomSQL customInsert; + private CustomSQL customUpdate; + private CustomSQL customDelete; + + private String[] synchronizedTableNames = StringHelper.EMPTY_STRINGS; + private Map attributeBindingMap = new LinkedHashMap(); + + private List jpaCallbackClasses = new ArrayList(); + private final int subEntityBindingId; + private int nextSubEntityBindingId = 0; + //for joined sub entitybinding only + private boolean isCascadeDeleteEnabled = false; + /** + * Used to instantiate the EntityBinding for an entity that is the root of an inheritance hierarchy + * + * @param inheritanceType The inheritance type for the hierarchy + * @param entityMode The entity mode used in this hierarchy. + */ + public EntityBinding(InheritanceType inheritanceType, EntityMode entityMode) { + this.superEntityBinding = null; + this.hierarchyDetails = new HierarchyDetails( this, inheritanceType, entityMode ); + this.subEntityBindingId = 0; + } + + /** + * Used to instantiate the EntityBinding for an entity that is a subclass (sub-entity) in an inheritance hierarchy + * + * @param superEntityBinding The entity binding of this binding's super + */ + public EntityBinding(EntityBinding superEntityBinding) { + this.superEntityBinding = superEntityBinding; + this.superEntityBinding.subEntityBindings.add( this ); + // TODO: the ID attribute binding needs to be recreated for this EntityBinding + // otherwise, this != hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer() + this.hierarchyDetails = superEntityBinding.getHierarchyDetails(); + this.subEntityBindingId = superEntityBinding.nextSubEntityBindingId(); + } + + private int nextSubEntityBindingId(){ + return isRoot()? ++nextSubEntityBindingId : superEntityBinding.nextSubEntityBindingId(); + } + + public HierarchyDetails getHierarchyDetails() { + return hierarchyDetails; + } + + public EntityBinding getSuperEntityBinding() { + return superEntityBinding; + } + + public int getSubEntityBindingId() { + return subEntityBindingId; + } + + public boolean isRoot() { + return superEntityBinding == null; + } + + public boolean isPolymorphic() { + return !isRoot() || + hierarchyDetails.getEntityDiscriminator() != null || + !subEntityBindings.isEmpty(); + } + + public boolean hasSubEntityBindings() { + return !subEntityBindings.isEmpty(); + } + + + + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + } + + @Override + public TableSpecification getPrimaryTable() { + return primaryTable; + } + + public void setPrimaryTable(TableSpecification primaryTable) { + this.primaryTable = primaryTable; + } + + public boolean hasTable(String tableName) { + return tableName.equals( getPrimaryTableName() ) || + secondaryTables.containsKey( Identifier.toIdentifier( tableName ) ); + } + + public TableSpecification locateTable(String tableName) { + if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) { + return primaryTable; + } + SecondaryTable secondaryTable = secondaryTables.get( Identifier.toIdentifier( tableName ) ); + if ( secondaryTable == null ) { + throw new AssertionFailure( + String.format( + "Unable to find table %s amongst tables %s", + tableName, + secondaryTables.keySet() + ) + ); + } + return secondaryTable.getSecondaryTableReference(); + } + + public AttributeBinding locateAttributeBinding(String name, boolean searchParent) { + AttributeBinding attributeBinding = locateAttributeBinding( name ); + if ( attributeBinding == null && searchParent && getSuperEntityBinding() != null ) { + return getSuperEntityBinding().locateAttributeBinding( name, searchParent ); + } + else { + return attributeBinding; + } + } + + public SingularAttributeBinding locateAttributeBinding( + TableSpecification table, + List values, + boolean searchParent) { + SingularAttributeBinding attributeBinding = null; + SingularAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( primaryTable.equals( table ) && idAttributeBinding.getValues().equals( values ) ) { + attributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + } + if ( attributeBinding == null ) { + attributeBinding = locateAttributeBinding( table, values ); + } + if ( attributeBinding == null && searchParent && getSuperEntityBinding() != null ) { + attributeBinding = getSuperEntityBinding().locateAttributeBinding( table, values, searchParent ); + } + return attributeBinding; + } + + public AttributeBinding locateAttributeBindingByPath(String path, boolean searchParent) { + if ( path == null ) { + throw new IllegalArgumentException( "path must be non-null." ); + } + final String pathDelimiter = "\\."; + String[] tokens = path.split( pathDelimiter ); + AttributeBinding attributeBinding = locateAttributeBinding( tokens[ 0 ], searchParent ); + for ( int i = 1 ; i < tokens.length && attributeBinding != null ; i++ ) { + if ( ! attributeBinding.getAttribute().isSingular() || + ! ( (SingularAttribute) attributeBinding.getAttribute() ).getSingularAttributeType().isAggregate() ) { + // TODO: improve this message!!! + throw new MappingException( "improve this!!!" ); + } + AttributeBindingContainer attributeBindingContainer = (AttributeBindingContainer) attributeBinding; + attributeBinding = attributeBindingContainer.locateAttributeBinding( tokens[ i ] ); + } + return attributeBinding; + } + + public String getPrimaryTableName() { + return primaryTableName; + } + + public void setPrimaryTableName(String primaryTableName) { + this.primaryTableName = primaryTableName; + } + + public void addSecondaryTable(SecondaryTable secondaryTable) { + secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName(), secondaryTable ); + } + public Map getSecondaryTables() { + return Collections.unmodifiableMap( secondaryTables ); + } + + public boolean isVersioned() { + return getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() != null; + } + + public boolean isDiscriminatorMatchValueNull() { + return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); + } + + public boolean isDiscriminatorMatchValueNotNull() { + return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); + } + + public String getDiscriminatorMatchValue() { + return discriminatorMatchValue; + } + + public void setDiscriminatorMatchValue(String discriminatorMatchValue) { + this.discriminatorMatchValue = discriminatorMatchValue; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + if ( superEntityBinding != null ) { + List results = new ArrayList( filterConfigurations ); + results.addAll( superEntityBinding.getFilterConfigurations() ); + return results; + } + return filterConfigurations; + } + + @Override + public EntityBinding seekEntityBinding() { + return this; + } + + @Override + public String getPathBase() { + return ""; + } + + @Override + public AttributeContainer getAttributeContainer() { + return getEntity(); + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { + this.metaAttributeContext = metaAttributeContext; + } + + public boolean isMutable() { + return mutable; + } + + public void setMutable(boolean mutable) { + this.mutable = mutable; + } + + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { + isCascadeDeleteEnabled = cascadeDeleteEnabled; + } + + public boolean isLazy() { + return lazy; + } + + public void setLazy(boolean lazy) { + this.lazy = lazy; + } + + public ValueHolder> getProxyInterfaceType() { + return proxyInterfaceType; + } + + public void setProxyInterfaceType(ValueHolder> proxyInterfaceType) { + this.proxyInterfaceType = proxyInterfaceType; + } + + public String getWhereFilter() { + if ( StringHelper.isNotEmpty( whereFilter ) ) { + return whereFilter; + } + else if ( superEntityBinding != null ) { + return superEntityBinding.getWhereFilter(); + } + else { + return null; + } + } + + public void setWhereFilter(String whereFilter) { + this.whereFilter = whereFilter; + } + + public String getRowId() { + return rowId; + } + + public void setRowId(String rowId) { + this.rowId = rowId; + } + + public boolean isDynamicUpdate() { + return dynamicUpdate; + } + + public void setDynamicUpdate(boolean dynamicUpdate) { + this.dynamicUpdate = dynamicUpdate; + } + + public boolean isDynamicInsert() { + return dynamicInsert; + } + + public void setDynamicInsert(boolean dynamicInsert) { + this.dynamicInsert = dynamicInsert; + } + + public int getBatchSize() { + return batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public boolean isSelectBeforeUpdate() { + return selectBeforeUpdate; + } + + public void setSelectBeforeUpdate(boolean selectBeforeUpdate) { + this.selectBeforeUpdate = selectBeforeUpdate; + } + + public boolean hasSubselectLoadableCollections() { + return hasSubselectLoadableCollections; + } + + public void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) { + this.hasSubselectLoadableCollections = hasSubselectLoadableCollections; + } + + public Class getCustomEntityPersisterClass() { + if ( customEntityPersisterClass != null ) { + return customEntityPersisterClass; + } + else if ( superEntityBinding != null ) { + return superEntityBinding.getCustomEntityPersisterClass(); + } + return null; + } + + public void setCustomEntityPersisterClass(Class customEntityPersisterClass) { + this.customEntityPersisterClass = customEntityPersisterClass; + } + @Override + public Class getCustomTuplizerClass() { + if ( customEntityTuplizerClass != null ) { + return customEntityTuplizerClass; + } + else if ( superEntityBinding != null ) { + return superEntityBinding.getCustomTuplizerClass(); + } + return null; + } + + public void setCustomEntityTuplizerClass(Class customEntityTuplizerClass) { + this.customEntityTuplizerClass = customEntityTuplizerClass; + } + + public Boolean isAbstract() { + return isAbstract; + } + + public void setAbstract(Boolean isAbstract) { + this.isAbstract = isAbstract; + } + + public String[] getSynchronizedTableNames() { + return synchronizedTableNames; + } + + public void addSynchronizedTableNames(String [] synchronizedTableNames) { + this.synchronizedTableNames = ArrayHelper.join( this.synchronizedTableNames, synchronizedTableNames ); + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public String getJpaEntityName() { + return jpaEntityName; + } + + public void setJpaEntityName(String jpaEntityName) { + this.jpaEntityName = jpaEntityName; + } + + public String getCustomLoaderName() { + return customLoaderName; + } + + public void setCustomLoaderName(String customLoaderName) { + this.customLoaderName = customLoaderName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public void setCustomInsert(CustomSQL customInsert) { + this.customInsert = customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public void setCustomUpdate(CustomSQL customUpdate) { + this.customUpdate = customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public void setCustomDelete(CustomSQL customDelete) { + this.customDelete = customDelete; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "EntityBinding" ); + sb.append( "{entity=" ).append( entity != null ? entity.getName() : "not set" ); + sb.append( '}' ); + return sb.toString(); + } + + public CompositeAttributeBinding makeVirtualCompositeAttributeBinding( + SingularAttribute syntheticAttribute, + MetaAttributeContext metaAttributeContext, + List idAttributeBindings) { + if ( !syntheticAttribute.isSynthetic() ) { + throw new AssertionFailure( + "Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference" + ); + } + // TODO: make sure all attributes are singular + final CompositeAttributeBinding binding = + CompositeAttributeBinding.createNonAggregatedCompositeAttributeBinding( + this, + syntheticAttribute, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID, + metaAttributeContext, + idAttributeBindings + ); + registerAttributeBinding( binding ); + return binding; + } + + public BackRefAttributeBinding makeBackRefAttributeBinding( + SingularAttribute syntheticAttribute, + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + if ( ! syntheticAttribute.isSynthetic() ) { + throw new AssertionFailure( + "Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference" + ); + } + final BackRefAttributeBinding binding = new BackRefAttributeBinding( + this, + syntheticAttribute, + pluralAttributeBinding, + isIndexBackRef + ); + + registerAttributeBinding( binding ); + return binding; + } + + + public void setJpaCallbackClasses(List jpaCallbackClasses) { + this.jpaCallbackClasses = jpaCallbackClasses; + } + + public List getJpaCallbackClasses() { + return Collections.unmodifiableList( jpaCallbackClasses ); + } + //-------------------------- + //meta methods for persister , to improve performance, these methods below should really be replaced as ValueHolder + //and only be called in persister -- after build MetadataImpl + + + public TableSpecification[] getTableClosure() { + if ( isRoot() ) { + return new TableSpecification[] { getPrimaryTable() }; + } + return ArrayHelper.join( superEntityBinding.getTableClosure(), getPrimaryTable() ); + } + + public EntityBinding[] getEntityBindingClosure() { + if ( isRoot() ) { + return new EntityBinding[] { this }; + } + return ArrayHelper.join( superEntityBinding.getEntityBindingClosure(), this ); + } + + public int getSecondaryTableClosureSpan() { + return isRoot() ? secondaryTables.size() : superEntityBinding.getSecondaryTableClosureSpan() + secondaryTables.size(); + } + + public SecondaryTable[] getSecondaryTableClosure() { + if ( isRoot() ) { + return secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] ); + } + else { + return ArrayHelper.join( + superEntityBinding.getSecondaryTableClosure(), + secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] ) + ); + } + } + + public String[] getSynchronizedTableNameClosure() { + if ( isRoot() ) { + return getSynchronizedTableNames(); + } + return ArrayHelper.join( superEntityBinding.getSynchronizedTableNameClosure(), getSynchronizedTableNames() ); + } + + + /** + * Gets the number of attribute bindings defined on this class, including the + * identifier attribute binding and attribute bindings defined + * as part of a join. + * + * @return The number of attribute bindings + */ + public int getAttributeBindingClosureSpan() { + // TODO: update account for join attribute bindings + return getAttributeBindingClosure().length; + } + + /** + * Gets the attribute bindings defined on this class, including the + * identifier attribute binding and attribute bindings defined + * as part of a join. + * + * @return The attribute bindings. + */ + public AttributeBinding[] getAttributeBindingClosure() { + // TODO: update size to account for joins + if ( isRoot() ) { + return attributeBindingMapInternal().values() + .toArray( new AttributeBinding[attributeBindingMapInternal().size()] ); + } + else { + return ArrayHelper.join( + superEntityBinding.getAttributeBindingClosure(), + attributeBindingMapInternal().values() + .toArray( new AttributeBinding[attributeBindingMapInternal().size()] ) + + ); + } + } + + public AttributeBinding[] getNonIdAttributeBindingClosure(){ + // TODO: update size to account for joins + if ( isRoot() ) { + return internalGetNonIdAttributeBindingClosure(); + } + else { + return ArrayHelper.join( + superEntityBinding.getNonIdAttributeBindingClosure(), + internalGetNonIdAttributeBindingClosure() + ); + } + } + + private AttributeBinding[] internalGetNonIdAttributeBindingClosure() { + List list = new ArrayList(); + for ( final AttributeBinding ab : attributeBindings() ) { + boolean isId = getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( ab ); + if ( !isId ) { + list.add( ab ); + } + } + return list.toArray( new AttributeBinding[list.size()] ); + + } + + public List getDirectSubEntityBindings() { + return subEntityBindings; + } + + /** + * Returns sub-EntityBinding objects in a special 'order', most derived subclasses + * first. Specifically, the sub-entity bindings follow a depth-first, + * post-order traversal + * + * Note that the returned value excludes this entity binding. + * + * @return sub-entity bindings ordered by those entity bindings that are most derived. + */ + public EntityBinding[] getPostOrderSubEntityBindingClosure() { + EntityBinding[] results = new EntityBinding[0]; + if ( subEntityBindings.isEmpty() ) { + return results; + } + for ( EntityBinding subEntityBinding : subEntityBindings ) { + EntityBinding[] subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure(); + results = ArrayHelper.join( results, subSubEntityBindings ); + } + if ( !subEntityBindings.isEmpty() ) { + results = ArrayHelper.join( results, subEntityBindings.toArray( new EntityBinding[subEntityBindings.size()] ) ); + } + return results; + } + + /** + * Returns sub-EntityBinding ordered as a depth-first, + * pre-order traversal (a subclass precedes its own subclasses). + * + * Note that the returned value specifically excludes this entity binding. + * + * @return sub-entity bindings ordered as a depth-first, + * pre-order traversal + */ + public EntityBinding[] getPreOrderSubEntityBindingClosure() { + return getPreOrderSubEntityBindingClosure( false, new EntityBinding[0] ); + } + + private EntityBinding[] getPreOrderSubEntityBindingClosure(boolean includeThis, EntityBinding[] results) { + if ( includeThis ) { + results = ArrayHelper.join( results, this ); + } + for ( EntityBinding subEntityBinding : subEntityBindings ) { + results = subEntityBinding.getPreOrderSubEntityBindingClosure( + true, results + ); + } + return results; + } + + public TableSpecification[] getPreOrderSubTableClosure(){ + EntityBinding[] subEntityBindings = getPreOrderSubEntityBindingClosure(); + TableSpecification [] tables = new TableSpecification[subEntityBindings.length]; + for(int i=0;i sts = eb.getSecondaryTables().values(); + int size = sts.size(); + if ( size == 0 ) { + continue; + } + results = ArrayHelper.join( results, sts.toArray( new SecondaryTable[size] ) ); + } + return results; + } + + + public SecondaryTable[] getEntitiesSecondaryTableClosure() { + if ( ! subEntityBindings.isEmpty() ) { + return ArrayHelper.join( getSecondaryTableClosure(), getSubEntitySecondaryTables() ); + } + else { + return getSecondaryTableClosure(); + } + } + + public int getSubEntityBindingClosureSpan() { + int n = subEntityBindings.size(); + for ( final EntityBinding seb : subEntityBindings ) { + n += seb.getSubEntityBindingClosureSpan(); + } + return n; + } + + /** + * @return the attribute bindings for this EntityBinding and all of its + * sub-EntityBinding, starting from the root of the hierarchy; includes + * the identifier and attribute bindings defined as part of a join. + */ + public AttributeBinding[] getEntitiesAttributeBindingClosure() { + AttributeBinding[] results = getAttributeBindingClosure(); + + for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { + // only add attribute bindings declared for the subEntityBinding + + results = ArrayHelper.join( + results, + subEntityBinding.attributeBindingMapInternal().values().toArray( new AttributeBinding[subEntityBinding.attributeBindingMapInternal().size()] ) + ); + // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here + } + return results; + } + public AttributeBinding[] getNonIdEntitiesAttributeBindingClosure() { + AttributeBinding[] results = getNonIdAttributeBindingClosure(); + + for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { + // only add attribute bindings declared for the subEntityBinding + + results = ArrayHelper.join( + results, + subEntityBinding.internalGetNonIdAttributeBindingClosure() + ); + // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here + } + return results; + } + + public boolean isClassOrSuperclassSecondaryTable(SecondaryTable secondaryTable) { + return secondaryTables.containsKey( secondaryTable.getSecondaryTableReference().getLogicalName() ) || + ( superEntityBinding != null && superEntityBinding.isClassOrSuperclassSecondaryTable( secondaryTable ) ); + } + + private List keyRelationalValueBindings; + + public List getKeyRelationalValueBindings() { + if(keyRelationalValueBindings == null){ + keyRelationalValueBindings = getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getRelationalValueBindings(); + } + return keyRelationalValueBindings; + } + + public void setKeyRelationalValueBindings(List keyRelationalValueBindings) { + this.keyRelationalValueBindings = keyRelationalValueBindings; + } + + public int getSecondaryTableNumber(SingularAttributeBinding attributeBinding) { + if ( attributeBinding.getRelationalValueBindings().isEmpty() ) { + return 0; + } + int result=1; + TableSpecification table = attributeBinding.getRelationalValueBindings().get( 0 ).getTable(); + for ( SecondaryTable secondaryTable : getEntitiesSecondaryTableClosure() ) { + if ( secondaryTable.getSecondaryTableReference() == table ) { + return result; + } + result++; + } + return 0; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java index 724d194d8f..1b31f064b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java @@ -21,9 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import org.hibernate.metamodel.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Value; /** * Binding of the discriminator in a entity hierarchy @@ -34,19 +34,18 @@ import org.hibernate.metamodel.relational.SimpleValue; public class EntityDiscriminator { private final HibernateTypeDescriptor explicitHibernateTypeDescriptor = new HibernateTypeDescriptor(); - private SimpleValue boundValue; - private boolean forced; - private boolean inserted = true; + private final Value relationalValue; + private final boolean inserted; + private final boolean forced; - public EntityDiscriminator() { + public EntityDiscriminator(Value relationalValue, boolean inserted, boolean forced) { + this.relationalValue = relationalValue; + this.inserted = inserted; + this.forced = forced; } - public SimpleValue getBoundValue() { - return boundValue; - } - - public void setBoundValue(SimpleValue boundValue) { - this.boundValue = boundValue; + public Value getRelationalValue() { + return relationalValue; } public HibernateTypeDescriptor getExplicitHibernateTypeDescriptor() { @@ -57,23 +56,15 @@ public class EntityDiscriminator { return forced; } - public void setForced(boolean forced) { - this.forced = forced; - } - public boolean isInserted() { return inserted; } - public void setInserted(boolean inserted) { - this.inserted = inserted; - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "EntityDiscriminator" ); - sb.append( "{boundValue=" ).append( boundValue ); + sb.append( "{relationalValue=" ).append( relationalValue ); sb.append( ", forced=" ).append( forced ); sb.append( ", inserted=" ).append( inserted ); sb.append( '}' ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java new file mode 100644 index 0000000000..c4091b86fb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java @@ -0,0 +1,537 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.MappingException; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.id.CompositeNestedGeneratedValueGenerator; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.property.Setter; + +import static org.hibernate.id.EntityIdentifierNature.AGGREGATED_COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.SIMPLE; + +/** + * Hold information about the entity identifier. At a high-level, can be one of 2-types:

    + *
  • single-attribute identifier - this includes both simple identifiers and aggregated composite identifiers
  • + *
  • multiple-attribute identifier - non-aggregated composite identifiers
  • + *
+ * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class EntityIdentifier { + private final EntityBinding entityBinding; + private EntityIdentifierBinding entityIdentifierBinding; + private IdentifierGenerator identifierGenerator; + + /** + * Create an identifier + * + * @param entityBinding the entity binding for which this instance is the id + */ + public EntityIdentifier(EntityBinding entityBinding) { + this.entityBinding = entityBinding; + } + + public EntityBinding getEntityBinding() { + return entityBinding; + } + + public void prepareAsSimpleIdentifier( + SingularNonAssociationAttributeBinding attributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + ensureNotBound(); + this.entityIdentifierBinding = + new SimpleAttributeIdentifierBindingImpl( attributeBinding, identifierGeneratorDefinition, unsavedValue ); + } + + public void prepareAsAggregatedCompositeIdentifier( + CompositeAttributeBinding attributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + ensureNotBound(); + this.entityIdentifierBinding = + new AggregatedComponentIdentifierBindingImpl( attributeBinding, + identifierGeneratorDefinition, unsavedValue ); + } + + public void prepareAsNonAggregatedCompositeIdentifier( + CompositeAttributeBinding compositeAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class externalAggregatingClass, + String externalAggregatingPropertyAccessorName) { + ensureNotBound(); + this.entityIdentifierBinding = new NonAggregatedCompositeIdentifierBindingImpl( + compositeAttributeBinding, + identifierGeneratorDefinition, + unsavedValue, + externalAggregatingClass, + externalAggregatingPropertyAccessorName + ); + } + + public EntityIdentifierNature getNature() { + ensureBound(); + return entityIdentifierBinding.getNature(); + } + + public SingularNonAssociationAttributeBinding getAttributeBinding() { + ensureBound(); + return entityIdentifierBinding.getAttributeBinding(); + } + + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + ensureBound(); + return entityIdentifierBinding.isIdentifierAttributeBinding( attributeBinding ); + } + + public boolean isCascadeDeleteEnabled() { + if ( getAttributeBinding() instanceof Cascadeable ) { + Cascadeable cascadeable = Cascadeable.class.cast( getAttributeBinding() ); + cascadeable.getCascadeStyle();//todo + } + return false; + } + + public String getUnsavedValue() { + ensureBound(); + return entityIdentifierBinding.getUnsavedValue(); + } + + public boolean isNonAggregatedComposite() { + ensureBound(); + return getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + + public Class getIdClassClass() { + ensureBound(); + ensureNonAggregatedComposite(); + return ( (NonAggregatedCompositeIdentifierBindingImpl) entityIdentifierBinding ).getIdClassClass(); + } + + public String getIdClassPropertyAccessorName() { + ensureBound(); + ensureNonAggregatedComposite(); + return ( (NonAggregatedCompositeIdentifierBindingImpl) entityIdentifierBinding ).getIdClassPropertyAccessorName(); + } + + private void ensureNonAggregatedComposite() { + if ( ! isNonAggregatedComposite() ) { + throw new UnsupportedOperationException( + String.format( + "Entity identifiers of nature %s does not support idClasses.", + entityIdentifierBinding.getNature() + ) + ); + } + } + + public boolean isIdentifierMapper() { + ensureBound(); + return isNonAggregatedComposite() && + ( (NonAggregatedCompositeIdentifierBindingImpl) entityIdentifierBinding ).getIdClassClass() != null; + } + + // todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early + // maybe some sort of visitor pattern here!? (HF) + public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) { + ensureBound(); + if ( identifierGenerator == null ) { + identifierGenerator = entityIdentifierBinding.createIdentifierGenerator( factory, properties ); + } + return identifierGenerator; + } + + public IdentifierGenerator getIdentifierGenerator() { + ensureBound(); + return identifierGenerator; + } + + protected void ensureBound() { + if ( ! isBound() ) { + throw new IllegalStateException( "Entity identifier was not yet bound" ); + } + } + + protected void ensureNotBound() { + if ( isBound() ) { + throw new IllegalStateException( "Entity identifier was already bound" ); + } + } + + protected boolean isBound() { + return entityIdentifierBinding != null; + } + + public int getColumnCount() { + ensureBound(); + return entityIdentifierBinding.getColumnCount(); + } + + private abstract class EntityIdentifierBinding { + private final EntityIdentifierNature nature; + private final SingularNonAssociationAttributeBinding identifierAttributeBinding; + private final IdentifierGeneratorDefinition identifierGeneratorDefinition; + private final String unsavedValue; + private final int columnCount; + + + protected EntityIdentifierBinding( + EntityIdentifierNature nature, + SingularNonAssociationAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + this.nature = nature; + this.identifierAttributeBinding = identifierAttributeBinding; + this.identifierGeneratorDefinition = identifierGeneratorDefinition; + this.unsavedValue = unsavedValue; + + // Configure primary key in relational model + final List relationalValueBindings = identifierAttributeBinding.getRelationalValueBindings(); + this.columnCount = relationalValueBindings.size(); + for ( final RelationalValueBinding valueBinding : relationalValueBindings ) { + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() ); + } + } + + public EntityIdentifierNature getNature() { + return nature; + } + + public SingularNonAssociationAttributeBinding getAttributeBinding() { + return identifierAttributeBinding; + } + + public String getUnsavedValue() { + return unsavedValue; + } + + protected IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() { + return identifierGeneratorDefinition; + } + + public int getColumnCount() { + return columnCount; + } + + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + return getAttributeBinding().equals( attributeBinding ); + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory identifierGeneratorFactory, + Properties properties) { + final List relationalValueBindings = + getAttributeBinding().getRelationalValueBindings(); + + // TODO: If multiple @Column annotations exist within an id's + // @Columns, we need a more solid solution than simply grabbing + // the first one to get the TableSpecification. + + final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + final TableSpecification table = relationalValueBinding.getTable(); + if ( !Column.class.isInstance( relationalValueBinding.getValue() ) ) { + throw new MappingException( + "Cannot create an IdentifierGenerator because the value is not a column: " + + relationalValueBinding.getValue().toLoggableString() + ); + } + + Properties params = new Properties(); + params.putAll( properties ); + + // use the schema/catalog specified by getValue().getTable() - but note that + // if the schema/catalog were specified as params, they will already be initialized and + //will override the values set here (they are in identifierGeneratorDefinition.getParameters().) + Schema schema = table.getSchema(); + if ( schema != null ) { + if ( schema.getName().getSchema() != null ) { + params.setProperty( PersistentIdentifierGenerator.SCHEMA, schema.getName().getSchema().getText() ); + } + if ( schema.getName().getCatalog() != null ) { + params.setProperty( PersistentIdentifierGenerator.CATALOG, schema.getName().getCatalog().getText() ); + } + } + + params.setProperty( IdentifierGenerator.ENTITY_NAME, entityBinding.getEntity().getName() ); + params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, entityBinding.getJpaEntityName() ); + + //init the table here instead of earlier, so that we can get a quoted table name + //TODO: would it be better to simply pass the qualified table name, instead of + // splitting it up into schema/catalog/table names + String tableName = table.getQualifiedName( identifierGeneratorFactory.getDialect() ); + params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); + + params.setProperty( + PersistentIdentifierGenerator.PK, + ( (Column) relationalValueBinding.getValue() ).getColumnName().getText( + identifierGeneratorFactory.getDialect() + ) + ); + if ( entityBinding.getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) { + params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); + } else { + params.setProperty( + PersistentIdentifierGenerator.TABLES, + resolveTableNames( identifierGeneratorFactory.getDialect(), entityBinding ) + ); + } + params.putAll( getIdentifierGeneratorDefinition().getParameters() ); + return identifierGeneratorFactory.createIdentifierGenerator( + getIdentifierGeneratorDefinition().getStrategy(), + getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(), + params + ); + } + } + + private class SimpleAttributeIdentifierBindingImpl extends EntityIdentifierBinding { + SimpleAttributeIdentifierBindingImpl( + SingularNonAssociationAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + super( SIMPLE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + } + + } + + private String resolveTableNames(Dialect dialect, EntityBinding entityBinding) { + EntityBinding[] ebs = entityBinding.getPostOrderSubEntityBindingClosure(); + StringBuilder tableNames = new StringBuilder(); + String tbName = resolveTableName( dialect, entityBinding ); + if( StringHelper.isNotEmpty( tbName )){ + tableNames.append( tbName ); + } + + for ( EntityBinding eb : ebs ) { + tbName = resolveTableName( dialect, eb ); + if(StringHelper.isNotEmpty( tbName )){ + tableNames.append( ", " ).append( tbName ); + } + } + return tableNames.toString(); + } + + private String resolveTableName(Dialect dialect, EntityBinding entityBinding) { + TableSpecification tableSpecification = entityBinding.getPrimaryTable(); + if ( tableSpecification instanceof Table ) { + Table tb = (Table) tableSpecification; + if ( tb.isPhysicalTable() ) { + return tb.getTableName().toText( dialect ); + } + } + return null; + } + + private class AggregatedComponentIdentifierBindingImpl extends EntityIdentifierBinding { + AggregatedComponentIdentifierBindingImpl( + CompositeAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + super( AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + if ( ! identifierAttributeBinding.isAggregated() ) { + throw new IllegalArgumentException( + String.format( + "identifierAttributeBinding must be an aggregated CompositeAttributeBinding: %s", + identifierAttributeBinding.getAttribute().getName() + ) + ); + } + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory factory, + Properties properties) { + if ( entityBinding.getSuperEntityBinding() != null ) { + throw new AssertionError( "Creating an identifier generator for a component on a subclass." ); + } + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); + + final boolean hasCustomGenerator = ! "assigned".equals( getIdentifierGeneratorDefinition().getStrategy() ); + if ( hasCustomGenerator ) { + return super.createIdentifierGenerator( + factory, properties + ); + } + final Class entityClass = entityBinding.getEntity().getClassReference(); + final Class attributeDeclarer; // what class is the declarer of the composite pk attributes + // IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the + // various scenarios for which we need to account here + // we have the "@EmbeddedId" / case + CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator = + new CompositeNestedGeneratedValueGenerator.GenerationContextLocator() { + public Serializable locateGenerationContext( SessionImplementor session, Object incomingObject) { + return session.getEntityPersister( entityBinding.getEntity().getName(), incomingObject ) + .getIdentifier( incomingObject, session ); + } + }; + // TODO: set up IdentifierGenerator for non-assigned sub-attributes + return new CompositeNestedGeneratedValueGenerator( locator ); + } + } + + private static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan { + private final String propertyName; + private final IdentifierGenerator subGenerator; + private final Setter injector; + + public ValueGenerationPlan( + String propertyName, + IdentifierGenerator subGenerator, + Setter injector) { + this.propertyName = propertyName; + this.subGenerator = subGenerator; + this.injector = injector; + } + + /** + * {@inheritDoc} + */ + public void execute(SessionImplementor session, Object incomingObject, Object injectionContext) { + final Object generatedValue = subGenerator.generate( session, incomingObject ); + injector.set( injectionContext, generatedValue, session.getFactory() ); + } + + public void registerPersistentGenerators(Map generatorMap) { + if ( PersistentIdentifierGenerator.class.isInstance( subGenerator ) ) { + generatorMap.put( ( (PersistentIdentifierGenerator) subGenerator ).generatorKey(), subGenerator ); + } + } + } + + private class NonAggregatedCompositeIdentifierBindingImpl extends EntityIdentifierBinding { + private final Class externalAggregatingClass; + private final String externalAggregatingPropertyAccessorName; + + NonAggregatedCompositeIdentifierBindingImpl( + CompositeAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class externalAggregatingClass, + String externalAggregatingPropertyAccessorName) { + super( NON_AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + if ( identifierAttributeBinding.isAggregated() ) { + throw new IllegalArgumentException( + String.format( + "identifierAttributeBinding must be a non-aggregated CompositeAttributeBinding: %s", + identifierAttributeBinding.getAttribute().getName() + ) + ); + } + this.externalAggregatingClass = externalAggregatingClass; + this.externalAggregatingPropertyAccessorName = externalAggregatingPropertyAccessorName; + if ( identifierAttributeBinding.attributeBindingSpan() == 0 ) { + throw new MappingException( + "A composite ID has 0 attributes for " + entityBinding.getEntity().getName() + ); + } + for ( AttributeBinding attributeBinding : identifierAttributeBinding.attributeBindings() ) { + if ( ! attributeBinding.getAttribute().isSingular() ) { + throw new MappingException( + String.format( + "The composite ID for [%s] contains an attribute [%s} that is plural.", + entityBinding.getEntity().getName(), + attributeBinding.getAttribute().getName() + ) + ); + } + } + } + + private CompositeAttributeBinding getNonAggregatedCompositeAttributeBinding() { + return (CompositeAttributeBinding) getAttributeBinding(); + } + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + if ( !isIdentifierMapper() && getNonAggregatedCompositeAttributeBinding().equals( attributeBinding ) ) { + return true; + + } + for ( AttributeBinding idAttributeBindings : getNonAggregatedCompositeAttributeBinding().attributeBindings() ) { + if ( idAttributeBindings.equals( attributeBinding ) ) { + return true; + } + } + return false; + } + + public Class getIdClassClass() { + return externalAggregatingClass; + } + + public String getIdClassPropertyAccessorName() { + return externalAggregatingPropertyAccessorName; + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory factory, + Properties properties) { + if ( entityBinding.getSuperEntityBinding() != null ) { + throw new AssertionError( "Creating an identifier generator for a component on a subclass." ); + } + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); + final Class entityClass = entityBinding.getEntity().getClassReference(); + final Class attributeDeclarer; // what class is the declarer of the composite pk attributes + // IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the + // various scenarios for which we need to account here + //if ( idClassClass != null ) { + // we have the @IdClass / case + // attributeDeclarer = idClassClass; + //} + //else { + // we have the "straight up" embedded (again the hibernate term) component identifier + // attributeDeclarer = entityClass; + //} + CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator = + new CompositeNestedGeneratedValueGenerator.GenerationContextLocator() { + public Serializable locateGenerationContext( SessionImplementor session, Object incomingObject) { + return session.getEntityPersister( entityBinding.getEntity().getName(), incomingObject ) + .getIdentifier( incomingObject, session ); + } + }; + // TODO: set up IdentifierGenerator for non-assigned sub-attributes + return new CompositeNestedGeneratedValueGenerator( locator ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java new file mode 100644 index 0000000000..ccd484a324 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * @author Steve Ebersole + */ +public class EntityVersion { + private final EntityBinding rootEntityBinding; + private BasicAttributeBinding versioningAttributeBinding; + private String unsavedValue; + + public EntityVersion(EntityBinding rootEntityBinding) { + this.rootEntityBinding = rootEntityBinding; + } + + + public BasicAttributeBinding getVersioningAttributeBinding() { + return versioningAttributeBinding; + } + + public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { + this.versioningAttributeBinding = versioningAttributeBinding; + } + + public String getUnsavedValue() { + return unsavedValue; + } + + public void setUnsavedValue(String unsavedValue) { + this.unsavedValue = unsavedValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java index 31b6d5dbc5..56f144a70f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.Collections; import java.util.Set; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java similarity index 68% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java index 57743a69e4..17cd753f8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,34 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.binding; import org.hibernate.FetchMode; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; /** - * Contract describing sources for attributes which model associations. - * * @author Steve Ebersole */ -public interface AssociationAttributeSource extends AttributeSource { - /** - * Obtain the cascade styles to be applied to this association. - * - * @return The cascade styles. - */ - public Iterable getCascadeStyles(); - - /** - * Obtain the fetch mode to be applied to this association. - * - * @return The fetch mode. - */ +public interface Fetchable { public FetchMode getFetchMode(); public FetchTiming getFetchTiming(); + public void setFetchTiming(FetchTiming fetchTiming); + public FetchStyle getFetchStyle(); + + public void setFetchStyle(FetchStyle fetchStyle); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java index 4914f05da1..9ef4f9c6e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java @@ -21,16 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.internal.FilterConfiguration; /** - * TODO : javadoc - * - * @author Steve Ebersole + * @author Strong Liu */ -public interface PluralAttribute extends Attribute { - public String getRole(); - public PluralAttributeNature getNature(); - public Type getElementType(); - public void setElementType(Type elementType); +public interface Filterable { + public void addFilterConfiguration(FilterConfiguration filterConfiguration); + + public List getFilterConfigurations(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java index 1bd2427d81..7440aacd90 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java @@ -21,11 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; /** * Helper utilities specific to the binding package. @@ -33,7 +32,7 @@ import org.hibernate.metamodel.domain.PluralAttributeNature; * @author Steve Ebersole */ public class Helper { - public static void checkPluralAttributeNature(PluralAttribute attribute, PluralAttributeNature expected) { + public static void checkPluralAttributeNature(PluralAttribute attribute, PluralAttribute.Nature expected) { if ( attribute.getNature() != expected ) { throw new AssertionFailure( String.format( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java index 6629783f50..9bb369f83b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.HashMap; import java.util.Map; @@ -35,11 +35,12 @@ import org.hibernate.type.Type; */ public class HibernateTypeDescriptor { private String explicitTypeName; - private String javaTypeName; - private boolean isToOne; private Map typeParameters = new HashMap( ); + private Type resolvedTypeMapping; + private String javaTypeName; + private boolean isToOne; public String getExplicitTypeName() { return explicitTypeName; @@ -62,22 +63,30 @@ public class HibernateTypeDescriptor { } public void setToOne(boolean toOne) { - isToOne = toOne; + this.isToOne = toOne; } public Map getTypeParameters() { return typeParameters; } - public void setTypeParameters(Map typeParameters) { - this.typeParameters = typeParameters; - } - public Type getResolvedTypeMapping() { return resolvedTypeMapping; } public void setResolvedTypeMapping(Type resolvedTypeMapping) { this.resolvedTypeMapping = resolvedTypeMapping; + if ( getJavaTypeName() == null && resolvedTypeMapping!=null ) { + setJavaTypeName( resolvedTypeMapping.getReturnedClass().getName() ); + setToOne( resolvedTypeMapping.isEntityType() ); + } + } + + public void copyFrom(HibernateTypeDescriptor hibernateTypeDescriptor) { + setJavaTypeName( hibernateTypeDescriptor.getJavaTypeName() ); + setExplicitTypeName( hibernateTypeDescriptor.getExplicitTypeName() ); + setToOne( hibernateTypeDescriptor.isToOne() ); + getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters() ); + setResolvedTypeMapping( hibernateTypeDescriptor.getResolvedTypeMapping() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java similarity index 80% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java index 3b31495472..8c303b2df3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.EntityMode; import org.hibernate.engine.OptimisticLockStyle; @@ -32,16 +32,17 @@ import org.hibernate.engine.OptimisticLockStyle; public class HierarchyDetails { private final EntityBinding rootEntityBinding; private final InheritanceType inheritanceType; + private final TenantDiscrimination tenantDiscrimination; private final EntityMode entityMode; - private final EntityIdentifier entityIdentifier; private EntityDiscriminator entityDiscriminator; private OptimisticLockStyle optimisticLockStyle; - private BasicAttributeBinding versioningAttributeBinding; + private EntityVersion entityVersion; private Caching caching; + private Caching naturalIdCaching; private boolean explicitPolymorphism; @@ -50,6 +51,8 @@ public class HierarchyDetails { this.inheritanceType = inheritanceType; this.entityMode = entityMode; this.entityIdentifier = new EntityIdentifier( rootEntityBinding ); + this.entityVersion = new EntityVersion( rootEntityBinding ); + this.tenantDiscrimination = new TenantDiscrimination(); } public EntityBinding getRootEntityBinding() { @@ -60,6 +63,10 @@ public class HierarchyDetails { return inheritanceType; } + public TenantDiscrimination getTenantDiscrimination() { + return tenantDiscrimination; + } + public EntityMode getEntityMode() { return entityMode; } @@ -84,12 +91,12 @@ public class HierarchyDetails { this.entityDiscriminator = entityDiscriminator; } - public BasicAttributeBinding getVersioningAttributeBinding() { - return versioningAttributeBinding; + public EntityVersion getEntityVersion() { + return entityVersion; } - public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { - this.versioningAttributeBinding = versioningAttributeBinding; + public void setEntityVersion(EntityVersion entityVersion) { + this.entityVersion = entityVersion; } public Caching getCaching() { @@ -100,6 +107,14 @@ public class HierarchyDetails { this.caching = caching; } + public Caching getNaturalIdCaching() { + return naturalIdCaching; + } + + public void setNaturalIdCaching(Caching naturalIdCaching) { + this.naturalIdCaching = naturalIdCaching; + } + public boolean isExplicitPolymorphism() { return explicitPolymorphism; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java new file mode 100644 index 0000000000..a071c40e5b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; + +import org.hibernate.internal.util.collections.CollectionHelper; + +/** + * Identifier generator definition, should be immutable. + * + * @author Emmanuel Bernard + * @author Strong Liu + */ +public class IdentifierGeneratorDefinition implements Serializable { + private final String name; + private final String strategy; + private final Map parameters; + + public IdentifierGeneratorDefinition( + final String name, + final String strategy, + final Map parameters) { + this.name = name; + this.strategy = strategy; + if ( CollectionHelper.isEmpty( parameters ) ) { + this.parameters = Collections.emptyMap(); + } + else { + this.parameters = Collections.unmodifiableMap( parameters ); + } + } + + /** + * @return identifier generator strategy + */ + public String getStrategy() { + return strategy; + } + + /** + * @return generator name + */ + public String getName() { + return name; + } + + /** + * @return generator configuration parameters + */ + public Map getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof IdentifierGeneratorDefinition ) ) { + return false; + } + + IdentifierGeneratorDefinition that = (IdentifierGeneratorDefinition) o; + + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( parameters != null ? !parameters.equals( that.parameters ) : that.parameters != null ) { + return false; + } + if ( strategy != null ? !strategy.equals( that.strategy ) : that.strategy != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( strategy != null ? strategy.hashCode() : 0 ); + result = 31 * result + ( parameters != null ? parameters.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "IdentifierGeneratorDefinition{" + + "name='" + name + '\'' + + ", strategy='" + strategy + '\'' + + ", parameters=" + parameters + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java new file mode 100644 index 0000000000..ae9adcce28 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Specialization of plural attribute binding for indexed collections (maps and lists). + * + * @author Steve Ebersole + */ +public interface IndexedPluralAttributeBinding extends PluralAttributeBinding { + /** + * Retrieve the binding descriptor pertaining to the plural attribute's index value. + * + * @return The index binding descriptor + */ + public PluralAttributeIndexBinding getPluralAttributeIndexBinding(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java index 9bcd4792cd..3d55aff685 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.MappingException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java new file mode 100644 index 0000000000..772d7c6425 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Gail Badner + */ +public class JoinRelationalValueBindingContainer extends RelationalValueBindingContainer { + private final TableSpecification table; + private final ForeignKey foreignKey; + + public JoinRelationalValueBindingContainer( + List relationalValueBindings, + ForeignKey foreignKey) { + super( relationalValueBindings ); + if ( relationalValueBindings.isEmpty() ) { + table = null; + } + else { + table = relationalValueBindings.get( 0 ).getTable(); + for ( int i = 1; i< relationalValueBindings.size(); i++ ) { + if ( !table.equals( relationalValueBindings.get( i ).getTable() ) ) { + throw new AssertionFailure( + String.format( + "Multiple tables found in a %s: %s, %s", + getClass().getName(), + table.getLogicalName(), + relationalValueBindings.get( i ).getTable() + ) + ); + } + } + } + if ( table != null && foreignKey != null && !table.equals( foreignKey.getSourceTable() ) ) { + throw new IllegalStateException( + String.format( + "Unexpected source table for foreign key: %s; expected %s.", + foreignKey.getSourceTable(), + table + ) + ); + } + this.foreignKey = foreignKey; + } + + public TableSpecification getTable() { + return table; + } + + public ForeignKey getForeignKey() { + return foreignKey; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/KeyValueBinding.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/KeyValueBinding.java index cc48595d02..066e6a4b1e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/KeyValueBinding.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; /** * TODO : javadoc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java new file mode 100644 index 0000000000..d278de479c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * + */ +public class ListBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + private final int base; + + public ListBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + int base) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext ); + pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this ); + this.base = base; + } + + public int base() { + return base; + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToAnyPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToAnyPluralAttributeElementBinding.java new file mode 100644 index 0000000000..4920baf428 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToAnyPluralAttributeElementBinding.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#MANY_TO_ANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class ManyToAnyPluralAttributeElementBinding extends AbstractPluralAttributeAssociationElementBinding { + ManyToAnyPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueContainer() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_ANY; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java new file mode 100644 index 0000000000..9c87d8a60f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToManyPluralAttributeElementBinding.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.FetchMode; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.metamodel.spi.relational.ForeignKey; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#MANY_TO_MANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class ManyToManyPluralAttributeElementBinding extends AbstractPluralAttributeAssociationElementBinding implements Filterable{ + private List filterConfigurations = new ArrayList(); + private String manyToManyWhere; + private String manyToManyOrderBy; + private FetchMode fetchMode; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + + ManyToManyPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_MANY; + } + + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer( + relationalValueBindings, + foreignKey + ); + } + + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + + public String getManyToManyWhere() { + return manyToManyWhere; + } + + public void setManyToManyWhere(String manyToManyWhere) { + this.manyToManyWhere = manyToManyWhere; + } + + public String getManyToManyOrderBy() { + return manyToManyOrderBy; + } + + public void setManyToManyOrderBy(String manyToManyOrderBy) { + this.manyToManyOrderBy = manyToManyOrderBy; + } + + + @Override + public FetchMode getFetchMode() { + return fetchMode; + } + + public void setFetchMode(FetchMode fetchMode) { + this.fetchMode = fetchMode; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + return filterConfigurations; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java new file mode 100644 index 0000000000..3689aabd82 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * TODO : javadoc + * + * @author Gail Badner + * @author Steve Ebersole + */ +public class ManyToOneAttributeBinding + extends AbstractSingularAssociationAttributeBinding { + + public ManyToOneAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isNotFoundAnException, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isNotFoundAnException, + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding + ); + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java new file mode 100644 index 0000000000..dd5652438b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java @@ -0,0 +1,92 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * + */ +public class MapBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + + public MapBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + PluralAttributeIndexBinding.Nature pluralAttributeIndexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); + pluralAttributeIndexBinding = createPluralAttributeIndexBinding( pluralAttributeIndexNature ); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } + + private PluralAttributeIndexBinding createPluralAttributeIndexBinding(PluralAttributeIndexBinding.Nature nature) { + switch ( nature ) { + case BASIC: { + return new BasicPluralAttributeIndexBinding( this ); + } + case AGGREGATE: { + return new CompositePluralAttributeIndexBinding( this ); + } + case MANY_TO_MANY: { + throw new NotYetImplementedException( + String.format( "%s index nature is not supported yet.", nature ) + ); + } + case MANY_TO_ANY: { + throw new NotYetImplementedException( + String.format( "%s index nature is not supported yet.", nature ) + ); + } + default: { + throw new AssertionFailure( "Unknown collection index nature : " + nature ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java index 18babda0e3..9930b16bd3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.io.Serializable; import java.util.ArrayList; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToManyPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToManyPluralAttributeElementBinding.java new file mode 100644 index 0000000000..368aba6f54 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToManyPluralAttributeElementBinding.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.FetchMode; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#ONE_TO_MANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class OneToManyPluralAttributeElementBinding extends AbstractPluralAttributeAssociationElementBinding { + private RelationalValueBindingContainer relationalValueBindingContainer; + + OneToManyPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + @Override + public Nature getNature() { + return Nature.ONE_TO_MANY; + } + + public void setElementEntityIdentifier(List relationalValueBindingList) { + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindingList ); + } + + @Override + public FetchMode getFetchMode() { + return FetchMode.JOIN; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java new file mode 100644 index 0000000000..3075388a99 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; + +/** + * TODO : javadoc + * + * @author Gail Badner + */ +public class OneToOneAttributeBinding + extends AbstractSingularAssociationAttributeBinding { + final boolean isConstrained; + + public OneToOneAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + true, //always true + naturalIdMutability, + metaAttributeContext, + referencedEntityBinding, + referencedAttributeBinding + ); + this.isConstrained = isConstrained; + } + + @Override + public boolean isNullable() { + return !isConstrained; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java new file mode 100644 index 0000000000..dd58aa8f64 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Specialization of PluralAttributeElementBinding for elements which are association (entity) values. + * + * @author Steve Ebersole + */ +public interface PluralAttributeAssociationElementBinding + extends PluralAttributeElementBinding, Cascadeable { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java similarity index 64% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java index df48c1e229..68120b6789 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java @@ -21,34 +21,46 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.Comparator; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.relational.TableSpecification; +import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.persister.collection.CollectionPersister; /** + * Describes the binding of a plural attribute. + * * @author Steve Ebersole */ -public interface PluralAttributeBinding extends AssociationAttributeBinding { - // todo : really it is the element (and/or index) that can be associative not the collection itself... - +public interface PluralAttributeBinding extends AttributeBinding, Fetchable, Filterable { + /** + * Retrieve the plural attribute being bound. + * + * @return The plural attribute descriptor + */ @Override public PluralAttribute getAttribute(); - public CollectionKey getCollectionKey(); + /** + * Retrieve the binding information pertaining to the collection (foreign) key. + * + * @return The key binding descriptor + */ + public PluralAttributeKeyBinding getPluralAttributeKeyBinding(); - public AbstractCollectionElement getCollectionElement(); - - public TableSpecification getCollectionTable(); + /** + * Retrieve the binding information pertaining to the collection elements. + * + * @return The element binding descriptor + */ + public PluralAttributeElementBinding getPluralAttributeElementBinding(); public boolean isMutable(); public Caching getCaching(); - public Class getCollectionPersisterClass(); + public Class getExplicitPersisterClass(); public String getCustomLoaderName(); @@ -60,19 +72,17 @@ public interface PluralAttributeBinding extends AssociationAttributeBinding { public CustomSQL getCustomSqlDeleteAll(); - public boolean isOrphanDelete(); - String getWhere(); boolean isSorted(); + boolean hasIndex(); + Comparator getComparator(); int getBatchSize(); - java.util.Map getFilterMap(); - - boolean isInverse(); - String getOrderBy(); + + String getReferencedPropertyName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java new file mode 100644 index 0000000000..42208ef53e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.FetchMode; + + +/** + * Common information pertaining to the binding of the various plural attribute natures (one-to-many, basic, etc). + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementBinding { + /** + * Retrieves the plural attribute binding descriptor whose element binding is described here. + * + * @return The plural attribute binding descriptor. + */ + PluralAttributeBinding getPluralAttributeBinding(); + + /** + * Retrieve the relational aspect of the element binding. Essentially describes the column(s) to which the + * binding maps the elements + * + * @return The relation information. + */ + List getRelationalValueBindings(); + + boolean isNullable(); + + boolean hasDerivedValue(); + + boolean hasNonNullableValue(); + + FetchMode getFetchMode(); + + /** + * Retrieves an enumeration describing the mapping nature of the collection's elements. + * + * @return The nature enum. + */ + Nature getNature(); + + /** + * Retrieve the Hibernate type descriptor describing the mapping-typing of the elements. + * + * @return The element type descriptor. + */ + HibernateTypeDescriptor getHibernateTypeDescriptor(); + + /** + * Describes the nature of plural attribute elements in terms of relational implications. + * + * @author Steve Ebersole + * @author Gail Badner + */ + public static enum Nature { + /** + * The collection elements are basic, simple values. + */ + BASIC( false, false ), + /** + * The collection elements are compositions. + */ + AGGREGATE( false, true ), + /** + * The collection elements represent entity's in a one-to-many association. + */ + ONE_TO_MANY, + /** + * The collection elements represent entity's in a many-to-many association. + */ + MANY_TO_MANY, + /** + * The collection elements represent entity's in a multi-valued ANY mapping. + */ + MANY_TO_ANY; + + private final boolean isAssociation; + private final boolean isCascadeable; + + private Nature() { + this( true, true ); + } + + private Nature(boolean association, boolean cascadeable) { + this.isAssociation = association; + this.isCascadeable = cascadeable; + } + + public boolean isAssociation() { + return isAssociation; + } + + public boolean isCascadeable() { + return isCascadeable; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java new file mode 100644 index 0000000000..68683b8685 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.domain.Type; + +/** + * @author Steve Ebersole + */ +public interface PluralAttributeIndexBinding { + IndexedPluralAttributeBinding getIndexedPluralAttributeBinding(); + + Nature getNature(); + + /** + * Retrieve the relational aspect of the index binding. Essentially describes the + * column(s)/derived value(s) to which the binding maps the indexes. + * + * @return The relational values. + */ + public List getRelationalValueBindings(); + + HibernateTypeDescriptor getHibernateTypeDescriptor(); + + Type getPluralAttributeIndexType(); + + /** + * Describes the nature of plural attribute indexes in terms of relational implications. + * + * @author Steve Ebersole + */ + enum Nature { + /** + * The collection indexes are basic, simple values. This is the only valid nature for lists + */ + BASIC, + /** + * The map key is an aggregated composite + */ + AGGREGATE, + /** + * The map key is an association identified by a column(s) on the collection table. + */ + MANY_TO_MANY, + /** + * The map key is represented by a Hibernate ANY mapping + */ + MANY_TO_ANY + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java new file mode 100644 index 0000000000..2305346692 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java @@ -0,0 +1,151 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Describes the binding information pertaining to the plural attribute foreign key. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeKeyBinding { + private final AbstractPluralAttributeBinding pluralAttributeBinding; + private final SingularAttributeBinding referencedAttributeBinding; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + private boolean inverse; + + // this knowledge can be implicitly resolved based on the typing information on the referenced owner attribute + private HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + +// todo : this would be nice to have but we do not always know it, especially in HBM case. +// private BasicAttributeBinding otherSide; + + + public PluralAttributeKeyBinding( + AbstractPluralAttributeBinding pluralAttributeBinding, + SingularAttributeBinding referencedAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + this.referencedAttributeBinding = referencedAttributeBinding; + } + + /** + * Identifies the plural attribute binding whose foreign key this class is describing. + * + * @return The plural attribute whose foreign key is being described + */ + public AbstractPluralAttributeBinding getPluralAttributeBinding() { + return pluralAttributeBinding; + } + + public SingularAttributeBinding getReferencedAttributeBinding() { + return referencedAttributeBinding; + } + + public TableSpecification getCollectionTable() { + return relationalValueBindingContainer.getTable(); + } + + /** + * Is the plural attribute considered inverse? + *

+ * NOTE: The "inverse-ness" of a plural attribute logically applies to it key. + * + * @return {@code true} indicates the plural attribute is inverse; {@code false} indicates is not. + */ + public boolean isInverse() { + return inverse; + } + + public void setInverse(boolean inverse) { + this.inverse = inverse; + } + + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + public void setHibernateTypeDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { + this.hibernateTypeDescriptor = hibernateTypeDescriptor; + } + + public List getRelationalValueBindings() { + return relationalValueBindingContainer.relationalValueBindings(); + } + + public List getValues() { + return relationalValueBindingContainer.values(); + } + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." ); + } + if ( this.relationalValueBindingContainer != null ) { + throw new AssertionFailure( "Relational value bindings have already initialized" ); + } + this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer( + relationalValueBindings, + foreignKey + ); + if ( this.relationalValueBindingContainer.hasDerivedValue() ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + } + + public boolean isCascadeDeleteEnabled() { + return relationalValueBindingContainer.getForeignKey().getDeleteRule() == ForeignKey.ReferentialAction.CASCADE; + } + + public boolean isNullable() { + // cannot be nullable if the foreign key source columns are included in the primary key + // TODO: move this into RelationalValueBindingContainer. + if ( getCollectionTable().getPrimaryKey().getColumns().containsAll( relationalValueBindingContainer.columns() ) ) { + return false; + } + return relationalValueBindingContainer.hasNullableRelationalValueBinding(); + } + + public boolean isInsertable() { + return relationalValueBindingContainer.hasInsertableRelationalValueBinding(); + } + + public boolean isUpdatable() { + return relationalValueBindingContainer.hasUpdateableRelationalValueBinding(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java new file mode 100644 index 0000000000..7365c8f023 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Represents the binding information of a column/formula. + * + * Different from a {@link Value} because, while the {@link Value} exists only once in the relational model, + * that {@link Value} may be bound to multiple attributes. A {@link RelationalValueBinding} then tracks the + * information that is specific to each attribute's binding to that {@link Value}. + * + * @author Steve Ebersole + */ +public class RelationalValueBinding { + private final TableSpecification table; + private final Value value; + private final boolean includeInInsert; + private final boolean includeInUpdate; + private final boolean isDerived; + + public RelationalValueBinding(final TableSpecification table, final DerivedValue value) { + this.table = table; + this.value = value; + this.includeInInsert = false; + this.includeInUpdate = false; + this.isDerived = true; + } + + public RelationalValueBinding(final TableSpecification table, final Column value, final boolean includeInInsert, final boolean includeInUpdate) { + this.table = table; + this.value = value; + this.includeInInsert = includeInInsert; + this.includeInUpdate = includeInUpdate; + this.isDerived = false; + } + + public TableSpecification getTable() { + return table; + } + + /** + * Retrieve the relational value bound here. + * + * @return The relational value. + */ + public Value getValue() { + return value; + } + + /** + * Is the value bound here derived? Same as checking {@link #getValue()} as a {@link DerivedValue} + * + * @return {@code true} indicates the bound value is derived. + */ + public boolean isDerived() { + return isDerived; + } + + /** + * Is the value bound here nullable? + * + * @return {@code true} indicates the bound value is derived or a column not marked as non-null. + */ + public boolean isNullable() { + return isDerived() || ( (Column) value ).isNullable(); + } + + /** + * Is the value to be inserted as part of its binding here? + * + * @return {@code true} indicates the value should be included; {@code false} indicates it should not + */ + public boolean isIncludeInInsert() { + return includeInInsert; + } + + /** + * Is the value to be updated as part of its binding here? + * + * @return {@code true} indicates the value should be included; {@code false} indicates it should not + */ + public boolean isIncludeInUpdate() { + return includeInUpdate; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java new file mode 100644 index 0000000000..907fc6770c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + */ +public class RelationalValueBindingContainer { + private final List relationalValueBindings; + private final boolean isListModifiable; + + public RelationalValueBindingContainer(List relationalValueBindings) { + this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings ); + this.isListModifiable = false; + } + + public RelationalValueBindingContainer() { + this.relationalValueBindings = new ArrayList(); + this.isListModifiable = true; + } + + public List relationalValueBindings() { + return isListModifiable ? + Collections.unmodifiableList( relationalValueBindings ) : + relationalValueBindings; + } + + public List values() { + final List values = new ArrayList( relationalValueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + values.add( relationalValueBinding.getValue() ); + } + return values; + } + + public List columns() { + final List columns = new ArrayList( relationalValueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( !relationalValueBinding.isDerived() ) { + columns.add( (Column) relationalValueBinding.getValue() ); + } + } + return columns; + } + + void addRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + if ( !isListModifiable ) { + throw new IllegalStateException( "Cannot add relationalValueBindings because this object is unmodifiable." ); + } + relationalValueBindings.addAll( relationalValueBindingContainer.relationalValueBindings ); + } + + public boolean hasDerivedValue() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if (relationalValueBinding.isDerived() ) { + return true; + } + } + return false; + } + + public boolean hasNullableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isNullable() ) { + return true; + } + } + return false; + } + + public boolean hasNonNullableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( !relationalValueBinding.isNullable() ) { + return true; + } + } + return false; + } + + public boolean hasInsertableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isIncludeInInsert() ) { + return true; + } + } + return false; + } + + public boolean hasUpdateableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isIncludeInUpdate() ) { + return true; + } + } + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java new file mode 100644 index 0000000000..deeaeeb209 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Steve Ebersole + */ +public class SecondaryTable { + private final TableSpecification secondaryTableReference; + private final ForeignKey foreignKeyReference; + private FetchStyle fetchStyle = FetchStyle.JOIN; + private boolean isInverse = false; + private boolean isOptional = true; + private boolean isCascadeDeleteEnabled; + private CustomSQL customInsert; + private CustomSQL customUpdate; + private CustomSQL customDelete; + + public SecondaryTable(TableSpecification secondaryTableReference, ForeignKey foreignKeyReference) { + this.secondaryTableReference = secondaryTableReference; + this.foreignKeyReference = foreignKeyReference; + } + + public TableSpecification getSecondaryTableReference() { + return secondaryTableReference; + } + + public ForeignKey getForeignKeyReference() { + return foreignKeyReference; + } + + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + public void setFetchStyle(FetchStyle fetchStyle) { + this.fetchStyle = fetchStyle; + } + + public boolean isInverse() { + return isInverse; + } + + public void setInverse(boolean isInverse) { + this.isInverse = isInverse; + } + + public boolean isOptional() { + return isOptional; + } + + public void setOptional(boolean isOptional) { + this.isOptional = isOptional; + } + + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + public void setCascadeDeleteEnabled(boolean isCascadeDeleteEnabled) { + this.isCascadeDeleteEnabled = isCascadeDeleteEnabled; + } + public boolean isLazy() { + // TODO: need to check attribute bindings using this table + return false; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public void setCustomDelete(CustomSQL customDelete) { + this.customDelete = customDelete; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public void setCustomInsert(CustomSQL customInsert) { + this.customInsert = customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public void setCustomUpdate(CustomSQL customUpdate) { + this.customUpdate = customUpdate; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java similarity index 65% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java index 98a0b05d02..1eee42cb76 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java @@ -21,30 +21,32 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import java.util.Comparator; - -import org.hibernate.metamodel.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * @author Steve Ebersole */ public class SetBinding extends AbstractPluralAttributeBinding { - private Comparator comparator; - protected SetBinding( + public SetBinding( AttributeBindingContainer container, PluralAttribute attribute, - CollectionElementNature collectionElementNature) { - super( container, attribute, collectionElementNature ); - } - - public Comparator getComparator() { - return comparator; - } - - public void setComparator(Comparator comparator) { - this.comparator = comparator; + PluralAttributeElementBinding.Nature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext + ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java similarity index 66% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java index eb1e60c88d..c685f82824 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java @@ -21,7 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; /** * Contract describing the attribute binding for singular associations ({@code many-to-one}, {@code one-to-one}). @@ -30,16 +33,7 @@ package org.hibernate.metamodel.binding; * @author Steve Ebersole */ @SuppressWarnings( {"JavaDoc", "UnusedDeclaration"}) -public interface SingularAssociationAttributeBinding extends SingularAttributeBinding, AssociationAttributeBinding { - /** - * Is this association based on a property reference (non PK column(s) as target of FK)? - *

- * Convenience form of checking {@link #getReferencedAttributeName()} for {@code null}. - * - * @return - */ - public boolean isPropertyReference(); - +public interface SingularAssociationAttributeBinding extends SingularAttributeBinding, Cascadeable, Fetchable { /** * Obtain the name of the referenced entity. * @@ -47,19 +41,13 @@ public interface SingularAssociationAttributeBinding extends SingularAttributeBi */ public String getReferencedEntityName(); - /** - * Set the name of the - * @param referencedEntityName - */ - public void setReferencedEntityName(String referencedEntityName); - - public String getReferencedAttributeName(); - public void setReferencedAttributeName(String referencedAttributeName); - - - // "resolvable" - public void resolveReference(AttributeBinding attributeBinding); - public boolean isReferenceResolved(); public EntityBinding getReferencedEntityBinding(); - public AttributeBinding getReferencedAttributeBinding(); -} + + public SingularAttributeBinding getReferencedAttributeBinding(); + + public boolean isNotFoundAnException(); + + public TableSpecification getTable(); + + public ForeignKey getForeignKey(); +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java new file mode 100644 index 0000000000..fa0d4f230f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Specialized binding contract for singular (non-collection) attributes + * + * @author Steve Ebersole + */ +public interface SingularAttributeBinding extends AttributeBinding { + + @Override + public SingularAttribute getAttribute(); + + public List getRelationalValueBindings(); + + public List getValues(); + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are derived values + * (formula mappings). + * + * @return {@code true} indicates that the binding contains a derived value; {@code false} indicates it does not. + */ + public boolean hasDerivedValue(); + + /** + * Convenience method to determine if all {@link RelationalValueBinding simple value bindings} allow nulls. + * + * @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not. + */ + public boolean isNullable(); + + /** + * Convenience method to determine if all tables (primary and secondary) involved with this attribute + * binding are optional. + * + * @return true, if all tables involved with this attribute are optional; false, otherwise. + */ + public boolean isOptional(); + + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are inserted. + * + * @return {@code true} indicates that at least one value is inserted; {@code false} indicates none are inserted. + */ + public boolean isIncludedInInsert(); + + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} can be updated. + * + * @return {@code true} indicates that at least one value can be updated; {@code false} indicates none can + * be updated. + */ + public boolean isIncludedInUpdate(); + + /** + * Convenience method to determine if this attribute is an natural id and if it is, then returns its mutability. + * + * @return The {@link NaturalIdMutability} linked with this attribute, + * {@code NaturalIdMutability#NOT_NATURAL_ID} indicates this is NOT a natural id attribute. + */ + public NaturalIdMutability getNaturalIdMutability(); + + public void setAlternateUniqueKey(boolean alternateUniqueKey); + + public enum NaturalIdMutability { + MUTABLE, + IMMUTABLE, + NOT_NATURAL_ID + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java index 115f67aef9..f8c29d086b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,12 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.binding; /** * @author Steve Ebersole */ -public interface Orderable { - public boolean isOrdered(); - public String getOrder(); +public interface SingularNonAssociationAttributeBinding extends SingularAttributeBinding { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java new file mode 100644 index 0000000000..2c9f8cf1b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public class TenantDiscrimination { + private Value discriminatorValue; + private boolean isShared = false; + private boolean useParameterBinding = true; + + public Value getDiscriminatorValue() { + return discriminatorValue; + } + + public void setDiscriminatorValue(Value discriminatorValue) { + this.discriminatorValue = discriminatorValue; + } + + public boolean isShared() { + return isShared; + } + + public void setShared(boolean shared) { + isShared = shared; + } + + public boolean isUseParameterBinding() { + return useParameterBinding; + } + + public void setUseParameterBinding(boolean useParameterBinding) { + this.useParameterBinding = useParameterBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java new file mode 100644 index 0000000000..6a509b674d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; + +/** + * Describes custom type definitions supplied by the user as part of the metadata. + * + * @author John Verhaeg + */ +public class TypeDefinition implements Serializable { + private final String name; + private final Class typeImplementorClass; + private final String[] registrationKeys; + private final Map parameters; + + public TypeDefinition( + String name, + Class typeImplementorClass, + String[] registrationKeys, + Map parameters) { + this.name = name; + this.typeImplementorClass = typeImplementorClass; + this.registrationKeys= registrationKeys; + this.parameters = parameters == null ? Collections.emptyMap() : Collections.unmodifiableMap( + parameters + ); + } + + public String getName() { + return name; + } + + public Class getTypeImplementorClass() { + return typeImplementorClass; + } + + public String[] getRegistrationKeys() { + return registrationKeys; + } + + public Map getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof TypeDefinition ) ) { + return false; + } + + TypeDefinition that = (TypeDefinition) o; + + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( parameters != null ? !parameters.equals( that.parameters ) : that.parameters != null ) { + return false; + } + if ( !Arrays.equals( registrationKeys, that.registrationKeys ) ) { + return false; + } + if ( typeImplementorClass != null ? !typeImplementorClass.equals( that.typeImplementorClass ) : that.typeImplementorClass != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( typeImplementorClass != null ? typeImplementorClass.hashCode() : 0 ); + result = 31 * result + ( registrationKeys != null ? Arrays.hashCode( registrationKeys ) : 0 ); + result = 31 * result + ( parameters != null ? parameters.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "TypeDefinition{" + + "name='" + name + '\'' + + ", typeImplementorClass=" + typeImplementorClass + + ", registrationKeys=" + Arrays.toString( registrationKeys ) + + ", parameters=" + parameters + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java similarity index 76% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java index 3258f7de70..a03946ba18 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java @@ -21,14 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Set; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.ValueHolder; @@ -44,6 +43,7 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, private final String className; private final ValueHolder> classReference; private final Hierarchical superType; + private LinkedHashSet attributeSet = new LinkedHashSet(); private HashMap attributeMap = new HashMap(); @@ -100,83 +100,35 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, } @Override - public SingularAttribute createSingularAttribute(String name) { - SingularAttribute attribute = new SingularAttributeImpl( name, this ); - addAttribute( attribute ); - return attribute; - } - - @Override - public SingularAttribute createVirtualSingularAttribute(String name) { - throw new NotYetImplementedException(); - } - - @Override - public SingularAttribute locateComponentAttribute(String name) { + public SingularAttribute locateCompositeAttribute(String name) { return (SingularAttributeImpl) locateAttribute( name ); } - @Override - public SingularAttribute createComponentAttribute(String name, Component component) { - SingularAttributeImpl attribute = new SingularAttributeImpl( name, this ); - attribute.resolveType( component ); - addAttribute( attribute ); - return attribute; - } - @Override public PluralAttribute locatePluralAttribute(String name) { return (PluralAttribute) locateAttribute( name ); } - protected PluralAttribute createPluralAttribute(String name, PluralAttributeNature nature) { - PluralAttribute attribute = nature.isIndexed() - ? new IndexedPluralAttributeImpl( name, nature, this ) - : new PluralAttributeImpl( name, nature, this ); - addAttribute( attribute ); - return attribute; - } - @Override public PluralAttribute locateBag(String name) { return locatePluralAttribute( name ); } - @Override - public PluralAttribute createBag(String name) { - return createPluralAttribute( name, PluralAttributeNature.BAG ); - } - @Override public PluralAttribute locateSet(String name) { return locatePluralAttribute( name ); } - @Override - public PluralAttribute createSet(String name) { - return createPluralAttribute( name, PluralAttributeNature.SET ); - } - @Override public IndexedPluralAttribute locateList(String name) { return (IndexedPluralAttribute) locatePluralAttribute( name ); } - @Override - public IndexedPluralAttribute createList(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST ); - } - @Override public IndexedPluralAttribute locateMap(String name) { return (IndexedPluralAttribute) locatePluralAttribute( name ); } - @Override - public IndexedPluralAttribute createMap(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP ); - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -187,8 +139,71 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, return sb.toString(); } + + @Override + public SingularAttribute createSyntheticSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, true ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical type) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, true ); + attribute.resolveType( type ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, false ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createCompositeAttribute(String name, Aggregate composite) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, false ); + attribute.resolveType( composite ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createBag(String name) { + return createPluralAttribute( name, PluralAttribute.Nature.BAG ); + } + + protected PluralAttribute createPluralAttribute(String name, PluralAttribute.Nature nature) { + PluralAttribute attribute = nature.isIndexable() + ? new IndexedPluralAttributeImpl( this, name, nature ) + : new PluralAttributeImpl( this, name, nature ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createSet(String name) { + return createPluralAttribute( name, PluralAttribute.Nature.SET ); + } + + @Override + public IndexedPluralAttribute createList(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttribute.Nature.LIST ); + } + + @Override + public IndexedPluralAttribute createArray(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttribute.Nature.ARRAY ); + } + + @Override + public IndexedPluralAttribute createMap(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttribute.Nature.MAP ); + } + protected void addAttribute(Attribute attribute) { - // todo : how to best "secure" this? if ( attributeMap.put( attribute.getName(), attribute ) != null ) { throw new IllegalArgumentException( "Attribute with name [" + attribute.getName() + "] already registered" ); } @@ -200,11 +215,13 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public static class SingularAttributeImpl implements SingularAttribute { private final AttributeContainer attributeContainer; private final String name; + private final boolean synthetic; private Type type; - public SingularAttributeImpl(String name, AttributeContainer attributeContainer) { - this.name = name; + public SingularAttributeImpl(AttributeContainer attributeContainer, String name, boolean synthetic) { this.attributeContainer = attributeContainer; + this.name = name; + this.synthetic = synthetic; } public boolean isTypeResolved() { @@ -237,19 +254,24 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public boolean isSingular() { return true; } + + @Override + public boolean isSynthetic() { + return synthetic; + } } public static class PluralAttributeImpl implements PluralAttribute { private final AttributeContainer attributeContainer; - private final PluralAttributeNature nature; + private final Nature nature; private final String name; private Type elementType; - public PluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { + public PluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, Nature nature) { + this.attributeContainer = attributeContainer; this.name = name; this.nature = nature; - this.attributeContainer = attributeContainer; } @Override @@ -263,7 +285,13 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, } @Override - public PluralAttributeNature getNature() { + public boolean isSynthetic() { + // don't think there are ever any synthetic plural attributes created... + return false; + } + + @Override + public Nature getNature() { return nature; } @@ -291,8 +319,8 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute { private Type indexType; - public IndexedPluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { - super( name, nature, attributeContainer ); + public IndexedPluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, Nature nature) { + super( attributeContainer, name, nature ); } @Override @@ -305,4 +333,4 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, this.indexType = indexType; } } -} +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java index e300355a43..c5dfe4c970 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java @@ -21,19 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; /** - * Models the notion of a component (what JPA calls an Embeddable). + * Models the notion of an aggregated composite (what JPA calls an Embeddable). *

- * NOTE : Components are not currently really hierarchical. But that is a feature I want to add. + * NOTE : Composites are not currently really hierarchical. But that is a feature I want to add. * * @author Steve Ebersole */ -public class Component extends AbstractAttributeContainer { - public Component(String name, String className, ValueHolder> classReference, Hierarchical superType) { +public class Aggregate extends AbstractAttributeContainer { + public Aggregate(String name, String className, ValueHolder> classReference, Hierarchical superType) { super( name, className, classReference, superType ); } @@ -43,14 +43,14 @@ public class Component extends AbstractAttributeContainer { } @Override - public boolean isComponent() { + public boolean isAggregate() { return true; } @Override public String getRoleBaseName() { // todo : this is not really completely accurate atm - // the role base here should really be the role of the component attribute. + // the role base here should really be the role of the aggregated composite attribute. return getClassName(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java index c58bd8778f..5c3930b845 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Describes an attribute. @@ -37,7 +37,7 @@ public interface Attribute { public String getName(); /** - * Retrieve the declaring container for this attribute (entity/component). + * Retrieve the declaring container for this attribute (entity or aggregated composite). * * @return The attribute container. */ @@ -52,4 +52,13 @@ public interface Attribute { * @return True if attribute is singular; false if plural. */ public boolean isSingular(); + + /** + * Synthetic attributes do not really exist in the users domain classes. Hibernate sometimes generates these + * synthetic attributes for various reasons. Some parts of the code base use the phrase "virtual" as well. + * + * @return {@code true} indicates this attribute is synthetic; {@code false} indicates it is non-synthetic + * (an actual attribute). + */ + public boolean isSynthetic(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java index 6024c758e4..b512852e50 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import java.util.Set; /** * Basic contract for any container holding attributes. This allows polymorphic handling of both - * components and entities in terms of the attributes they hold. + * aggregated composites and entities in terms of the attributes they hold. * * @author Steve Ebersole */ @@ -42,6 +42,13 @@ public interface AttributeContainer extends Type { */ public String getRoleBaseName(); + /** + * Retrieve the attributes contained in this container. + * + * @return The contained attributes + */ + public Set attributes(); + /** * Retrieve an attribute by name. * @@ -50,33 +57,22 @@ public interface AttributeContainer extends Type { * @return The attribute matching the given name, or null. */ public Attribute locateAttribute(String name); - - /** - * Retrieve the attributes contained in this container. - * - * @return The contained attributes - */ - public Set attributes(); - public SingularAttribute locateSingularAttribute(String name); - public SingularAttribute createSingularAttribute(String name); - public SingularAttribute createVirtualSingularAttribute(String name); - - public SingularAttribute locateComponentAttribute(String name); - public SingularAttribute createComponentAttribute(String name, Component component); - + public SingularAttribute locateCompositeAttribute(String name); public PluralAttribute locatePluralAttribute(String name); - public PluralAttribute locateBag(String name); - public PluralAttribute createBag(String name); - public PluralAttribute locateSet(String name); - public PluralAttribute createSet(String name); - public IndexedPluralAttribute locateList(String name); - public IndexedPluralAttribute createList(String name); - public IndexedPluralAttribute locateMap(String name); - public IndexedPluralAttribute createMap(String name); + public SingularAttribute createSingularAttribute(String name); + public SingularAttribute createCompositeAttribute(String name, Aggregate composite); + public PluralAttribute createBag(String name); + public PluralAttribute createSet(String name); + public IndexedPluralAttribute createList(String name); + public IndexedPluralAttribute createMap(String name); + public IndexedPluralAttribute createArray(String name); + + public SingularAttribute createSyntheticSingularAttribute(String name); + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical container); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java index 682ce46afd..baf24ebbd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; @@ -65,7 +65,7 @@ public class BasicType implements Type { } @Override - public boolean isComponent() { + public boolean isAggregate() { return false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java index fc6b41f6a3..3980d5973c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; @@ -50,7 +50,7 @@ public class Entity extends AbstractAttributeContainer { } @Override - public boolean isComponent() { + public boolean isAggregate() { return false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java index fd587b0a1f..29eb0ba000 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Additional contract for things that can occur in an inheritance hierarchy (specifically ones we would diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java index 5a15664925..aea4f1f859 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * TODO : javadoc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaType.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaType.java index 1b89606989..aa7821c242 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.util.ValueHolder; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/NonEntity.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/NonEntity.java index 973dc8af6e..7915e097a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/NonEntity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; @@ -49,7 +49,7 @@ public class NonEntity extends AbstractAttributeContainer { } @Override - public boolean isComponent() { + public boolean isAggregate() { return false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java new file mode 100644 index 0000000000..4cbe368d4b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public interface PluralAttribute extends Attribute { + public String getRole(); + public Nature getNature(); + public Type getElementType(); + public void setElementType(Type elementType); + + /** + * Identifies the specific semantic of a plural valued attribute. + * + * @author Steve Ebersole + */ + enum Nature { + ARRAY( "array", Object[].class ), + BAG( "bag", Collection.class ), + IDBAG( "idbag", Collection.class ), + SET( "set", Set.class ), + LIST( "list", List.class ), + MAP( "map", Map.class ); + + private final String name; + private final Class javaContract; + private final boolean indexable; + + Nature(String name, Class javaContract) { + this.name = name; + this.javaContract = javaContract; + this.indexable = Map.class.isAssignableFrom( javaContract ) + || List.class.isAssignableFrom( javaContract ) + || javaContract.isArray(); + } + + public String getName() { + return name; + } + + public Class getJavaContract() { + return javaContract; + } + + public boolean isIndexable() { + return indexable; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java index f27b61fced..2ee54b86cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * A single valued (non-collection) attribute diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Superclass.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Superclass.java index 4a5a095339..24b44186ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Superclass.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; @@ -49,7 +49,7 @@ public class Superclass extends AbstractAttributeContainer { } @Override - public boolean isComponent() { + public boolean isAggregate() { return false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java index 58d0f9592a..e5d53c5aeb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import org.hibernate.internal.util.ValueHolder; @@ -60,5 +60,11 @@ public interface Type { public boolean isAssociation(); - public boolean isComponent(); + /** + * Is this attribute an aggregated composite (what JPA calls an Embeddable)? + * + * @return true, if this attribute is an aggregated composite; + * false, otherwise. + */ + public boolean isAggregate(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java index 09350d2a80..21ce86494e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java @@ -21,16 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Describes the type of a type :/ * + * todo: this is not currently used; is it needed? + * * @author Steve Ebersole */ public enum TypeNature { BASIC( "basic" ), - COMPONENT( "component" ), + AGGREGATE( "aggregate" ), ENTITY( "entity" ), SUPERCLASS( "superclass" ), NON_ENTITY( "non-entity" ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/package.html similarity index 100% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/package.html rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/package.html diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java index 8b2b58c0a6..7ea0f5421b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.HashSet; import java.util.Set; @@ -46,9 +46,15 @@ public abstract class AbstractAuxiliaryDatabaseObject implements AuxiliaryDataba private static final AtomicInteger counter = new AtomicInteger( 0 ); private final String exportIdentifier; private final Set dialectScopes; + private boolean beforeTablesOnCreation; protected AbstractAuxiliaryDatabaseObject(Set dialectScopes) { + this( dialectScopes, false ); + } + + protected AbstractAuxiliaryDatabaseObject(Set dialectScopes, boolean beforeTablesOnCreation) { this.dialectScopes = dialectScopes == null ? new HashSet() : dialectScopes; + this.beforeTablesOnCreation = beforeTablesOnCreation; this.exportIdentifier = new StringBuilder( EXPORT_IDENTIFIER_PREFIX ) .append( '.' ) @@ -73,4 +79,9 @@ public abstract class AbstractAuxiliaryDatabaseObject implements AuxiliaryDataba public String getExportIdentifier() { return exportIdentifier; } + + @Override + public boolean beforeTablesOnCreation() { + return beforeTablesOnCreation; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java new file mode 100644 index 0000000000..4737c9dd6a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java @@ -0,0 +1,193 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; + +/** + * Support for writing {@link Constraint} implementations + * + * @todo do we need to support defining these on particular schemas/catalogs? + * + * @author Steve Ebersole + * @author Gail Badner + * @author Brett Meyer + */ +public abstract class AbstractConstraint implements Constraint { + private TableSpecification table; + private String name; + private final Map columnMap = new LinkedHashMap(); + private final Map columnOrderMap = new HashMap(); + + protected AbstractConstraint(TableSpecification table, String name) { + this.table = table; + this.name = name; + } + + @Override + public TableSpecification getTable() { + return table; + } + + public void setTable( TableSpecification table ) { + this.table = table; + } + + /** + * Returns the constraint name, or null if the name has not been set. + * + * @return the constraint name, or null if the name has not been set + */ + public String getName() { + return name; + } + + /** + * Sets a constraint name that is unique across + * all database objects. + * + * @param name - the unique constraint name; must be non-null. + * + * @throws IllegalArgumentException if name is null. + * @throws IllegalStateException if this constraint already has a non-null name. + */ + public void setName(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "name must be non-null." ); + } + if ( this.name != null ) { + throw new IllegalStateException( + String.format( + "This constraint already has a name (%s) and cannot be renamed to (%s).", + this.name, + name + ) + ); + } + this.name = name; + } + + protected int generateConstraintColumnListId() { + return table.generateColumnListId( getColumns() ); + } + + public List getColumns() { + return Collections.unmodifiableList( new ArrayList( columnMap.values() ) ); + } + + public int getColumnSpan() { + return columnMap.size(); + } + + public boolean hasColumn(Column column) { + return columnMap.containsKey( column.getColumnName() ); + } + + public boolean hasColumn(String columnName) { + for ( Identifier key : columnMap.keySet() ) { + if ( key.getText().equals( columnName ) ) return true; + } + return false; + } + + protected Map internalColumnAccess() { + return columnMap; + } + + public void addColumn(Column column) { + internalAddColumn( column ); + } + + protected void internalAddColumn(Column column) { +// if ( column.getTable() != getTable() ) { +// throw new AssertionFailure( +// String.format( +// "Unable to add column to constraint; tables [%s, %s] did not match", +// column.getTable().toLoggableString(), +// getTable().toLoggableString() +// ) +// ); +// } + columnMap.put( column.getColumnName(), column ); + } + + public void addColumn(Column column, String order) { + addColumn( column ); + if ( StringHelper.isNotEmpty( order ) ) { + columnOrderMap.put( column, order ); + } + } + + public boolean hasOrdering(Column column) { + return columnOrderMap.containsKey( column ); + } + + public String getOrdering(Column column) { + return columnOrderMap.get( column ); + } + + protected boolean isCreationVetoed(Dialect dialect) { + return false; + } + + protected abstract String sqlConstraintStringInAlterTable(Dialect dialect); + + public String[] sqlDropStrings(Dialect dialect) { + if ( isCreationVetoed( dialect ) ) { + return null; + } + else { + return new String[] { + new StringBuilder() + .append( "alter table " ) + .append( getTable().getQualifiedName( dialect ) ) + .append( " drop constraint " ) + .append( dialect.quote( name ) ) + .toString() + }; + } + } + + public String[] sqlCreateStrings(Dialect dialect) { + if ( isCreationVetoed( dialect ) ) { + return null; + } + else { + return new String[] { + new StringBuilder( "alter table " ) + .append( getTable().getQualifiedName( dialect ) ) + .append( sqlConstraintStringInAlterTable( dialect ) ) + .toString() + }; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java new file mode 100644 index 0000000000..e7176097db --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java @@ -0,0 +1,226 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * Convenience base class for implementing the {@link ValueContainer} contract centralizing commonality + * between modeling tables, views and inline views. + * + * @author Steve Ebersole + * @author Brett Meyer + */ +public abstract class AbstractTableSpecification implements TableSpecification { + + // A column an derived value can have the same text, so use the Value.ValueType to disambiguate. + private class ValueKey { + private final Value.ValueType valueType; + private final Identifier identifier; + + private ValueKey(Value.ValueType valueType, Identifier identifier) { + this.valueType = valueType; + this.identifier = identifier; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + ValueKey valueKey = (ValueKey) o; + + if ( identifier != null ? !identifier.equals( valueKey.identifier ) : valueKey.identifier != null ) { + return false; + } + return valueType == valueKey.valueType; + + } + + @Override + public int hashCode() { + int result = valueType != null ? valueType.hashCode() : 0; + result = 31 * result + ( identifier != null ? identifier.hashCode() : 0 ); + return result; + } + } + private int tableNumber; + + private final List valueList = new ArrayList(); + private final LinkedHashMap valueMap = new LinkedHashMap(); + + private final PrimaryKey primaryKey = new PrimaryKey( this ); + private final List foreignKeys = new ArrayList(); + + @Override + public int getTableNumber() { + return tableNumber; + } + + public void setTableNumber( int tableNumber ) { + // This must be done outside of Table, rather than statically, to ensure + // deterministic alias names. See HHH-2448. + this.tableNumber = tableNumber; + } + + @Override + public List values() { + return Collections.unmodifiableList( valueList ); + } + + @Override + public Column locateOrCreateColumn(String name) { + Column column = locateColumn( name ); + if(column == null){ + column = createColumn( name ); + } + return column; + } + + @Override + public Column locateColumn(String name) { + final Identifier identifier = Identifier.toIdentifier( name ); + final ValueKey valueKey = new ValueKey( Value.ValueType.COLUMN, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); + return Column.class.isInstance( value ) ? Column.class.cast( value ) : null; + } + return null; + } + + @Override + public boolean hasValue(Value value) { + return valueMap.containsValue( value ); + } + + @Override + public Column createColumn(String name) { + return createColumn( Identifier.toIdentifier( name ) ); + } + + @Override + public Column createColumn(Identifier name) { + final Column column = new Column( valueList.size(), name ); + valueMap.put( new ValueKey( column.getValueType(), name ), column ); + valueList.add( column ); + return column; + } + + @Override + public DerivedValue locateOrCreateDerivedValue(String fragment) { + DerivedValue value = locateDerivedValue( fragment ); + return value != null ? value : createDerivedValue( fragment ); + } + + protected DerivedValue locateDerivedValue(String fragment) { + final Identifier identifier = Identifier.toIdentifier( fragment ); + final ValueKey valueKey = new ValueKey( Value.ValueType.DERIVED_VALUE, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); + if ( DerivedValue.class.isInstance( value ) ) { + return DerivedValue.class.cast( value ); + } + } + return null; + } + + protected DerivedValue createDerivedValue(String fragment) { + final Identifier identifier = Identifier.toIdentifier( fragment ); + final DerivedValue value = new DerivedValue( valueList.size(), fragment ); + valueMap.put( new ValueKey( value.getValueType(), identifier ), value ); + valueList.add( value ); + return value; + } + + @Override + public Iterable getForeignKeys() { + return foreignKeys; + } + + @Override + public ForeignKey createForeignKey(TableSpecification targetTable, String name) { + ForeignKey fk = new ForeignKey( this, targetTable, name ); + foreignKeys.add( fk ); + return fk; + } + + @Override + public ForeignKey locateForeignKey(String name) { + return locateConstraint( foreignKeys, name ); + } + + protected T locateConstraint(Iterable constraints, String name) { + if ( name == null ) { + throw new IllegalArgumentException( "name must be non-null." ); + } + for ( T constraint : constraints ) { + if ( name.equals( constraint.getName() ) ) { + return constraint; + } + } + return null; + } + + @Override + public Iterable locateForeignKey(TableSpecification targetTable) { + List result = null; + for ( ForeignKey fk : foreignKeys ) { + if ( fk.getTargetTable().equals( targetTable ) ) { + if ( result == null ) { + result = new ArrayList(); + } + result.add( fk ); + } + } + return result; + } + + + @Override + public PrimaryKey getPrimaryKey() { + return primaryKey; + } + @Override + public int generateColumnListId(Iterable columns) { + int result = getLogicalName().hashCode(); + for ( Column column : columns ) { + sameTableCheck( column ); + result = 31 * result + column.getColumnName().hashCode(); + } + return result; + } + + private void sameTableCheck(Column column) { + if ( ! hasValue( column ) ) { + throw new IllegalArgumentException( "All columns must be from this table." ); + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java index 8bec29682f..db5e20f021 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -21,58 +21,50 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import org.jboss.logging.Logger; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.metamodel.ValidationException; -import org.jboss.logging.Logger; - /** - * Basic support for {@link SimpleValue} implementations. + * Basic support for {@link Value} implementations. * * @author Steve Ebersole */ -public abstract class AbstractSimpleValue implements SimpleValue { +public abstract class AbstractValue implements Value { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractSimpleValue.class.getName()); + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractValue.class.getName()); - private final TableSpecification table; private final int position; - private Datatype datatype; + private JdbcDataType jdbcDataType; - protected AbstractSimpleValue(TableSpecification table, int position) { - this.table = table; + protected AbstractValue(int position) { this.position = position; } - @Override - public TableSpecification getTable() { - return table; - } - public int getPosition() { return position; } @Override - public Datatype getDatatype() { - return datatype; + public JdbcDataType getJdbcDataType() { + return jdbcDataType; } - @Override - public void setDatatype(Datatype datatype) { - LOG.debugf( "setting datatype for column %s : %s", toLoggableString(), datatype ); - if ( this.datatype != null && ! this.datatype.equals( datatype ) ) { - LOG.debugf( "overriding previous datatype : %s", this.datatype ); + public void setJdbcDataType(JdbcDataType jdbcDataType) { + LOG.debugf( "setting jdbcDataType for column %s : %s", toLoggableString(), jdbcDataType ); + if ( this.jdbcDataType != null && ! this.jdbcDataType.equals( jdbcDataType ) ) { + LOG.debugf( "overriding previous jdbcDataType : %s", this.jdbcDataType ); } - this.datatype = datatype; + this.jdbcDataType = jdbcDataType; } @Override public void validateJdbcTypes(JdbcCodes typeCodes) { // todo : better compatibility testing... - if ( datatype.getTypeCode() != typeCodes.nextJdbcCde() ) { + if ( jdbcDataType.getTypeCode() != typeCodes.nextJdbcCde() ) { throw new ValidationException( "Mismatched types" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java new file mode 100644 index 0000000000..fde238dba0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.io.Serializable; + +import org.hibernate.dialect.Dialect; + +/** + * Auxiliary database objects (i.e., triggers, stored procedures, etc) defined + * in the mappings. Allows Hibernate to manage their lifecycle as part of + * creating/dropping the schema. + * + * @author Steve Ebersole + */ +public interface AuxiliaryDatabaseObject extends Exportable, Serializable { + /** + * Does this database object apply to the given dialect? + * + * @param dialect The dialect to check against. + * @return True if this database object does apply to the given dialect. + */ + public boolean appliesToDialect(Dialect dialect); + + /** + * Defines a simple precedence. Should creation of this auxiliary object happen before creation of + * tables? If {@code true}, the auxiliary object creation will happen after any explicit schema creations + * but before table/sequence creations; if {@code false}, the auxiliary object creation will happen after + * explicit schema creations and after table/sequence creations. + * + * This precedence is automatically inverted for dropping. + * + * @return {@code true} indicates this object should be created before tables; {@code false} indicates + * it should be created after. + */ + public boolean beforeTablesOnCreation(); + + /** + * Gets the SQL strings for creating the database object. + * + * @param dialect The dialect for which to generate the SQL creation strings + * + * @return the SQL strings for creating the database object. + */ + public String[] sqlCreateStrings(Dialect dialect); + + /** + * Gets the SQL strings for dropping the database object. + * + * @param dialect The dialect for which to generate the SQL drop strings + * + * @return the SQL strings for dropping the database object. + */ + public String[] sqlDropStrings(Dialect dialect); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java index 07389d08ca..834f87d975 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.Set; @@ -35,6 +35,7 @@ import org.hibernate.internal.util.StringHelper; public class BasicAuxiliaryDatabaseObjectImpl extends AbstractAuxiliaryDatabaseObject { private static final String CATALOG_NAME_PLACEHOLDER = "${catalog}"; private static final String SCHEMA_NAME_PLACEHOLDER = "${schema}"; + private final Schema defaultSchema; private final String createString; private final String dropString; @@ -63,8 +64,8 @@ public class BasicAuxiliaryDatabaseObjectImpl extends AbstractAuxiliaryDatabaseO } private static String injectCatalogAndSchema(String ddlString, Schema schema) { - String rtn = StringHelper.replace( ddlString, CATALOG_NAME_PLACEHOLDER, schema.getName().getCatalog().getName() ); - rtn = StringHelper.replace( rtn, SCHEMA_NAME_PLACEHOLDER, schema.getName().getSchema().getName() ); + String rtn = StringHelper.replace( ddlString, CATALOG_NAME_PLACEHOLDER, schema.getName().getCatalog().getText() ); + rtn = StringHelper.replace( rtn, SCHEMA_NAME_PLACEHOLDER, schema.getName().getSchema().getText() ); return rtn; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java index 52c0a5c129..885d3439f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; /** * TODO : javadoc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java new file mode 100644 index 0000000000..bf6df8cdd4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java @@ -0,0 +1,240 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.function.SQLFunctionRegistry; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.sql.Template; + +/** + * Models a physical column + * + * @author Gavin King + * @author Steve Ebersole + */ +public class Column extends AbstractValue { + private final Identifier columnName; + private boolean nullable = true; + + private String defaultValue; + private String checkCondition; + private String sqlType; + + private String readFragment; + private String writeFragment; + + private String comment; + + private Size size = new Size(); + + private boolean isIdentity = false; + + protected Column(int position, Identifier name) { + super( position ); + this.columnName = name; + } + + public Identifier getColumnName() { + return columnName; + } + + public boolean isNullable() { + return nullable; + } + + public void setNullable(boolean nullable) { + this.nullable = nullable; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getCheckCondition() { + return checkCondition; + } + + public void setCheckCondition(String checkCondition) { + this.checkCondition = checkCondition; + } + + public String getSqlType() { + return sqlType; + } + + public void setSqlType(String sqlType) { + this.sqlType = sqlType; + } + + // TODO: Solely used by schema tools. Re-think this, getSqlType, and getJdbcDataType. Clean-up and/or + // condense somehow? + public String getSqlTypeString(Dialect dialect) { + if ( sqlType != null ) { + return sqlType; + } + else { + return dialect.getTypeName( + getJdbcDataType().getTypeCode(), + size.getLength(), + size.getPrecision(), + size.getScale() + ); + } + } + + public String getReadFragment() { + return readFragment; + } + + public void setReadFragment(String readFragment) { + this.readFragment = readFragment; + } + + public String getWriteFragment() { + return writeFragment; + } + + public void setWriteFragment(String writeFragment) { + this.writeFragment = writeFragment; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getTemplate(Dialect dialect, SQLFunctionRegistry functionRegistry) { + return hasCustomRead() + ? Template.renderWhereStringTemplate( readFragment, dialect, functionRegistry ) + : Template.TEMPLATE + '.' + getColumnName().getText( dialect ); + } + + public boolean hasCustomRead() { + return StringHelper.isNotEmpty( readFragment ); + } + + public String getReadExpr(Dialect dialect) { + return hasCustomRead() ? readFragment : getColumnName().getText( dialect ); + } + + public String getWriteExpr() { + return StringHelper.isNotEmpty( writeFragment ) ? writeFragment : "?"; + } + + + public Size getSize() { + return size; + } + + public void setSize(Size size) { + this.size = size; + } + + /** + * Returns true if this column is an identity column. + * @return true, if this column is an identity column; false, otherwise. + */ + public boolean isIdentity() { + return isIdentity; + } + + /** + * Indicate if this column is an identity column. + * @param isIdentity - true, if this column is an identity column; false, otherwise. + */ + public void setIdentity(boolean isIdentity) { + this.isIdentity = isIdentity; + } + + @Override + public ValueType getValueType() { + return ValueType.COLUMN; + } + + @Override + public String toLoggableString() { + return getColumnName().getText(); + } + + @Override + public String getAlias(Dialect dialect, TableSpecification tableSpecification) { + if ( tableSpecification == null ) { + // see HHH-7547 -- protect against ambiguity + throw new IllegalArgumentException("To ensure uniqueness, tableSpecification must not be null"); + } + + final int lastLetter = StringHelper.lastIndexOfLetter( columnName.getText() ); + final String colPositionSuffix = String.valueOf( getPosition() ) + '_'; + final String tableNumberSuffix = String.valueOf( tableSpecification.getTableNumber() ) + "_"; + final String suffix = colPositionSuffix + tableNumberSuffix; + + String alias; + if ( lastLetter == -1 ) { + alias = "column" ; + } + else if ( columnName.getText().length() > lastLetter + 1 ) { + alias = columnName.getText().substring( 0, lastLetter + 1 ); + } + else { + alias = columnName.getText(); + } + + if ( alias.length() + suffix.length() > dialect.getMaxAliasLength() ) { + alias = alias.substring( 0, dialect.getMaxAliasLength() - suffix.length() ); + } + + return alias + suffix; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + Column column = (Column) o; + + if ( columnName != null ? !columnName.equals( column.columnName ) : column.columnName != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return columnName != null ? columnName.hashCode() : 0; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java similarity index 86% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java index 5587ebcbd6..8b71dc693e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import java.util.List; /** * Basic contract for the types of constraints we fully support as metadata constructs:

    @@ -48,9 +50,9 @@ public interface Constraint extends Exportable { public String getName(); /** - * Obtain the columns that are part of this constraint. + * Obtain a read-only view of the columns that are part of this constraint. * - * @return The constrained columns. + * @return A read-only view of the constrained columns. */ - public Iterable getColumns(); + public List getColumns(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java new file mode 100644 index 0000000000..81d04a9958 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.Metadata; + +/** + * Represents a database and manages the named schema/catalog pairs defined within. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class Database { + private final Schema.Name implicitSchemaName; + private final JdbcEnvironment jdbcEnvironment; + + private final Map schemaMap = new HashMap(); + private final List auxiliaryDatabaseObjects = new ArrayList(); + private final List initCommands = new ArrayList(); + + public Database(Metadata.Options options, JdbcEnvironment jdbcEnvironment) { + String schemaName = options.getDefaultSchemaName(); + String catalogName = options.getDefaultCatalogName(); + if ( options.isGloballyQuotedIdentifiers() ) { + schemaName = StringHelper.quote( schemaName ); + catalogName = StringHelper.quote( catalogName ); + } + this.implicitSchemaName = new Schema.Name( catalogName, schemaName ); + makeSchema( implicitSchemaName ); + this.jdbcEnvironment = jdbcEnvironment; + } + + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + public Iterable getSchemas() { + return schemaMap.values(); + } + + public Schema getDefaultSchema() { + return schemaMap.get( implicitSchemaName ); + } + + public Schema locateSchema(Schema.Name name) { + if ( name.getSchema() == null && name.getCatalog() == null ) { + return getDefaultSchema(); + } + Schema schema = schemaMap.get( name ); + if ( schema == null ) { + schema = makeSchema( name ); + } + return schema; + } + + public Schema getSchemaFor(ObjectName objectName) { + return getSchema( objectName.getCatalog(), objectName.getSchema() ); + } + + private Schema makeSchema(Schema.Name name) { + Schema schema; + schema = new Schema( name ); + schemaMap.put( name, schema ); + return schema; + } + + public Schema getSchema(Identifier catalog, Identifier schema) { + return locateSchema( new Schema.Name( catalog, schema ) ); + } + + public Schema getSchema(String catalog, String schema) { + return locateSchema( new Schema.Name( Identifier.toIdentifier( catalog ), Identifier.toIdentifier( schema ) ) ); + } + + public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) { + if ( auxiliaryDatabaseObject == null ) { + throw new IllegalArgumentException( "Auxiliary database object is null." ); + } + auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject ); + } + + public Iterable getAuxiliaryDatabaseObjects() { + return auxiliaryDatabaseObjects; + } + + public void addInitCommand(InitCommand initCommand) { + initCommands.add( initCommand ); + } + + public Iterable getInitCommands() { + return initCommands; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java new file mode 100644 index 0000000000..f7dede09bd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java @@ -0,0 +1,128 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Strong Liu + */ +public class DenormalizedTable extends Table { + private final Table includedTable; + + public DenormalizedTable(Schema database, Identifier logicalName, Identifier physicalName, Table includedTable) { + super( database, logicalName, physicalName ); + this.includedTable = includedTable; + this.includedTable.setHasDenormalizedTables( true ); + } + + @Override + public List values() { + List values = new ArrayList( super.values().size() + includedTable.values().size() ); + values.addAll( super.values() ); + values.addAll( includedTable.values() ); + return Collections.unmodifiableList( values ); + } + + @Override + public Column locateColumn(String name) { + Column column = includedTable.locateColumn( name ); + if(column!=null){ + return column; + } + return super.locateColumn( name ); + } + + @Override + public boolean hasValue(Value value) { + return includedTable.hasValue( value ) || super.hasValue( value ); + } + + @Override + protected DerivedValue locateDerivedValue(String fragment) { + DerivedValue value = includedTable.locateDerivedValue( fragment ); + return value != null ? value : super.locateDerivedValue( fragment ); + } + //todo other constraints other than fk + //we have to copy all FKs defined in the parent table to this sub table, can this be doing only once? like using ValueHolder? + @Override + public Iterable getForeignKeys() { + copyFKsFromParentTable(); + return super.getForeignKeys(); + } + private Set alreadyCopiedNonNameParentFK = new HashSet( ); + private void copyFKsFromParentTable() { + Iterable fksInSuperTable = includedTable.getForeignKeys(); + final String fkNamePostfix = Integer.toHexString( getTableName().hashCode() ); + for ( ForeignKey fk : fksInSuperTable ) { + + String name = fk.getName(); + if ( name == null ) { + if(!alreadyCopiedNonNameParentFK.contains( fk )){ + copyFK( fk, name ); + alreadyCopiedNonNameParentFK.add( fk ); + } + } + else { + String fkName = name + fkNamePostfix; + ForeignKey copiedFK = super.locateForeignKey( fkName ); + if ( copiedFK == null ) { + copyFK( fk, fkName ); + } + } + } + } + + private void copyFK(ForeignKey fk, String fkName) { + ForeignKey copiedFK = createForeignKey( fk.getTargetTable(), fkName ); + copiedFK.setDeleteRule( fk.getDeleteRule() ); + copiedFK.setUpdateRule( fk.getUpdateRule() ); + Iterable columnMappings = fk.getColumnMappings(); + for ( ForeignKey.ColumnMapping cm : columnMappings ) { + copiedFK.addColumnMapping( cm.getSourceColumn(), cm.getTargetColumn() ); + } + } + + @Override + public Iterable locateForeignKey(TableSpecification targetTable) { + Iterable fks = includedTable.locateForeignKey( targetTable ); + return fks != null ? fks : super.locateForeignKey( targetTable ); + } + + @Override + protected T locateConstraint(Iterable constraints, String name) { + T t = includedTable.locateConstraint( constraints, name ); + return t != null ? t : super.locateConstraint( constraints, name ); + } + + @Override + public PrimaryKey getPrimaryKey() { + return includedTable.getPrimaryKey(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java index 2f39332ac7..c743958fd8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; @@ -30,21 +30,31 @@ import org.hibernate.dialect.Dialect; * * @author Steve Ebersole */ -public class DerivedValue extends AbstractSimpleValue { +public class DerivedValue extends AbstractValue { private final String expression; - public DerivedValue(TableSpecification table, int position, String expression) { - super( table, position ); + public DerivedValue(int position, String expression) { + super( position ); this.expression = expression; } @Override - public String toLoggableString() { - return getTable().toLoggableString() + ".{derived-column}"; + public ValueType getValueType() { + return ValueType.DERIVED_VALUE; } + /** + * {@inheritDoc} + */ + public String toLoggableString() { + return "{derived-column}"; + } + + /** + * {@inheritDoc} + */ @Override - public String getAlias(Dialect dialect) { + public String getAlias(Dialect dialect, TableSpecification tableSpecification) { return "formula" + Integer.toString( getPosition() ) + '_'; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java index 7d720c2322..6ed7d95bd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java @@ -21,14 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; +package org.hibernate.metamodel.spi.relational; /** * Contract for entities (in the ERD sense) which can be exported via {@code CREATE}, {@code ALTER}, etc * * @author Steve Ebersole + * + * @see org.hibernate.tool.schema.spi.Exporter */ public interface Exportable { /** @@ -37,23 +37,4 @@ public interface Exportable { * @return The exporting identifier. */ public String getExportIdentifier(); - - /** - * Gets the SQL strings for creating the database object. - * - * @param dialect The dialect for which to generate the SQL creation strings - * - * @return the SQL strings for creating the database object. - */ - public String[] sqlCreateStrings(Dialect dialect); - - /** - * Gets the SQL strings for dropping the database object. - * - * @param dialect The dialect for which to generate the SQL drop strings - * - * @return the SQL strings for dropping the database object. - */ - public String[] sqlDropStrings(Dialect dialect); - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java index 099fb5110c..ff193c6115 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,17 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.domain.PluralAttribute; +package org.hibernate.metamodel.spi.relational; /** - * TODO : javadoc + * Identifies metamodel objects that can produce {@link Exportable} relational stuff. * * @author Steve Ebersole */ -public class BagBinding extends AbstractPluralAttributeBinding { - protected BagBinding(AttributeBindingContainer container, PluralAttribute attribute, CollectionElementNature nature) { - super( container, attribute, nature ); - } +public interface ExportableProducer { + /** + * Register the contained exportable things to the {@link Database} + * + * @param database The database instance + */ + public void registerExportables(Database database); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java index bcb8c84510..44f35afdc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java @@ -21,16 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; - import org.jboss.logging.Logger; /** @@ -41,8 +41,10 @@ import org.jboss.logging.Logger; * * @author Gavin King * @author Steve Ebersole + * @author Brett Meyer */ -public class ForeignKey extends AbstractConstraint implements Constraint, Exportable { +public class ForeignKey extends AbstractConstraint { + private static final Logger LOG = Logger.getLogger( ForeignKey.class ); private static final String ON_DELETE = " on delete "; @@ -56,6 +58,9 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name) { super( sourceTable, name ); + if ( targetTable == null ) { + throw new IllegalArgumentException( "targetTable must be non-null." ); + } this.targetTable = targetTable; } @@ -71,14 +76,18 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export return targetTable; } - public Iterable getSourceColumns() { + public List getSourceColumns() { return getColumns(); } - public Iterable getTargetColumns() { + public List getTargetColumns() { return targetColumns == null ? getTargetTable().getPrimaryKey().getColumns() - : targetColumns; + : Collections.unmodifiableList( targetColumns ); + } + + protected int generateConstraintColumnListId() { + return 31 * super.generateConstraintColumnListId() + targetTable.generateColumnListId( getTargetColumns() ); } @Override @@ -115,22 +124,17 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export } private void checkTargetTable(Column targetColumn) { - if ( targetColumn.getTable() != getTargetTable() ) { + if ( !getTargetTable().hasValue( targetColumn ) ) { throw new AssertionFailure( String.format( - "Unable to add column to constraint; tables [%s, %s] did not match", - targetColumn.getTable().toLoggableString(), + "Unable to add column to constraint; target column [%s] is not in target table [%s]", + targetColumn.toLoggableString(), getTargetTable().toLoggableString() ) ); } } - @Override - public String getExportIdentifier() { - return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); - } - public ReferentialAction getDeleteRule() { return deleteRule; } @@ -149,12 +153,17 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export @Override public String[] sqlDropStrings(Dialect dialect) { - return new String[] { - "alter table " + - getTable().getQualifiedName( dialect ) + - dialect.getDropForeignKeyString() + - getName() - }; + final StringBuilder buf = new StringBuilder( "alter table " ); + buf.append( getTable().getQualifiedName( dialect ) ); + buf.append( dialect.getDropForeignKeyString() ); + if ( dialect.supportsIfExistsBeforeConstraintName() ) { + buf.append( "if exists " ); + } + buf.append( getName() ); + if ( dialect.supportsIfExistsAfterConstraintName() ) { + buf.append( " if exists" ); + } + return new String[] { buf.toString() }; } public String sqlConstraintStringInAlterTable(Dialect dialect) { @@ -166,8 +175,8 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export if ( ! itTargetColumn.hasNext() ) { throw new MappingException( "More constraint columns that foreign key target columns." ); } - columnNames[i] = column.getColumnName().encloseInQuotesIfQuoted( dialect ); - targetColumnNames[i] = ( itTargetColumn.next() ).getColumnName().encloseInQuotesIfQuoted( dialect ); + columnNames[i] = column.getColumnName().getText( dialect ); + targetColumnNames[i] = ( itTargetColumn.next() ).getColumnName().getText( dialect ); i++; } if ( itTargetColumn.hasNext() ) { @@ -180,7 +189,8 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export columnNames, targetTable.getQualifiedName( dialect ), targetColumnNames, - this.targetColumns == null + this.targetColumns == null || + this.targetColumns.equals( targetTable.getPrimaryKey().getColumns() ) ) ); // TODO: If a dialect does not support cascade-delete, can it support other actions? (HHH-6428) @@ -213,4 +223,42 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export return actionString; } } + + public class ColumnMapping { + private final int position; + + public ColumnMapping(int position) { + this.position = position; + } + + public Column getSourceColumn() { + return getColumns().get( position ); + } + + public Column getTargetColumn() { + return getTargetColumns().get( position ); + } + } + + public boolean referencesPrimaryKey() { + return targetColumns == null + || targetColumns.equals( targetTable.getPrimaryKey().getColumns() ); + } + + public Iterable getColumnMappings() { + final List targetColumns = getTargetColumns(); + if ( getColumns().size() != targetColumns.size() ) { + // todo : this needs to be an error, though not sure the best type yet + } + final List columnMappingList = new ArrayList(); + for ( int i = 0; i < getColumns().size(); i++ ) { + columnMappingList.add( new ColumnMapping( i ) ); + } + return columnMappingList; + } + + @Override + public String getExportIdentifier() { + return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java index 3cd04f9479..b66ff016ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; @@ -33,58 +33,76 @@ import org.hibernate.internal.util.StringHelper; * @author Steve Ebersole */ public class Identifier { - private final String name; + private final String text; private final boolean isQuoted; /** * Means to generate an {@link Identifier} instance from its simple name * - * @param name The name + * @param text The text * * @return The identifier form of the name. */ - public static Identifier toIdentifier(String name) { - if ( StringHelper.isEmpty( name ) ) { + public static Identifier toIdentifier(String text) { + if ( StringHelper.isEmpty( text ) ) { return null; } - final String trimmedName = name.trim(); - if ( isQuoted( trimmedName ) ) { - final String bareName = trimmedName.substring( 1, trimmedName.length() - 1 ); + final String trimmed = text.trim(); + if ( isQuoted( trimmed ) ) { + final String bareName = trimmed.substring( 1, trimmed.length() - 1 ); return new Identifier( bareName, true ); } else { - return new Identifier( trimmedName, false ); + return new Identifier( trimmed, false ); } } - public static boolean isQuoted(String name) { - return name.startsWith( "`" ) && name.endsWith( "`" ); + /** + * Means to generate an {@link Identifier} instance from its simple name + * + * @param text The name + * + * @return The identifier form of the name. + */ + public static Identifier toIdentifier(String text, boolean quote) { + if ( StringHelper.isEmpty( text ) ) { + return null; + } + final String trimmed = text.trim(); + if ( isQuoted( trimmed ) ) { + final String bareName = trimmed.substring( 1, trimmed.length() - 1 ); + return new Identifier( bareName, true ); + } + else { + return new Identifier( trimmed, quote ); + } + } + + public static boolean isQuoted(String text) { + return text.startsWith( "`" ) && text.endsWith( "`" ); } /** * Constructs an identifier instance. * - * @param name The identifier text. + * private access. Use one of the static {@link #toIdentifier} forms instead to get a reference. + * + * @param text The identifier text. * @param quoted Is this a quoted identifier? */ - public Identifier(String name, boolean quoted) { - if ( StringHelper.isEmpty( name ) ) { + private Identifier(String text, boolean quoted) { + if ( StringHelper.isEmpty( text ) ) { throw new IllegalIdentifierException( "Identifier text cannot be null" ); } - if ( isQuoted( name ) ) { + if ( isQuoted( text ) ) { throw new IllegalIdentifierException( "Identifier text should not contain quote markers (`)" ); } - this.name = name; + this.text = text; this.isQuoted = quoted; } - /** - * Get the identifiers name (text) - * - * @return The name - */ - public String getName() { - return name; + public boolean isEmpty() { + return text.equals( "" ); } /** @@ -96,6 +114,23 @@ public class Identifier { return isQuoted; } + /** + * Get the identifier text + * + * @return The text + */ + public String getText() { + return text; + } + + /** + * @deprecated Use {@link #getText} instead + */ + @Deprecated + public String getName() { + return text; + } + /** * If this is a quoted identifier, then return the identifier name * enclosed in dialect-specific open- and end-quotes; otherwise, @@ -105,21 +140,31 @@ public class Identifier { * @return if quoted, identifier name enclosed in dialect-specific open- and end-quotes; otherwise, the * identifier name. */ - public String encloseInQuotesIfQuoted(Dialect dialect) { + public String getText(Dialect dialect) { + return getText( dialect.openQuote(), dialect.closeQuote() ); + } + + /** + * If this is a quoted identifier, then return the identifier name + * enclosed in dialect-specific open- and end-quotes; otherwise, + * simply return the identifier name. + * + * @param openQuote The character to use as start quote + * @param closeQuote The character to use as end quote + * @return if quoted, identifier name enclosed in dialect-specific open- and end-quotes; otherwise, the + * identifier name. + */ + public String getText(char openQuote, char closeQuote) { return isQuoted ? - new StringBuilder( name.length() + 2 ) - .append( dialect.openQuote() ) - .append( name ) - .append( dialect.closeQuote() ) - .toString() : - name; + String.valueOf( openQuote ) + text + closeQuote : + text; } @Override public String toString() { return isQuoted - ? '`' + getName() + '`' - : getName(); + ? '`' + getText() + '`' + : getText(); } @Override @@ -134,11 +179,11 @@ public class Identifier { Identifier that = (Identifier) o; return isQuoted == that.isQuoted - && name.equals( that.name ); + && isQuoted ? text.equals( that.text ) : text.equalsIgnoreCase( that.text ); } @Override public int hashCode() { - return name.hashCode(); + return isQuoted ? text.hashCode() : text.toUpperCase().hashCode(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java index 80ccba8ecc..e904ffd61d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java index 23651e8d82..adc0aeee13 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.Collections; @@ -36,10 +36,10 @@ import org.hibernate.dialect.Dialect; */ public class InLineView extends AbstractTableSpecification { private final Schema schema; - private final String logicalName; + private final Identifier logicalName; private final String select; - public InLineView(Schema schema, String logicalName, String select) { + public InLineView(Schema schema, Identifier logicalName, String select) { this.schema = schema; this.logicalName = logicalName; this.select = select; @@ -49,13 +49,18 @@ public class InLineView extends AbstractTableSpecification { return schema; } + @Override + public Identifier getLogicalName() { + return logicalName; + } + public String getSelect() { return select; } @Override public String getLoggableValueQualifier() { - return logicalName; + return logicalName.getText(); } @Override @@ -64,7 +69,7 @@ public class InLineView extends AbstractTableSpecification { } @Override - public Index getOrCreateIndex(String name) { + public void addIndex(Index index) { throw new UnsupportedOperationException( "Cannot create index on inline view" ); } @@ -74,10 +79,15 @@ public class InLineView extends AbstractTableSpecification { } @Override - public UniqueKey getOrCreateUniqueKey(String name) { + public void addUniqueKey(UniqueKey uk) { throw new UnsupportedOperationException( "Cannot create unique-key on inline view" ); } + @Override + public boolean hasUniqueKey(Column column) { + return false; + } + @Override public Iterable getCheckConstraints() { return Collections.emptyList(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java similarity index 51% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java index 2eb119c914..b88649de39 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java @@ -21,10 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; /** * Models a SQL INDEX @@ -32,74 +31,17 @@ import org.hibernate.internal.util.StringHelper; * @author Gavin King * @author Steve Ebersole */ -public class Index extends AbstractConstraint implements Constraint { +public class Index extends AbstractConstraint { + + public Index() { + this( null, null ); + } + protected Index(Table table, String name) { super( table, name ); } - - + @Override - public String getExportIdentifier() { - StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier()); - sb.append( ".IDX" ); - for ( Column column : getColumns() ) { - sb.append( '_' ).append( column.getColumnName().getName() ); - } - return sb.toString(); - } - - public String[] sqlCreateStrings(Dialect dialect) { - return new String[] { - buildSqlCreateIndexString( - dialect, getName(), getTable(), getColumns(), false - ) - }; - } - - public static String buildSqlCreateIndexString( - Dialect dialect, - String name, - TableSpecification table, - Iterable columns, - boolean unique - ) { - StringBuilder buf = new StringBuilder( "create" ) - .append( unique ? - " unique" : - "" ) - .append( " index " ) - .append( dialect.qualifyIndexName() ? - name : - StringHelper.unqualify( name ) ) - .append( " on " ) - .append( table.getQualifiedName( dialect ) ) - .append( " (" ); - boolean first = true; - for ( Column column : columns ) { - if ( first ) { - first = false; - } - else { - buf.append( ", " ); - } - buf.append( ( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ) ); - } - buf.append( ")" ); - return buf.toString(); - } - - public static String buildSqlDropIndexString( - Dialect dialect, - TableSpecification table, - String name - ) { - return "drop index " + - StringHelper.qualify( - table.getQualifiedName( dialect ), - name - ); - } - public String sqlConstraintStringInAlterTable(Dialect dialect) { StringBuilder buf = new StringBuilder( " index (" ); boolean first = true; @@ -110,20 +52,22 @@ public class Index extends AbstractConstraint implements Constraint { else { buf.append( ", " ); } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); + buf.append( column.getColumnName().getText( dialect ) ); + if ( hasOrdering( column ) ) { + buf.append( " " ).append( getOrdering( column ) ); + } } return buf.append( ')' ).toString(); } - - public String[] sqlDropStrings(Dialect dialect) { - return new String[] { - new StringBuilder( "drop index " ) - .append( - StringHelper.qualify( - getTable().getQualifiedName( dialect ), - getName() - ) - ).toString() - }; + + @Override + public String getExportIdentifier() { + StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); + sb.append( ".IDX" ); + sb.append( '_' ).append( getName() ); + for ( Column column : getColumns() ) { + sb.append( '_' ).append( column.getColumnName().getText() ); + } + return sb.toString(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java new file mode 100644 index 0000000000..320c2675f7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +/** + * A general SQL command. + * + * @author Steve Ebersole + */ +public class InitCommand { + private final String[] initCommands; + + public InitCommand(String... initCommands) { + this.initCommands = initCommands; + } + + public String[] getInitCommands() { + return initCommands; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java index f0f5189b6d..7421fe9f82 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java @@ -21,29 +21,37 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; /** - * Models a JDBC {@link java.sql.Types DATATYPE} + * Models a JDBC {@link java.sql.Types DATATYPE}. Mainly breaks down into 3 pieces of information:
      + *
    • + * {@link #getTypeCode() type code} - The JDBC type code; generally matches a code from {@link java.sql.Types} + * though not necessarily. + *
    • + *
    • + * {@link #getTypeName() type name} - The database type name for the given type code. + *
    • + *
    • + * {@link #getJavaType()} java type} - The java type recommended for representing this JDBC type (if known) + *
    • + *
    * - * @todo Do we somehow link this in with {@link org.hibernate.internal.util.jdbc.TypeInfo} ? + * @todo Would love to link this in with {@link org.hibernate.engine.jdbc.internal.TypeInfo} * * @author Steve Ebersole */ -public class Datatype { +public class JdbcDataType { private final int typeCode; private final String typeName; private final Class javaType; private final int hashCode; - public Datatype(int typeCode, String typeName, Class javaType) { + public JdbcDataType(int typeCode, String typeName, Class javaType) { this.typeCode = typeCode; this.typeName = typeName; this.javaType = javaType; - this.hashCode = generateHashCode(); - } - private int generateHashCode() { int result = typeCode; if ( typeName != null ) { result = 31 * result + typeName.hashCode(); @@ -51,8 +59,8 @@ public class Datatype { if ( javaType != null ) { result = 31 * result + javaType.hashCode(); } - return result; - } + this.hashCode = result; + } public int getTypeCode() { return typeCode; @@ -66,6 +74,11 @@ public class Datatype { return javaType; } + @Override + public int hashCode() { + return hashCode; + } + @Override public boolean equals(Object o) { if ( this == o ) { @@ -75,19 +88,14 @@ public class Datatype { return false; } - Datatype datatype = (Datatype) o; + JdbcDataType jdbcDataType = (JdbcDataType) o; - return typeCode == datatype.typeCode - && javaType.equals( datatype.javaType ) - && typeName.equals( datatype.typeName ); + return typeCode == jdbcDataType.typeCode + && javaType.equals( jdbcDataType.javaType ) + && typeName.equals( jdbcDataType.typeName ); } - @Override - public int hashCode() { - return hashCode; - } - @Override public String toString() { return super.toString() + "[code=" + typeCode + ", name=" + typeName + ", javaClass=" + javaType.getName() + "]"; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java index b49008d244..8f61c8fb08 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; /** * Marker for things which can be logged. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java index b27b73ac27..8b9feb7593 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java @@ -21,10 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; /** * Models the qualified name of a database object. @@ -36,27 +37,57 @@ import org.hibernate.dialect.Dialect; * @author Steve Ebersole */ public class ObjectName { - // todo - should depend on DatabaseMetaData. For now hard coded (HF) - private static String SEPARATOR = "."; - - private final Identifier schema; private final Identifier catalog; + private final Identifier schema; private final Identifier name; private final String identifier; private final int hashCode; /** - * Tries to create an {@code ObjectName} from a name. + * Tries to create an {@code ObjectName} from a name. This form explicitly looks for the form + * {@code catalog.schema.name}. If you need db specific parsing use + * {@link org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport#parseName} instead * - * @param objectName simple or qualified name of the database object. + * @param text simple or qualified name of the database object. */ - public ObjectName(String objectName) { - this( - extractSchema( objectName ), - extractCatalog( objectName ), - extractName( objectName ) - ); + public static ObjectName parse(String text) { + if ( text == null ) { + throw new IllegalIdentifierException( "Object name must be specified" ); + } + + String schemaName = null; + String catalogName = null; + String localObjectName; + + boolean wasQuoted = false; + if ( text.startsWith( "`" ) && text.endsWith( "`" ) ) { + wasQuoted = true; + text = StringHelper.unquote( text ); + } + + final String[] tokens = text.split( "." ); + if ( tokens.length == 0 || tokens.length == 1 ) { + // we have just a local name... + localObjectName = text; + } + else if ( tokens.length == 2 ) { + schemaName = tokens[0]; + localObjectName = tokens[1]; + } + else if ( tokens.length == 3 ) { + schemaName = tokens[0]; + catalogName = tokens[1]; + localObjectName = tokens[2]; + } + else { + throw new HibernateException( "Unable to parse object name: " + text ); + } + + final Identifier schema = Identifier.toIdentifier( schemaName, wasQuoted ); + final Identifier catalog = Identifier.toIdentifier( catalogName, wasQuoted ); + final Identifier object = Identifier.toIdentifier( localObjectName, wasQuoted ); + return new ObjectName( catalog, schema, object ); } public ObjectName(Identifier name) { @@ -64,17 +95,21 @@ public class ObjectName { } public ObjectName(Schema schema, String name) { - this( schema.getName().getSchema(), schema.getName().getCatalog(), Identifier.toIdentifier( name ) ); + this( schema.getName().getCatalog(), schema.getName().getSchema(), Identifier.toIdentifier( name ) ); } public ObjectName(Schema schema, Identifier name) { - this( schema.getName().getSchema(), schema.getName().getCatalog(), name ); + this( schema.getName().getCatalog(), schema.getName().getSchema(), name ); } - public ObjectName(String schemaName, String catalogName, String name) { + public ObjectName(Schema.Name schemaName, Identifier name) { + this( schemaName.getCatalog(), schemaName.getSchema(), name ); + } + + public ObjectName(String catalogName, String schemaName, String name) { this( - Identifier.toIdentifier( schemaName ), Identifier.toIdentifier( catalogName ), + Identifier.toIdentifier( schemaName ), Identifier.toIdentifier( name ) ); } @@ -82,22 +117,22 @@ public class ObjectName { /** * Creates a qualified name reference. * - * @param schema The in which the object is defined (optional) * @param catalog The catalog in which the object is defined (optional) + * @param schema The in which the object is defined (optional) * @param name The name (required) */ - public ObjectName(Identifier schema, Identifier catalog, Identifier name) { + public ObjectName(Identifier catalog, Identifier schema, Identifier name) { if ( name == null ) { // Identifier cannot be constructed with an 'empty' name throw new IllegalIdentifierException( "Object name must be specified" ); } - this.name = name; - this.schema = schema; this.catalog = catalog; + this.schema = schema; + this.name = name; this.identifier = qualify( - schema == null ? null : schema.toString(), catalog == null ? null : catalog.toString(), + schema == null ? null : schema.toString(), name.toString() ); @@ -128,8 +163,8 @@ public class ObjectName { throw new IllegalArgumentException( "dialect must be non-null." ); } return qualify( - encloseInQuotesIfQuoted( schema, dialect ), encloseInQuotesIfQuoted( catalog, dialect ), + encloseInQuotesIfQuoted( schema, dialect ), encloseInQuotesIfQuoted( name, dialect ) ); } @@ -137,7 +172,7 @@ public class ObjectName { private static String encloseInQuotesIfQuoted(Identifier identifier, Dialect dialect) { return identifier == null ? null : - identifier.encloseInQuotesIfQuoted( dialect ); + identifier.getText( dialect ); } private static String qualify(String schema, String catalog, String name) { @@ -176,9 +211,9 @@ public class ObjectName { @Override public String toString() { return "ObjectName{" + - "name='" + name + '\'' + + "catalog='" + catalog + '\'' + ", schema='" + schema + '\'' + - ", catalog='" + catalog + '\'' + + ", name='" + name + '\'' + '}'; } @@ -187,58 +222,5 @@ public class ObjectName { ? other == null : one.equals( other ); } - - private static String extractSchema(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 || tokens.length == 1 ) { - return null; - } - else if ( tokens.length == 2 ) { - // todo - this case needs to be refined w/ help of DatabaseMetaData (HF) - return null; - } - else if ( tokens.length == 3 ) { - return tokens[0]; - } - else { - throw new HibernateException( "Unable to parse object name: " + qualifiedName ); - } - } - - private static String extractCatalog(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 || tokens.length == 1 ) { - return null; - } - else if ( tokens.length == 2 ) { - // todo - this case needs to be refined w/ help of DatabaseMetaData (HF) - return null; - } - else if ( tokens.length == 3 ) { - return tokens[1]; - } - else { - throw new HibernateException( "Unable to parse object name: " + qualifiedName ); - } - } - - private static String extractName(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 ) { - return qualifiedName; - } - else { - return tokens[tokens.length - 1]; - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java index 3962571ef4..81c0f33cb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; @@ -34,33 +34,12 @@ import org.hibernate.dialect.Dialect; * @author Gavin King * @author Steve Ebersole */ -public class PrimaryKey extends AbstractConstraint implements Constraint, Exportable { - // IMPL NOTE : I override the name behavior here because: - // (1) primary keys are not required to be named. - // (2) because a primary key is required for each table, it is easier to allow setting the constraint name - // later in terms of building the metamodel - // - // todo : default name? {TABLE_NAME}_PK maybe? - private String name; +public class PrimaryKey extends AbstractConstraint { protected PrimaryKey(TableSpecification table) { super( table, null ); } - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String getExportIdentifier() { - return getTable().getLoggableValueQualifier() + ".PK"; - } - public String sqlConstraintStringInCreateTable(Dialect dialect) { StringBuilder buf = new StringBuilder("primary key ("); boolean first = true; @@ -71,7 +50,7 @@ public class PrimaryKey extends AbstractConstraint implements Constraint, Export else { buf.append(", "); } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); + buf.append( column.getColumnName().getText( dialect ) ); } return buf.append(')').toString(); } @@ -88,9 +67,14 @@ public class PrimaryKey extends AbstractConstraint implements Constraint, Export else { buf.append(", "); } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); + buf.append( column.getColumnName().getText( dialect ) ); } return buf.append(')').toString(); } + + @Override + public String getExportIdentifier() { + return getTable().getLoggableValueQualifier() + ".PK"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java new file mode 100644 index 0000000000..800764a8be --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java @@ -0,0 +1,213 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.HashMap; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.HibernateException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.compare.EqualsHelper; + +/** + * Represents a named schema/catalog pair and manages objects defined within. + * + * @author Steve Ebersole + */ +public class Schema { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + Schema.class.getName() + ); + + private final Name name; + + private Map inLineViews = new HashMap(); + private Map tables = new HashMap(); + private Map sequences = new HashMap(); + + public Schema(Name name) { + this.name = name; + } + + public Schema(Identifier catalog, Identifier schema) { + this( new Name( catalog, schema ) ); + } + + public Name getName() { + return name; + } + + /** + * Returns the table with the specified logical table name. + * + * @param logicalTableName - the logical name of the table + * + * @return the table with the specified table name, + * or null if there is no table with the specified + * table name. + */ + public Table locateTable(Identifier logicalTableName) { + return tables.get( logicalTableName ); + } + + /** + * Creates a {@link Table} with the specified name. + * + * @param logicalTableName The logical table name + * @param physicalTableName - the name of the table + * + * @return the created table. + */ + public Table createTable(Identifier logicalTableName, Identifier physicalTableName) { + Table table = new Table( this, logicalTableName, physicalTableName ); + tables.put( logicalTableName, table ); + return table; + } + + public DenormalizedTable createDenormalizedTable(Identifier logicalTableName, Identifier physicalTableName, Table includedTable) { + DenormalizedTable table = new DenormalizedTable( this, logicalTableName, physicalTableName, includedTable ); + tables.put( logicalTableName, table ); + return table; + } + + public Iterable
getTables() { + return tables.values(); + } + + public InLineView getInLineView(Identifier logicalName) { + return inLineViews.get( logicalName ); + } + + public InLineView createInLineView(Identifier logicalName, String subSelect) { + InLineView inLineView = new InLineView( this, logicalName, subSelect ); + inLineViews.put( logicalName, inLineView ); + return inLineView; + } + + public Sequence locateSequence(Identifier name) { + return sequences.get( name ); + } + + public Sequence createSequence(Identifier name, int initialValue, int increment) { + if ( sequences.containsKey( name ) ) { + throw new HibernateException( "Sequence was already registered with that name [" + name.toString() + "]" ); + } + + Sequence sequence = new Sequence( + new ObjectName( this.name.catalog, this.name.schema, name ), + initialValue, + increment + ); + sequences.put( name, sequence ); + return sequence; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "Schema" ); + sb.append( "{name=" ).append( name ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final Schema that = (Schema) o; + return EqualsHelper.equals( this.name, that.name ); + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + + public Iterable getSequences() { + return sequences.values(); + } + + public static class Name { + private final Identifier catalog; + private final Identifier schema; + + public Name(Identifier catalog, Identifier schema) { + this.schema = schema; + this.catalog = catalog; + } + + public Name(String catalog, String schema) { + this( Identifier.toIdentifier( catalog ), Identifier.toIdentifier( schema ) ); + } + + public Identifier getCatalog() { + return catalog; + } + + public Identifier getSchema() { + return schema; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "Name" ); + sb.append( "{catalog=" ).append( catalog ); + sb.append( ", schema=" ).append( schema ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final Name that = (Name) o; + + return EqualsHelper.equals( this.catalog, that.catalog ) + && EqualsHelper.equals( this.schema, that.schema ); + } + + @Override + public int hashCode() { + int result = catalog != null ? catalog.hashCode() : 0; + result = 31 * result + (schema != null ? schema.hashCode() : 0); + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java index fcaf7b886d..d9739562de 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java @@ -21,10 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; +import org.hibernate.HibernateException; /** * Models a database {@code SEQUENCE}. @@ -32,35 +31,29 @@ import org.hibernate.dialect.Dialect; * @author Steve Ebersole */ public class Sequence implements Exportable { - private final Schema schema; - private final String name; - private final String qualifiedName; + private final ObjectName name; + private final String nameText; private int initialValue = 1; private int incrementSize = 1; - public Sequence(Schema schema, String name) { - this.schema = schema; + public Sequence(ObjectName name) { this.name = name; - this.qualifiedName = new ObjectName( schema, name ).toText(); + this.nameText = name.toText(); } - public Sequence(Schema schema, String name, int initialValue, int incrementSize) { - this( schema, name ); + public Sequence(ObjectName name, int initialValue, int incrementSize) { + this( name ); this.initialValue = initialValue; this.incrementSize = incrementSize; } - public Schema getSchema() { - return schema; - } - - public String getName() { + public ObjectName getName() { return name; } @Override public String getExportIdentifier() { - return qualifiedName; + return nameText; } public int getInitialValue() { @@ -71,13 +64,28 @@ public class Sequence implements Exportable { return incrementSize; } - @Override - public String[] sqlCreateStrings(Dialect dialect) throws MappingException { - return dialect.getCreateSequenceStrings( name, initialValue,incrementSize ); - } - - @Override - public String[] sqlDropStrings(Dialect dialect) throws MappingException { - return dialect.getDropSequenceStrings( name ); + public void validate(int initialValue, int incrementSize) { + if ( this.initialValue != initialValue ) { + throw new HibernateException( + String.format( + "Multiple references to database sequence [%s] were encountered attempting to" + + "set conflicting values for 'initial value'. Found [%s] and [%s]", + nameText, + this.initialValue, + initialValue + ) + ); + } + if ( this.incrementSize != incrementSize ) { + throw new HibernateException( + String.format( + "Multiple references to database sequence [%s] were encountered attempting to" + + "set conflicting values for 'increment size'. Found [%s] and [%s]", + nameText, + this.incrementSize, + incrementSize + ) + ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java index 731d05af78..59c3b407f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.io.Serializable; @@ -115,6 +115,7 @@ public class Size implements Serializable { this.precision = size.precision; this.scale = size.scale; this.length = size.length; + this.lobMultiplier = size.lobMultiplier; } public void setPrecision(int precision) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java new file mode 100644 index 0000000000..20ddbd568e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java @@ -0,0 +1,314 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * Models the concept of a relational TABLE (or VIEW). + * + * @author Gavin King + * @author Steve Ebersole + */ +public class Table extends AbstractTableSpecification implements Exportable { + private final Schema database; + private Identifier physicalName; + private Identifier logicalName; + private ObjectName qualifiedName; + private String exportIdentifier; + private boolean isPhysicalTable = true; + private boolean hasDenormalizedTables = false; + + private final Set indexes = new LinkedHashSet(); + private final Set uniqueKeys = new LinkedHashSet(); + private final List checkConstraints = new ArrayList(); + private final List comments = new ArrayList(); + + /** + * Constructs a {@link Table} instance. + * + * @param database - the schema + * @param logicalName - The logical name + * @param physicalName - the physical table name. + */ + public Table(Schema database, Identifier logicalName, Identifier physicalName) { + this.database = database; + this.logicalName = logicalName; + this.physicalName = physicalName; + this.qualifiedName = new ObjectName( database, physicalName ); + this.exportIdentifier = qualifiedName.toText(); + } + + @Override + public Schema getSchema() { + return database; + } + + /** + * Gets the logical table name. + * + * @return the logical table name. + */ + @Override + public Identifier getLogicalName() { + return logicalName; + } + + /** + * Returns the simple physical name. + * + * @return The simple (non-qualfied) table name. For the qualified name, see {@link #getTableName()} + * + * @see {@link #getTableName()} + */ + public Identifier getPhysicalName() { + return physicalName; + } + + /** + * Is this a physical table or should it be a virtual table representing as root entity in table-per-class hierarchy. + * + * It's {@code false} only when the entity is {@code abstract} and also having union sub-class + */ + public boolean isPhysicalTable() { + return isPhysicalTable; + } + + public void setPhysicalTable(boolean physicalTable) { + isPhysicalTable = physicalTable; + } + + public boolean hasDenormalizedTables() { + return hasDenormalizedTables; + } + + protected void setHasDenormalizedTables(boolean hasDenormalizedTables) { + this.hasDenormalizedTables = hasDenormalizedTables; + } + + /** + * Gets the qualified table name. + * + * @return the qualified table name. + */ + public ObjectName getTableName() { + return qualifiedName; + } + + @Override + public String getLoggableValueQualifier() { + return exportIdentifier; + } + + @Override + public String getExportIdentifier() { + return exportIdentifier; + } + + @Override + public String toLoggableString() { + return exportIdentifier; + } + + @Override + public Iterable getIndexes() { + return Collections.unmodifiableSet( indexes ); + } + + @Override + public void addIndex(Index idx) { + indexes.add( idx ); + } + + @Override + public Iterable getUniqueKeys() { + return Collections.unmodifiableSet( uniqueKeys ); + } + + @Override + public void addUniqueKey(UniqueKey uk) { + uniqueKeys.add( uk ); + } + + @Override + public boolean hasUniqueKey(Column column) { + for ( UniqueKey uniqueKey : uniqueKeys ) { + if ( uniqueKey.hasColumn( column ) ) { + return true; + } + } + return false; + } + + @Override + public Iterable getCheckConstraints() { + return checkConstraints; + } + + @Override + public void addCheckConstraint(String checkCondition) { + //todo ? StringHelper.isEmpty( checkCondition ); + //todo default name? + checkConstraints.add( new CheckConstraint( this, "", checkCondition ) ); + } + + @Override + public Iterable getComments() { + return comments; + } + + @Override + public void addComment(String comment) { + comments.add( comment ); + } + + @Override + public String getQualifiedName(Dialect dialect) { + return qualifiedName.toText( dialect ); + } + + @Override + public String toString() { + return "Table{name=" + exportIdentifier + '}'; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( ! ( o instanceof Table ) ) { + return false; + } + + final Table that = (Table) o; + + return EqualsHelper.equals( this.database, that.database ) + && EqualsHelper.equals( this.logicalName, that.logicalName ) + && EqualsHelper.equals( this.physicalName, that.physicalName ); + } + + @Override + public int hashCode() { + int result = database != null ? database.hashCode() : 0; + result = 31 * result + ( physicalName != null ? physicalName.hashCode() : 0 ); + result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); + return result; + } + + public String[] sqlAlterStrings(TableInformation tableInformation, JdbcEnvironment jdbcEnvironment) { + final Dialect dialect = jdbcEnvironment.getDialect(); + final String baseAlterCommand = new StringBuilder( "alter table " ) + .append( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( getTableName() ) ) + .append( ' ' ) + .append( dialect.getAddColumnString() ) + .toString(); + + final List commands = new ArrayList(); + + for ( Value value : values() ) { + if ( ! Column.class.isInstance( value ) ) { + continue; + } + + final Column column = (Column) value; + final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() ); + + if ( columnInformation != null ) { + continue; + } + + StringBuilder alter = new StringBuilder( baseAlterCommand ) + .append( ' ' ) + .append( column.getColumnName().getText( dialect ) ) + .append( ' ' ) + .append( column.getSqlType() ); + + + final String defaultValue = column.getDefaultValue(); + if ( defaultValue != null ) { + alter.append( " default " ) + .append( defaultValue ); + } + String nullablePostfix = column.isNullable() ? dialect.getNullColumnString() : " not null"; + alter.append( nullablePostfix ); + + if ( hasUniqueKey(column) ) { + alter.append( dialect.getUniqueDelegate().getColumnDefinitionUniquenessFragment( + column ) ); + } + + final String checkCondition = column.getCheckCondition(); + if ( checkCondition != null && dialect.supportsColumnCheck() ) { + alter.append( " check(" ) + .append( checkCondition ) + .append( ")" ); + } + + final String columnComment = column.getComment(); + if ( columnComment != null ) { + alter.append( dialect.getColumnComment( columnComment ) ); + } + + commands.add( alter.toString() ); + } + + return commands.toArray( new String[ commands.size() ] ); + } + + /** + * @return Sorted column list so that primary key appears first, followed by foreign keys and other properties. + * Within each group columns are not sorted in any way. + */ + public Iterable sortedColumns() { + final Set sortedColumns = new LinkedHashSet(); + + // Adding primary key columns. + sortedColumns.addAll( getPrimaryKey().getColumns() ); + // Adding foreign key columns. + for ( ForeignKey fk : getForeignKeys() ) { + sortedColumns.addAll( fk.getColumns() ); + } + // Adding other columns. + for ( Value value : values() ) { + if ( value instanceof Column ) { + final Column column = (Column) value; + if ( ! sortedColumns.contains( column ) ) { + sortedColumns.add( column ); + } + } + } + return sortedColumns; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java index 69fbd02d55..46503428fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; @@ -38,6 +38,13 @@ public interface TableSpecification extends ValueContainer, Loggable { */ public Schema getSchema(); + /** + * Gets the logical table name. + * + * @return the logical table name. + */ + public Identifier getLogicalName(); + /** * Get the table number. * @@ -62,13 +69,17 @@ public interface TableSpecification extends ValueContainer, Loggable { public Column locateOrCreateColumn(String name); /** - * Factory method for creating a {@link Column} associated with this container. + * Attempt to locate a column with the given name * * @param name The column name * - * @return The generated column + * @return The located column, or {@code null} is none found */ - public Tuple createTuple(String name); + public Column locateColumn(String name); + + public Column createColumn(String name); + + public Column createColumn(Identifier name); /** * Factory method for creating a {@link DerivedValue} associated with this container. @@ -79,17 +90,59 @@ public interface TableSpecification extends ValueContainer, Loggable { */ public DerivedValue locateOrCreateDerivedValue(String fragment); + /** + * Generates a unique ID for the specified columns in this table. + * + * @param columns - the columns used to generate the ID + * @return the ID unique to the specified columns in this table. + */ + public int generateColumnListId(Iterable columns); + + /** + * Retrieve a read-only version of foreign keys currently defined for this table. + * + * @return a reforeign keys defined on this table. + */ public Iterable getForeignKeys(); + /** + * Locate a foreign key by name + * + * @param name The name of the foreign key to locate + * + * @return The foreign key, or {@code null} to indicate none with that name was found. + */ + public ForeignKey locateForeignKey(String name); + + /** + * Locate foreign keys with {@code this} table as source and the passed table as the target. + * + * @param targetTable The table that is the target of interest. + * + * @return The matching foreign keys, or {@code null} to indicate none were found. + */ + public Iterable locateForeignKey(TableSpecification targetTable); + + /** + * Create a foreign key targeting the specified table as the target. Columns should be handled through the + * returned reference. + * + * @param targetTable The table that is the target of the foreign key + * @param name The (optional) name of the foreign key + * + * @return The foreign key reference. + */ public ForeignKey createForeignKey(TableSpecification targetTable, String name); public Iterable getIndexes(); - public Index getOrCreateIndex(String name); + public void addIndex(Index idx); public Iterable getUniqueKeys(); - public UniqueKey getOrCreateUniqueKey(String name); + public void addUniqueKey(UniqueKey uk); + + public boolean hasUniqueKey(Column column); public Iterable getCheckConstraints(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java index f130f2ebe9..78d8e7f6f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java @@ -21,47 +21,50 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; /** * Models a SQL INDEX defined as UNIQUE * * @author Gavin King * @author Steve Ebersole + * @author Brett Meyer */ -public class UniqueKey extends AbstractConstraint implements Constraint { +public class UniqueKey extends AbstractConstraint { + + public UniqueKey() { + this( null, null ); + } + protected UniqueKey(Table table, String name) { super( table, name ); } - @Override - public String getExportIdentifier() { - StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); - sb.append( ".UK" ); - for ( Column column : getColumns() ) { - sb.append( '_' ).append( column.getColumnName().getName() ); - } - return sb.toString(); - } - @Override public String[] sqlCreateStrings(Dialect dialect) { - String s = dialect.getUniqueDelegate().getAlterTableToAddUniqueKeyCommand( this ); - return StringHelper.toArrayElement( s ); + return new String[] { dialect.getUniqueDelegate().getAlterTableToAddUniqueKeyCommand( this ) }; } @Override public String[] sqlDropStrings(Dialect dialect) { - String s = dialect.getUniqueDelegate().getAlterTableToDropUniqueKeyCommand( this ); - return StringHelper.toArrayElement( s ); + return new String[] { dialect.getUniqueDelegate().getAlterTableToDropUniqueKeyCommand( this ) }; } @Override - protected String sqlConstraintStringInAlterTable(Dialect dialect) { + public String sqlConstraintStringInAlterTable(Dialect dialect) { // not used return ""; } + + @Override + public String getExportIdentifier() { + StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); + sb.append( ".UK" ); + for ( Column column : getColumns() ) { + sb.append( '_' ).append( column.getColumnName().getText() ); + } + return sb.toString(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java similarity index 64% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java index 0549bb7cc1..0c41d56b1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java @@ -21,21 +21,36 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; /** - * Models a value within a {@link ValueContainer}. This will generally be either a {@link Column column} or a - * {@link DerivedValue derived value}, but we also allow the notion of {@link Tuple} at this level + * Models a value within a {@link ValueContainer}. Concretely, either a {@link Column column} or a + * {@link DerivedValue derived value}. * * @author Steve Ebersole */ public interface Value { + + public enum ValueType { + COLUMN, + DERIVED_VALUE + } + /** - * Retrieve the table that owns this value. + * Return the value type. * - * @return The owning table. + * @return The value type */ - public TableSpecification getTable(); + public ValueType getValueType(); + + /** + * Retrieve the JDBC data type of this value. + * + * @return The value's JDBC data type + */ + public JdbcDataType getJdbcDataType(); /** * Obtain the string representation of this value usable in log statements. @@ -44,6 +59,32 @@ public interface Value { */ public String toLoggableString(); + /** + * For any column name, generate an alias that is unique + * to that column name, and (optionally) unique across tables, and + * within alias size constraints determined by + * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. + * + * todo : not sure this contract is the best place for this method + * + * @param dialect the dialect. + * @param tableSpecification, if non-null, the table specification to use + * to make the alias unambiguous across tables; if null, there is no need to need + * to use the table to make the alias unambiguous across tables. + * @return the alias. + */ + public String getAlias(Dialect dialect, TableSpecification tableSpecification); + + /** + * Validate the value against the incoming JDBC type code array, both in terms of number of types + * and compatibility of types. + * + * @param typeCodes The type codes. + * + * @throws org.hibernate.metamodel.ValidationException if validaton fails. + */ + public void validateJdbcTypes(JdbcCodes typeCodes); + /** * Used to track JDBC type usage throughout a series of potential recursive calls to component * values since we do not know ahead of time which values correspond to which indexes of the @@ -66,14 +107,4 @@ public interface Value { } } - /** - * Validate the value against the incoming JDBC type code array, both in terms of number of types - * and compatibility of types. - * - * @param typeCodes The type codes. - * - * @throws org.hibernate.metamodel.ValidationException if validaton fails. - */ - public void validateJdbcTypes(JdbcCodes typeCodes); - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java index 5523716f4e..301f7e14c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java @@ -21,22 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import java.util.List; /** * Contract for data containers (what the ANSI SQL spec calls "table specifications") to which we can map - * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}, but a - * {@link Tuple} is a conceptual value container as well. + * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}. * * @author Steve Ebersole */ public interface ValueContainer { /** * Obtain an iterator over this containers current set of value definitions. + *

+ * The returned list is unmodifiable! * * @return Iterator over value definitions. */ - public Iterable values(); + public List values(); + + public boolean hasValue(Value value); /** * Get a qualifier which can be used to qualify {@link Value values} belonging to this container in diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/package.html similarity index 100% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/package.html rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/package.html diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java similarity index 72% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java index feb396751c..28ecf8149f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java @@ -21,13 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE aggregated-composite}. This equates to an identifier which is + * made up of multiple values which are defined as part of a component/embedded. + * * @author Strong Liu + * @author Steve Ebersole */ -public interface ComponentIdentifierSource extends IdentifierSource { +public interface AggregatedCompositeIdentifierSource extends CompositeIdentifierSource { /** * Obtain the source descriptor for the identifier attribute. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationPluralAttributeElementSource.java similarity index 79% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationPluralAttributeElementSource.java index cf7d0207ad..f1d20f94ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationPluralAttributeElementSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,14 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.spi.source; /** - * @author Hardy Ferentschik - */ -public enum ConfiguredClassType { - ENTITY, - MAPPED_SUPERCLASS, - EMBEDDABLE, - NON_ENTITY + + * @author Gail Badner + + */ +public interface AssociationPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationSource.java new file mode 100644 index 0000000000..0b1b4fd3ba --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AssociationSource.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.Set; + +/** + * @author Gail Badner + */ +public interface AssociationSource extends CascadeStyleSource { + + public AttributeSource getAttributeSource(); + + /** + * Obtain the name of the referenced entity. + * + * @return The name of the referenced entity + */ + public String getReferencedEntityName(); + + public boolean isNotFoundAnException(); + + /** + * Returns the attribute source that is owned by this {@link AssociationSource}, + * if there is one. + *

+ * Specifically, this method returns the {@link AttributeSource} that is + * "mappedBy" this {@link AssociationSource}. + * + * @return + */ + public Set getOwnedAssociationSources(); + + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource); + + public boolean isMappedBy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeRelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeRelationalValueSourceContainer.java new file mode 100644 index 0000000000..439fcfa0d4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeRelationalValueSourceContainer.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Contract for a container of {@link RelationalValueSource} references for an attribute. + * + * It provides the default table that contains the relational values for the singular attribute. + * + * See {@link RelationalValueSourceContainer} for additional details. + * + * @author Gail Badner + */ +public interface AttributeRelationalValueSourceContainer extends RelationalValueSourceContainer { + /** + * @return returns the default name of the table that contains the relational values. + */ + public String getContainingTableName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSource.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSource.java index 2999634f1a..2f69b3340f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSource.java @@ -21,14 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * Contract for sources of persistent attribute descriptions. * * @author Steve Ebersole */ -public interface AttributeSource { +public interface AttributeSource extends MetaSource{ /** * Obtain the attribute name. * @@ -48,7 +48,7 @@ public interface AttributeSource { * * @return The Hibernate type information */ - public ExplicitHibernateTypeSource getTypeInformation(); + public HibernateTypeSource getTypeInformation(); /** * Obtain the name of the property accessor style used to access this attribute. @@ -67,11 +67,4 @@ public interface AttributeSource { * @return {@code true} indicates it should be included; {@code false}, it should not. */ public boolean isIncludedInOptimisticLocking(); - - /** - * Obtain the meta-attribute sources associated with this attribute. - * - * @return The meta-attribute sources. - */ - public Iterable metaAttributes(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceContainer.java similarity index 91% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceContainer.java index d4d088bbe3..0cd80737e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceContainer.java @@ -21,9 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import org.hibernate.metamodel.source.LocalBindingContext; +import java.util.List; /** * Contract for a container of {@link AttributeSource} references. Both entities and components contain @@ -44,7 +44,7 @@ public interface AttributeSourceContainer { * * @return The attribute sources. */ - public Iterable attributeSources(); + public List attributeSources(); /** * Obtain the local binding context associated with this container. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceResolutionContext.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceResolutionContext.java index 69fc83a7a7..7265f3a02b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AttributeSourceResolutionContext.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,20 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; /** - * Describes the nature of persistent collection elements. * - * @author Steve Ebersole * @author Gail Badner - * - * @todo Merge with {@link org.hibernate.metamodel.source.binder.PluralAttributeNature} ? package separation kept me from doing that initially */ -public enum CollectionElementNature { - BASIC, - COMPOSITE, - ONE_TO_MANY, - MANY_TO_MANY, - MANY_TO_ANY +public interface AttributeSourceResolutionContext { + public IdentifierSource resolveIdentifierSource(String entityName); + public AttributeSource resolveAttributeSource(String entityName, String attributeName); + public List resolveIdentifierColumns(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java index bf1d055bd8..a2919f9e73 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeElementSource.java @@ -21,14 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole */ -public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource { - public List getValueSources(); - public ExplicitHibernateTypeSource getExplicitHibernateTypeSource(); +public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource, RelationalValueSourceContainer { + + public HibernateTypeSource getExplicitHibernateTypeSource(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeIndexSource.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeIndexSource.java index a0ea13a92c..c02473a6b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BasicPluralAttributeIndexSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; +package org.hibernate.metamodel.spi.source; /** * @author Gail Badner */ -public interface SimpleValueRelationalState extends ValueRelationalState { +public interface BasicPluralAttributeIndexSource extends PluralAttributeIndexSource { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BindingContext.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BindingContext.java index 6fbcfc0c0c..cc1cd658a9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/BindingContext.java @@ -21,11 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; import org.hibernate.cfg.NamingStrategy; import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.domain.Type; import org.hibernate.service.ServiceRegistry; /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CascadeStyleSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CascadeStyleSource.java new file mode 100644 index 0000000000..bc61eed5d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CascadeStyleSource.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; + +/** + * Describes sources which can be cascaded. + * + * @author Steve Ebersole + */ +public interface CascadeStyleSource { + /** + * Obtain the cascade styles to be applied to this association. + * + * @return The cascade styles. + */ + public Set getCascadeStyles(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnBindingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnBindingDefaults.java new file mode 100644 index 0000000000..762d7a3d7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnBindingDefaults.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Steve Ebersole + */ +public interface ColumnBindingDefaults { + /** + * How should non-specification of value insertion by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that insertions are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesIncludedInInsertByDefault(); + + /** + * How should non-specification of value updating by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that updates are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesIncludedInUpdateByDefault(); + + /** + * How should non-specification of value nullability by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that insertions are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesNullableByDefault(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java index 3f86bd6b0f..3b8029e2a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java @@ -21,13 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; /** - * Contract for source information pertaining to a column definition. + * Contract for source information pertaining to a physical column definition specific to a particular attribute + * context. + *

+ * Conceptual note: this really describes a column from the perspective of its binding to an attribute. + * This is especially important for {@link #isIncludedInInsert} and {@link #isIncludedInUpdate}. There it is + * not the column itself being described. * * @author Steve Ebersole */ @@ -58,7 +63,7 @@ public interface ColumnSource extends RelationalValueSource { * * @return {@code true} indicates it is nullable; {@code false} non-nullable. */ - public boolean isNullable(); + public TruthValue isNullable(); /** * Obtain a specified default value for the column @@ -79,14 +84,14 @@ public interface ColumnSource extends RelationalValueSource { * * @return The column's SQL data type. */ - public Datatype getDatatype(); + public JdbcDataType getDatatype(); /** - * Obtain the specified column size. + * Obtain the source for the specified column size. * - * @return The column size. + * @return The source for the column size. */ - public Size getSize(); + public SizeSource getSizeSource(); /** * Is this column unique? @@ -109,7 +114,17 @@ public interface ColumnSource extends RelationalValueSource { */ public String getComment(); - public boolean isIncludedInInsert(); + /** + * Is the described column written to as part of inserts for the attribute being mapped. + * + * @return {@code true} indicates the column is written on insert from this attribute + */ + public TruthValue isIncludedInInsert(); - public boolean isIncludedInUpdate(); + /** + * Is the described column written to as part of updates for the attribute being mapped. + * + * @return {@code true} indicates the column is written on update from this attribute + */ + public TruthValue isIncludedInUpdate(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ComponentAttributeSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ComponentAttributeSource.java index a480489397..4fd55e7c5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ComponentAttributeSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import org.hibernate.internal.util.ValueHolder; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositeIdentifierSource.java new file mode 100644 index 0000000000..75d754dd76 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositeIdentifierSource.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * @author Steve Ebersole + */ +public interface CompositeIdentifierSource extends IdentifierSource { + /** + * Handle silly SpecJ reading of the JPA spec. They believe composite identifiers should have "partial generation" + * capabilities. + * + * @todo See todo on {@link IdentifierSource#getIdentifierGeneratorDescriptor()} wrt "generator source"... + * + * @param identifierAttributeName The name of the individual attribute within the composite identifier. + * + * @return The generator for the named attribute (within the composite). + */ + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeElementSource.java similarity index 86% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeElementSource.java index 0965d93fc8..3667ccf829 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeElementSource.java @@ -21,14 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import org.hibernate.internal.util.ValueHolder; /** * @author Steve Ebersole */ -public interface CompositePluralAttributeElementSource extends PluralAttributeElementSource, AttributeSourceContainer { +public interface CompositePluralAttributeElementSource + extends PluralAttributeElementSource, AttributeSourceContainer, CascadeStyleSource, MetaSource { public String getClassName(); public ValueHolder> getClassReference(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeIndexSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeIndexSource.java new file mode 100644 index 0000000000..def93be522 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/CompositePluralAttributeIndexSource.java @@ -0,0 +1,36 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import org.hibernate.internal.util.ValueHolder; + +/** + * @author Gail Badner + */ +public interface CompositePluralAttributeIndexSource + extends PluralAttributeIndexSource, AttributeSourceContainer { + public String getClassName(); + + public ValueHolder> getClassReference(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ConstraintSource.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ConstraintSource.java index 0f59e50fb3..88479ffd8d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ConstraintSource.java @@ -21,7 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; + +import java.util.List; + /** * Contract describing source of table constraints @@ -40,9 +43,8 @@ public interface ConstraintSource { * @return The logical table name. Can be {@code null} in the case of the "primary table". */ public String getTableName(); - - /** - * @return returns the names of the column which are part of this constraint - */ - Iterable columnNames(); + + public List columnNames(); + + public List orderings(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DerivedValueSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DerivedValueSource.java index 85b2738c49..6c87e81070 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DerivedValueSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * Contract describing source of a derived value (formula). diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DiscriminatorSource.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DiscriminatorSource.java index c2fcc9c927..07d2a5702f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/DiscriminatorSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * Contract for sources of information about a mapped discriminator. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityAttributePluralAttributeIndexSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityAttributePluralAttributeIndexSource.java new file mode 100644 index 0000000000..262a9aaad1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityAttributePluralAttributeIndexSource.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Represents a plural attribute index source that is an attribute + * of the referenced entity (relevant only to one-to-many and many-to-many + * associations). + * + * @author Gail Badner + */ +public interface EntityAttributePluralAttributeIndexSource extends PluralAttributeIndexSource { + public String getAttributeName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityHierarchy.java similarity index 91% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityHierarchy.java index fdfdf9ec4f..5f33c3c37d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntityHierarchy.java @@ -21,9 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import org.hibernate.metamodel.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.InheritanceType; /** * Models the source-agnostic view of an entity hierarchy. @@ -43,7 +43,7 @@ public interface EntityHierarchy { /** * Obtain the hierarchy's root entity. * - * @return THe root entity. + * @return The root entity. */ public RootEntitySource getRootEntitySource(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntitySource.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntitySource.java index f118d9c49e..e9782333ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/EntitySource.java @@ -21,23 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import java.util.List; +import java.util.Set; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.MappedSuperclass; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.metamodel.spi.binding.CustomSQL; /** * Contract describing source of an entity * * @author Steve Ebersole */ -public interface EntitySource extends SubclassEntityContainer, AttributeSourceContainer { +public interface EntitySource extends SubclassEntityContainer, AttributeSourceContainer, MetaSource { /** * Obtain the origin of this source. @@ -79,14 +79,14 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo * * @return The primary table. */ - public TableSource getPrimaryTable(); + public TableSpecificationSource getPrimaryTable(); /** * Obtain the secondary tables for this entity * * @return returns an iterator over the secondary tables for this entity */ - public Iterable getSecondaryTables(); + public Set getSecondaryTables(); /** * Obtain the name of a custom tuplizer class to be used. @@ -184,16 +184,9 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo /** * Obtain any additional table names on which to synchronize (auto flushing) this entity. * - * @return Additional synchronized table names. + * @return Additional synchronized table names or 0 sized String array, never return null. */ - public List getSynchronizedTableNames(); - - /** - * Obtain the meta-attribute sources associated with this entity. - * - * @return The meta-attribute sources. - */ - public Iterable metaAttributes(); + public String[] getSynchronizedTableNames(); /** * Get the actual discriminator value in case of a single table inheritance @@ -212,5 +205,12 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo * @return the list of classes (this {@link Entity entity}/{@link MappedSuperclass mapped superclass}, or * {@link EntityListeners entity listeners}) that define JPA callbacks for this entity/mapped superclass. */ - List getJpaCallbackClasses(); + List getJpaCallbackClasses(); + + /** + * Obtain the filters for this entity. + * + * @return returns an array of the filters for this entity. + */ + public FilterSource[] getFilterSources(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchProfileSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchProfileSource.java new file mode 100644 index 0000000000..6a205c8aea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchProfileSource.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Defines a source of fetch profile information + * + * @author Steve Ebersole + */ +public interface FetchProfileSource { + /** + * Defines a source of an association fetch information within a fetch profile + */ + public static interface AssociationOverrideSource { + /** + * Retrieve the name of the entity containing the association. + * + * @return The entity name. + */ + public String getEntityName(); + + /** + * Retrieve the name of the association attribute on the entity. + * + * @return The attribute name + */ + public String getAttributeName(); + + /** + * Retrieve the name of the fetch mode to be applied to the association as part of this profile. + * + * @return the fetch mode name. + */ + public String getFetchModeName(); + } + + /** + * Retrieve the name of the profile. + * + * @return The profile name. + */ + public String getName(); + + /** + * Retrieve the association fetching overrides associated with this profile. + * + * @return The association fetching overrides + */ + public Iterable getAssociationOverrides(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchableAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchableAttributeSource.java new file mode 100644 index 0000000000..e705285f23 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FetchableAttributeSource.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; + +/** + * Describes source for attributes which can be fetched. + * + * @author Steve Ebersole + */ +public interface FetchableAttributeSource { + public FetchTiming getFetchTiming(); + + public FetchStyle getFetchStyle(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterDefinitionSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterDefinitionSource.java new file mode 100644 index 0000000000..04d57067de --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterDefinitionSource.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Describe the source of filer def information. Generally either {@code } or + * {@link org.hibernate.annotations.FilterDef @FilterDef} + * + * @author Steve Ebersole + */ +public interface FilterDefinitionSource { + /** + * Retrieve the name of the filter. Would match the related {@link FilterSource#getName} + * + * @return The filter name + * + * @see FilterSource#getName + */ + public String getName(); + + /** + * Retrieve the condition specified as part of the def. Defines the condition to use + * in related filters when {@link FilterSource#getCondition} is null. + * + * @return The "default" condition for associated filters. + * + * @see FilterSource#getCondition + */ + public String getCondition(); + + /** + * Retrieve parameter sources associated with this filer def. + * + * @return The parameter sources. Can be null. + */ + public Iterable getParameterSources(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterParameterSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterParameterSource.java new file mode 100644 index 0000000000..a54e60cdf9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterParameterSource.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Describes the source of filter parameter information + * + * @author Steve Ebersole + */ +public interface FilterParameterSource { + /** + * Retrieve the name of the parameter being described. + * + * @return The name + */ + public String getParameterName(); + + /** + * The Hibernate type name that can be used to handle bound parameter values. + * + * @return the type + */ + public String getParameterValueTypeName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterSource.java new file mode 100644 index 0000000000..1ab6664b4d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/FilterSource.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.Map; + +/** + * Defines the source of filter information. May have an associated {@link FilterDefinitionSource}. + * Relates to both {@code } and {@link org.hibernate.annotations.Filter @Filter} + * + * @author Steve Ebersole + */ +public interface FilterSource { + /** + * Get the name of the filter being described. + * + * @return The name. + */ + public String getName(); + + /** + * Get the condition associated with the filter. Can be {@code null} in the case of a filter described + * further by a "filter def" which contains the condition text. + * + * @return The condition defined on the filter. + * + * @see {@link FilterDefinitionSource#getCondition()} + */ + public String getCondition(); + + /** + * Should Hibernate perform automatic alias injection into the supplied condition string? The default it to + * perform auto injection *unless* explicit alias(es) are supplied. + * + * @return {@code true} indicates auto injection should occur; {@code false} that it should not + */ + public boolean shouldAutoInjectAliases(); + + /** + * Get the map of explicit alias to table name mappings. + * + * @return The alias to table map + */ + public Map getAliasToTableMap(); + + /** + * Get the map of explicit alias to entity name mappings. + * + * @return The alias to entity map + */ + public Map getAliasToEntityMap(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java new file mode 100644 index 0000000000..85318e1e3b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Additional contract for things which describe foreign keys. + * + * @author Steve Ebersole + */ +public interface ForeignKeyContributingSource { + /** + * Retrieve the name of the foreign key as supplied by the user, or {@code null} if the user supplied none. + * + * @return The user supplied foreign key name. + */ + public String getExplicitForeignKeyName(); + + /** + * Retrieve the delegate for resolving foreign key target columns. This corresponds directly to + * HBM {@code } and JPA {@link javax.persistence.JoinColumn} mappings. + *

+ * By default foreign keys target the primary key of the targeted table. {@code } and + * {@link javax.persistence.JoinColumn} mappings represents ways to instead target non-PK columns. Implementers + * should return {@code null} to indicate targeting primary key columns. + * + * @return The delegate, or {@code null} + */ + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate(); + + /** + * By default foreign keys target the columns defined as the primary key of the targeted table. This contract + * helps account for cases where other columns should be targeted instead. + */ + public static interface JoinColumnResolutionDelegate { + /** + * Resolve the (other, non-PK) columns which should targeted by the foreign key. + * + * @param context The context for resolving those columns. + * + * @return The resolved target columns. + */ + public List getJoinColumns(JoinColumnResolutionContext context); + + public TableSpecification getReferencedTable(JoinColumnResolutionContext context); + + /** + * Retrieves the explicitly named attribute that maps to the non-PK foreign-key target columns. + * + * @return The explicitly named referenced attribute, or {@code null}. This most likely always {@code null} + * from annotations cases. + */ + public String getReferencedAttributeName(); + } + + /** + * Means to allow the {@link JoinColumnResolutionDelegate} access to the relational values it needs. + */ + public static interface JoinColumnResolutionContext { + /** + * Given an attribute name, resolve the columns. This is used in the HBM {@code property-ref/>} case. + * + * @param attributeName The name of the referenced property. + * + * @return The corresponding referenced columns + */ + public List resolveRelationalValuesForAttribute(String attributeName); + + public TableSpecification resolveTableForAttribute(String attributeName); + + /** + * Resolve a column reference given the logical names of both the table and the column. Used in the + * {@link javax.persistence.JoinColumn} case + * + * @param logicalColumnName The logical column name. + * @param logicalTableName The logical table name. + * @param logicalSchemaName The logical schema name. + * @param logicalCatalogName The logical catalog name. + * + * @return The column. + */ + public Column resolveColumn(String logicalColumnName, String logicalTableName, String logicalSchemaName, String logicalCatalogName); + + /** + * Resolve a table reference given the logical names of the table and the column. Used in the + * {@link javax.persistence.JoinColumn} case + * + * @param logicalTableName The logical table name. + * @param logicalSchemaName The logical schema name. + * @param logicalCatalogName The logical catalog name. + * + * @return The column. + */ + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/HibernateTypeSource.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/HibernateTypeSource.java index c64fb0789c..326bdaffe6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/HibernateTypeSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import java.util.Map; @@ -30,18 +30,25 @@ import java.util.Map; * * @author Steve Ebersole */ -public interface ExplicitHibernateTypeSource { +public interface HibernateTypeSource { /** * Obtain the supplied Hibernate type name. * * @return The Hibernate type name */ - public String getName(); + String getName(); /** * Obtain any supplied Hibernate type parameters. * * @return The Hibernate type parameters. */ - public Map getParameters(); + Map getParameters(); + + /** + * Obtain the attribute's java type if possible. + * + * @return The java type of the attribute or null. + */ + Class getJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierGeneratorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierGeneratorSource.java new file mode 100644 index 0000000000..aee308ed61 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierGeneratorSource.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.Map; + +/** + * @author Steve Ebersole + */ +public interface IdentifierGeneratorSource { + /** + * Retrieve the name of the generator specification. This is the name used in + * {@link javax.persistence.GeneratedValue}, not the name of the underlying table/sequence! + * + * @return The generator name + */ + public String getGeneratorName(); + + /** + * Retrieve the name of the generator implementation name. This is either

    + *
  • an FQN naming the {@link org.hibernate.id.IdentifierGenerator} implementation
  • + *
  • the recognized "short name" of a built-in {@link org.hibernate.id.IdentifierGenerator} implementation
  • + *
+ * + * @return the generator implementation name + */ + public String getGeneratorImplementationName(); + + /** + * Retrieve the generator config parameters + * + * @return generator configuration parameters + */ + public Map getParameters(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java similarity index 60% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java index fe9a33d8e7..c38b280beb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java @@ -21,47 +21,43 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import org.hibernate.metamodel.binding.IdGenerator; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; /** * Contract describing source of identifier information for the entity. * * @author Steve Ebersole */ -public interface IdentifierSource { +public interface IdentifierSource extends MetaSource{ /** * Obtain the identifier generator source. + * + * @todo this should name a source as well, no? + * Basically, not sure it should be up to the sources to build binding objects. + * IdentifierGeneratorSource, possibly as a hierarchy as well to account for differences + * in "global" versus "local" declarations * * @return The generator source. */ - IdGenerator getIdentifierGeneratorDescriptor(); - - public static enum Nature { - /** - * A single, simple identifier. Equivalent of an {@code } mapping or a single {@code @Id} - * annotation. Indicates the {@link IdentifierSource} is castable to {@link SimpleIdentifierSource}. - */ - SIMPLE, - - /** - * What we used to term an "embedded composite identifier", which is not to be confused with the JPA - * term embedded. Specifically a composite id where there is no component class, though there may be an - * {@code @IdClass}. - */ - COMPOSITE, - - /** - * Composite identifier with an actual component class used to aggregate the individual attributes - */ - AGGREGATED_COMPOSITE - } + IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor(); /** * Obtain the nature of this identifier source. * * @return The identifier source's nature. */ - public Nature getNature(); + public EntityIdentifierNature getNature(); + + /** + * Returns the "unsaved" entity identifier value. + * + * @todo Not sure this is relevant for anything other than simple identifiers. Move to SimpleIdentifierSource ? + * + * @return the "unsaved" entity identifier value + */ + public String getUnsavedValue(); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InLineViewSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InLineViewSource.java new file mode 100644 index 0000000000..ff15a9ddaa --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InLineViewSource.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Describes in-line view source information. Generally, either {@link org.hibernate.annotations.Subselect} + * or {@code } + * + * @author Steve Ebersole + */ +public interface InLineViewSource extends TableSpecificationSource { + /** + * Obtain the {@code SQL SELECT} statement to use. Cannot be null! + * + * @return The {@code SQL SELECT} statement + */ + public String getSelectStatement(); + + public String getLogicalName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexConstraintSource.java similarity index 84% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexConstraintSource.java index 6bec20e59e..13d44d7abe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexConstraintSource.java @@ -21,13 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; +package org.hibernate.metamodel.spi.source; import java.util.List; + /** - * @author Gail Badner + * Defining a index constraint source + * + * @author Brett Meyer */ -public interface TupleRelationalState extends ValueRelationalState { - List getRelationalStates(); +public interface IndexConstraintSource extends ConstraintSource { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexedPluralAttributeSource.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexedPluralAttributeSource.java index 0e063a3b90..3a845db8fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IndexedPluralAttributeSource.java @@ -21,17 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** - * Describes the nature of the collection elements as declared by the metadata. * - * @author Steve Ebersole */ -public enum PluralAttributeElementNature { - BASIC, - COMPONENT, - ONE_TO_MANY, - MANY_TO_MANY, - MANY_TO_ANY +public interface IndexedPluralAttributeSource extends PluralAttributeSource, PluralAttributeIndexSourceResolver { + + PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context); + + PluralAttributeIndexSource getIndexSource(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InvalidMappingException.java similarity index 58% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InvalidMappingException.java index a272eec5ad..143a2d485a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/InvalidMappingException.java @@ -21,37 +21,39 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; +package org.hibernate.metamodel.spi.source; + +import javassist.runtime.Desc; + +import org.hibernate.jaxb.spi.Origin; /** - * Represents the metamodel view of a typedef (type definition). - * - * @author John Verhaeg + * @author Brett Meyer */ -public class TypeDef implements Serializable { - private final String name; - private final String typeClass; - private final Map parameters; +public class InvalidMappingException extends org.hibernate.InvalidMappingException { - public TypeDef(String name, String typeClass, Map parameters) { - this.name = name; - this.typeClass = typeClass; - this.parameters = parameters; + private final Origin origin; + + public InvalidMappingException(Origin origin) { + super( + String.format( "Could not parse mapping document: %s (%s)", origin.getName(), origin.getType() ), + origin + ); + this.origin = origin; } - public String getName() { - return name; + public InvalidMappingException(Origin origin, Throwable e) { + super( + String.format( "Could not parse mapping document: %s (%s)", origin.getName(), origin.getType() ), + origin.getType().name(), + origin.getName(), + e + ); + this.origin = origin; } - public String getTypeClass() { - return typeClass; - } - - public Map getParameters() { - return Collections.unmodifiableMap(parameters); - } + public Origin getOrigin() { + return origin; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JoinedSubclassEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JoinedSubclassEntitySource.java new file mode 100644 index 0000000000..78ff2fc8ec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JoinedSubclassEntitySource.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +/** + * @author Strong Liu + */ +public interface JoinedSubclassEntitySource extends SubclassEntitySource, ForeignKeyContributingSource { + /** + * The {@code PrimaryKeyJoinColumns} mapping for the joined-subclass. + * + * @return The {@code PrimaryKeyJoinColumnSource} lists defined on the joined subclass or null otherwise. + */ + public List getPrimaryKeyColumnSources(); + boolean isCascadeDeleteEnabled(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JpaCallbackSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JpaCallbackSource.java index 5101befc4a..a2dfc23bbf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/JpaCallbackSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import javax.persistence.Entity; import javax.persistence.EntityListeners; @@ -34,7 +34,7 @@ import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; -public interface JpaCallbackClass { +public interface JpaCallbackSource { /** * @param callbackType {@link PrePersist}, {@link PreRemove}, {@link PreUpdate}, {@link PostLoad}, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/LocalBindingContext.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/LocalBindingContext.java index 818beba54c..1c977812f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/LocalBindingContext.java @@ -21,13 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.jaxb.spi.Origin; /** * @author Steve Ebersole */ public interface LocalBindingContext extends BindingContext { public Origin getOrigin(); + public MappingException makeMappingException(String message); + public MappingException makeMappingException(String message, Exception cause); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToAnyPluralAttributeElementSource.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToAnyPluralAttributeElementSource.java index 89d49a8a05..39534c9feb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToAnyPluralAttributeElementSource.java @@ -21,10 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole */ -public interface ManyToAnyPluralAttributeElementSource extends PluralAttributeElementSource { +public interface ManyToAnyPluralAttributeElementSource + extends PluralAttributeElementSource, AssociationSource { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToManyPluralAttributeElementSource.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToManyPluralAttributeElementSource.java index e1c9cfb8ae..16099cadc3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ManyToManyPluralAttributeElementSource.java @@ -21,28 +21,30 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import java.util.List; +import java.util.Collection; -import org.hibernate.FetchMode; +import org.hibernate.engine.FetchTiming; /** * @author Steve Ebersole */ -public interface ManyToManyPluralAttributeElementSource extends PluralAttributeElementSource { +public interface ManyToManyPluralAttributeElementSource + extends PluralAttributeElementSource, AssociationSource, RelationalValueSourceContainer, ForeignKeyContributingSource, Orderable { public String getReferencedEntityName(); + public String getReferencedEntityAttributeName(); - public List getValueSources(); // these describe the "outgoing" link - public boolean isNotFoundAnException(); + public String getExplicitForeignKeyName(); + public boolean isUnique(); - public String getOrderBy(); + public FilterSource[] getFilterSources(); + public String getWhere(); - public FetchMode getFetchMode(); - public boolean fetchImmediately(); + public FetchTiming getFetchTiming(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappedByAssociationSource.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappedByAssociationSource.java index d8fb1ff8bd..89531e7c24 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappedByAssociationSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,10 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; +package org.hibernate.metamodel.spi.source; /** * @author Gail Badner */ -public interface ValueRelationalState { +public interface MappedByAssociationSource extends AssociationSource { + + String getMappedBy(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingDefaults.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingDefaults.java index bb66dc64f0..063e1eb8c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingDefaults.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; import org.hibernate.cache.spi.access.AccessType; @@ -62,6 +62,13 @@ public interface MappingDefaults { */ public String getIdColumnName(); + /** + * Identifies the default column name to use for the tenant identifier column if non is specified in the mapping. + * + * @return The default tenant identifier column name + */ + public String getTenantIdColumnName(); + /** * Identifies the default column name to use for the discriminator column if none specified in the mapping. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingException.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingException.java index 47bd55cf87..d4935c64d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingException.java @@ -22,17 +22,16 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; -import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.jaxb.spi.Origin; /** * Indicates a problem parsing a mapping document. * * @author Steve Ebersole */ -public class MappingException extends HibernateException { +public class MappingException extends org.hibernate.MappingException { private final Origin origin; public MappingException(String message, Origin origin) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingNotFoundException.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingNotFoundException.java index a0702f165e..ad8ff54e10 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MappingNotFoundException.java @@ -22,9 +22,9 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.jaxb.spi.Origin; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeContext.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeContext.java index 461c031863..f9488cffe3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeContext.java @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.hibernate.metamodel.binding.MetaAttribute; +import org.hibernate.metamodel.spi.binding.MetaAttribute; /** * @author Steve Ebersole @@ -67,7 +67,7 @@ public class MetaAttributeContext { public MetaAttribute getMetaAttribute(String key) { MetaAttribute value = getLocalMetaAttribute( key ); - if ( value == null ) { + if ( value == null && parentContext != null ) { // recursive call value = parentContext.getMetaAttribute( key ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeSource.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeSource.java index ab44fc4a23..27be34082c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaAttributeSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * Describes incoming {@link org.hibernate.mapping.MetaAttribute} values. This is only from {@code hbm} via the diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaSource.java new file mode 100644 index 0000000000..aa88970309 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MetaSource.java @@ -0,0 +1,36 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Strong Liu + */ +public interface MetaSource { + /** + * Obtain the meta-attribute sources associated with this attribute. + * + * @return The meta-attribute sources. + */ + public Iterable getMetaAttributeSources(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MultiTenancySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MultiTenancySource.java new file mode 100644 index 0000000000..9c534adb32 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/MultiTenancySource.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Steve Ebersole + */ +public interface MultiTenancySource { + /** + * Obtain the column/formula information about the multi-tenancy discriminator. + * + * @return The column/formula information + */ + public RelationalValueSource getRelationalValueSource(); + + public boolean isShared(); + + public boolean bindAsParameter(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java new file mode 100644 index 0000000000..8c9a9da8a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +/** + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#NON_AGGREGATED_COMPOSITE }. + * + * @author Steve Ebersole + */ +public interface NonAggregatedCompositeIdentifierSource extends CompositeIdentifierSource { + /** + * Retrieve the class specified as the {@link javax.persistence.IdClass}, if one. + * + * @return The class specified as the {@link javax.persistence.IdClass}, or {@code null} if none. + */ + public Class getLookupIdClass(); + + /** + * Obtain the property accessor name for the {@link javax.persistence.IdClass}, if one. + * + * @return The property accessor name for the {@link javax.persistence.IdClass}, or {@code null} if none. + **/ + public String getIdClassPropertyAccessorName(); + + /** + * Obtain the source descriptor for the identifier attribute. + * + * @return The identifier attribute source. + */ + public List getAttributeSourcesMakingUpIdentifier(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/OneToManyPluralAttributeElementSource.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/OneToManyPluralAttributeElementSource.java index aecc755706..d4f5e8f57f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/OneToManyPluralAttributeElementSource.java @@ -21,12 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole */ -public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource { +public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource { public String getReferencedEntityName(); + public boolean isNotFoundAnException(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Orderable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Orderable.java new file mode 100644 index 0000000000..f7b35c2b93 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Orderable.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Contact to define if a plural attribute source is orderable or not. + * + * @author Steve Ebersole + */ +public interface Orderable { + /** + * If the source of plural attribute is supposed to be applied the order by when loading. + * + * @return true for applying the order by or false means not. + */ + boolean isOrdered(); + + /** + * The order by clause used during loading this plural attribute. + * + *

+ * If the ordering element is not specified, ordering by + * the primary key of the associated entity is assumed + * + * {@see javax.persistence.OrderBy#value()} + * + * @return The order by clause used during loading this plural attribute from DB. + */ + String getOrder(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSource.java similarity index 66% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSource.java index 5d0f84c216..4011731b30 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSource.java @@ -21,24 +21,35 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole * @author Gail Badner */ -public class BasicCollectionElement extends AbstractCollectionElement { - private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); +public interface PluralAttributeElementSource { + public Nature getNature(); - public BasicCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } + /** + * Describes the nature of the collection elements as declared by the metadata. + * + * @author Steve Ebersole + */ + enum Nature { + BASIC( false ), + AGGREGATE( false ), + ONE_TO_MANY( true ), + MANY_TO_MANY( true ), + MANY_TO_ANY( true ); - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.BASIC; - } + private final boolean isAssociation; - public HibernateTypeDescriptor getHibernateTypeDescriptor() { - return hibernateTypeDescriptor; + private Nature(boolean isAssociation) { + this.isAssociation = isAssociation; + } + + public boolean isAssociation() { + return isAssociation; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSourceResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSourceResolver.java new file mode 100644 index 0000000000..efd1573102 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeElementSourceResolver.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Gail Badner + */ +public interface PluralAttributeElementSourceResolver { + PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSource.java new file mode 100644 index 0000000000..cf978acc3d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSource.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; + +/** + * + */ +public interface PluralAttributeIndexSource extends RelationalValueSourceContainer { + PluralAttributeIndexBinding.Nature getNature(); + List getDefaultNamingStrategies(); + /** + * Obtain information about the Hibernate index type ({@link org.hibernate.type.Type}) + * for this plural attribute index. + * + * @return The Hibernate type information + */ + public HibernateTypeSource getTypeInformation(); + + /** + * Is this plural attribute index source for an attribute of the referenced entity + * (relevant only for one-to-many and many-to-many associations)? + * + * If this method returns {@code true}, then this object can safely + * be cast to EntityAttributePluralAttributeIndexSource. + * + * @return true, if this plural attribute index source for an attribute of the referenced + * entity; false, otherwise. + */ + public boolean isReferencedEntityAttribute(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSourceResolver.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSourceResolver.java index c441b3e621..b397733a26 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeIndexSourceResolver.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,13 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; +package org.hibernate.metamodel.spi.source; /** * @author Gail Badner */ -public interface ManyToOneRelationalState extends ValueRelationalState { - boolean isLogicalOneToOne(); - - String getForeignKeyName(); +public interface PluralAttributeIndexSourceResolver { + PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeKeySource.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeKeySource.java index 815a7828fa..467262067f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeKeySource.java @@ -21,18 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import java.util.List; - -import org.hibernate.metamodel.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.ForeignKey; /** + * Describes the source mapping of plural-attribute (collection) foreign-key information. + * * @author Steve Ebersole */ -public interface PluralAttributeKeySource { - public List getValueSources(); - public String getExplicitForeignKeyName(); +public interface PluralAttributeKeySource extends ForeignKeyContributingSource, RelationalValueSourceContainer { public ForeignKey.ReferentialAction getOnDeleteAction(); - public String getReferencedEntityAttributeName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeSource.java similarity index 57% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeSource.java index 2f19b86b61..085ca831a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/PluralAttributeSource.java @@ -21,41 +21,48 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; /** * @author Steve Ebersole */ -public interface PluralAttributeSource extends AssociationAttributeSource { - public PluralAttributeNature getPluralAttributeNature(); +public interface PluralAttributeSource + extends AttributeSource, FetchableAttributeSource, PluralAttributeElementSourceResolver { + public Nature getNature(); public PluralAttributeKeySource getKeySource(); public PluralAttributeElementSource getElementSource(); - public String getExplicitSchemaName(); - public String getExplicitCatalogName(); - public String getExplicitCollectionTableName(); + public FilterSource[] getFilterSources(); + + public ValueHolder> getElementClassReference(); + + public TableSpecificationSource getCollectionTableSpecificationSource(); public String getCollectionTableComment(); + public String getCollectionTableCheck(); public Caching getCaching(); - /** - * Obtain the name of a custom persister class to be used. - * - * @return The custom persister class name - */ public String getCustomPersisterClassName(); public String getWhere(); public boolean isInverse(); + public boolean isMutable(); + public String getCustomLoaderName(); public CustomSQL getCustomSqlInsert(); @@ -65,4 +72,34 @@ public interface PluralAttributeSource extends AssociationAttributeSource { public CustomSQL getCustomSqlDelete(); public CustomSQL getCustomSqlDeleteAll(); + + public String getMappedBy(); + + public int getBatchSize(); + + public boolean usesJoinTable(); + + /** + * Describes the nature of the collection itself as declared by the metadata. + * + * @author Steve Ebersole + */ + enum Nature { + BAG( Collection.class ), + ID_BAG( Collection.class ), + SET( Set.class ), + LIST( List.class ), + MAP( Map.class ), + ARRAY( Object[].class ); + + private final Class reportedJavaType; + + Nature(Class reportedJavaType) { + this.reportedJavaType = reportedJavaType; + } + + public Class reportedJavaType() { + return reportedJavaType; + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java new file mode 100644 index 0000000000..a3608a169b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * Unifying interface for {@link ColumnSource} and {@link DerivedValueSource}. + * + * @author Steve Ebersole + * + * @see ColumnSource + * @see DerivedValueSource + */ +public interface RelationalValueSource { + /** + * @return returns the name of the table that contains this value. + */ + public String getContainingTableName(); + + /** + * Retrieve the nature of this relational value. Is it a column? Or is it a derived value (formula)? + * + * @return The nature. + */ + public Nature getNature(); + + public static enum Nature { + COLUMN( ColumnSource.class ), + DERIVED( DerivedValueSource.class ); + + private final Class specificContractClass; + + private Nature(Class specificContractClass) { + this.specificContractClass = specificContractClass; + } + + public Class getSpecificContractClass() { + return specificContractClass; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSourceContainer.java new file mode 100644 index 0000000000..cc1723dd2c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSourceContainer.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +/** + * Contract for a container of {@link RelationalValueSource} references. Multiple types of things operate as sources + * of "relational value" information; some examples include:

    + *
  • id attribute(s) mappings
  • + *
  • basic attribute mappings
  • + *
  • composite attribute mappings
  • + *
  • plural attribute mappings
  • + *
  • etc
  • + *
+ * + * Not only does it provide access to the relational value sources ({@link #relationalValueSources()}, it also defines + * contextual information for those sources in terms of default values. + * + * See {@link RelationalValueSource} for additional details. + * + * @author Steve Ebersole + */ +public interface RelationalValueSourceContainer extends ColumnBindingDefaults { + /** + * Obtain the contained {@link RelationalValueSource} references. + * + * @return The contained {@link RelationalValueSource} references. + */ + public List relationalValueSources(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java index 6d18eccd02..30fca394ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java @@ -21,17 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import org.hibernate.EntityMode; import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.metamodel.binding.Caching; +import org.hibernate.metamodel.spi.binding.Caching; /** * Contract for the entity that is the root of an inheritance hierarchy. *

* NOTE : I think most of this could be moved to {@link EntityHierarchy} much like was done with - * {@link org.hibernate.metamodel.binding.HierarchyDetails} + * {@link org.hibernate.metamodel.spi.binding.HierarchyDetails} * * @author Steve Ebersole * @@ -50,7 +50,7 @@ public interface RootEntitySource extends EntitySource { * * @return the source information about the attribute used for versioning */ - public SingularAttributeSource getVersioningAttributeSource(); + public VersionAttributeSource getVersioningAttributeSource(); /** * Obtain the source information about the discriminator attribute for single table inheritance @@ -59,6 +59,13 @@ public interface RootEntitySource extends EntitySource { */ public DiscriminatorSource getDiscriminatorSource(); + /** + * Obtain the source information about the multi-tenancy discriminator for this entity + * + * @return the source information about the multi-tenancy discriminator for this entity + */ + public MultiTenancySource getMultiTenancySource(); + /** * Obtain the entity mode for this entity. * @@ -107,4 +114,12 @@ public interface RootEntitySource extends EntitySource { * @return The caching configuration. */ public Caching getCaching(); + + /** + * Obtain the natural id caching configuration for this entity. + * + * @return The natural id caching configuration. + */ + public Caching getNaturalIdCaching(); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SecondaryTableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SecondaryTableSource.java new file mode 100644 index 0000000000..548b6f2b15 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SecondaryTableSource.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +/** + * @author Steve Ebersole + */ +public interface SecondaryTableSource extends ForeignKeyContributingSource { + /** + * Obtain the table being joined to. + * + * @return The joined table. + */ + public TableSpecificationSource getTableSource(); + + /** + * Retrieves the columns defines as making up this secondary tables primary key. Each entry should have + * a corresponding entry in the foreign-key columns described by the {@link ForeignKeyContributingSource} + * aspect of this contract. + * + * @return The columns defining the primary key for this secondary table + */ + public List getPrimaryKeyColumnSources(); + + public String getComment(); + + public FetchStyle getFetchStyle(); + + public boolean isInverse(); + + public boolean isOptional(); + + public boolean isCascadeDeleteEnabled(); + + /** + * Obtain the custom SQL to be used for inserts for this entity + * + * @return The custom insert SQL + */ + public CustomSQL getCustomSqlInsert(); + + /** + * Obtain the custom SQL to be used for updates for this entity + * + * @return The custom update SQL + */ + public CustomSQL getCustomSqlUpdate(); + + /** + * Obtain the custom SQL to be used for deletes for this entity + * + * @return The custom delete SQL + */ + public CustomSQL getCustomSqlDelete(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SequentialPluralAttributeIndexSource.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SequentialPluralAttributeIndexSource.java index 19021f58c3..10a5047a1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SequentialPluralAttributeIndexSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,11 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational.state; +package org.hibernate.metamodel.spi.source; /** * @author Gail Badner */ -public interface DerivedValueRelationalState extends SimpleValueRelationalState { - String getFormula(); +public interface SequentialPluralAttributeIndexSource extends BasicPluralAttributeIndexSource { + int base(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java similarity index 86% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java index 90585ae216..00944cdf43 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java @@ -21,10 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** - * Contract describing source of a simple identifier mapping. + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE simple}. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java similarity index 74% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java index 33978afb0f..93d21efe62 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,16 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; /** * Source-agnostic description of information needed to bind a singular attribute. * * @author Steve Ebersole */ -public interface SingularAttributeSource extends AttributeSource, RelationalValueSourceContainer { +public interface SingularAttributeSource extends AttributeSource, AttributeRelationalValueSourceContainer { /** * Determine whether this is a virtual attribute or whether it physically exists on the users domain model. * @@ -44,23 +45,7 @@ public interface SingularAttributeSource extends AttributeSource, RelationalValu * * @return The attribute type nature */ - public SingularAttributeNature getNature(); - - /** - * Determine whether this attribute is insertable. - * - * @return {@code true} indicates the attribute value should be used in the {@code SQL INSERT}; {@code false} - * indicates it should not. - */ - public boolean isInsertable(); - - /** - * Determine whether this attribute is updateable. - * - * @return {@code true} indicates the attribute value should be used in the {@code SQL UPDATE}; {@code false} - * indicates it should not. - */ - public boolean isUpdatable(); + public Nature getNature(); /** * Obtain a description of if/when the attribute value is generated by the database. @@ -75,4 +60,27 @@ public interface SingularAttributeSource extends AttributeSource, RelationalValu * @return {@code true} to indicate the attribute should be lazily loaded. */ public boolean isLazy(); + + /** + * Retrieve the natural id mutability + * + * @return The mutability, see enum for meanings + */ + public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability(); + + /** + * Describes the understood natures of a singular attribute. + * + * @author Steve Ebersole + */ + enum Nature { + BASIC, + // TODO: COMPOSITE should be changed to AGGREGATE + // when non-aggregated composite IDs are no longer + // modelled as an AttributeBinding + COMPOSITE, + MANY_TO_ONE, + ONE_TO_ONE, + ANY + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SizeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SizeSource.java new file mode 100644 index 0000000000..a74aa9f244 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SizeSource.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Gail Badner + */ +public interface SizeSource { + /** + * Is length defined? + * + * @return true, if length is defined; false, otherwise. + */ + boolean isLengthDefined(); + + /** + * If length is defined (as determined by {@link #isLengthDefined()}), then + * the length is returned. + * + * @return the length, if defined. + * @throws UnsupportedOperationException if length is not defined. + */ + int getLength(); + + /** + * Is precision defined? + * + * @return true, if precision is defined; false, otherwise. + */ + boolean isPrecisionDefined(); + + /** + * If precision is defined (as determined by {@link #isPrecisionDefined()}), then + * the precision is returned. + * + * @return the precision, if defined. + * @throws UnsupportedOperationException if precision is not defined. + * + * @see {@link #isPrecisionDefined()} + */ + int getPrecision(); + + /** + * Is scale defined? + * + * @return true, if scale is defined; false, otherwise. + */ + boolean isScaleDefined(); + + + /** + * If scale is defined (as determined by {@link #isScaleDefined()}), then + * the scale is returned. + * + * @return the scale, if defined. + * @throws UnsupportedOperationException if scale is not defined. + * + * @see {@link #isScaleDefined()} + */ + int getScale(); + + SizeSource NULL = new SizeSource() { + @Override + public boolean isLengthDefined() { + return false; + } + + @Override + public int getLength() { + return 0; + } + + @Override + public boolean isPrecisionDefined() { + return false; + } + + @Override + public int getPrecision() { + return 0; + } + + @Override + public boolean isScaleDefined() { + return false; + } + + @Override + public int getScale() { + return 0; + } + }; + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Sortable.java similarity index 66% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Sortable.java index 5a167f44e0..bad33ea2e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/Sortable.java @@ -21,26 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; +package org.hibernate.metamodel.spi.source; /** - * Contract for a container of {@link RelationalValueSource} references. + * Contact to define if the source of plural attribute is sortable or not. * * @author Steve Ebersole */ -public interface RelationalValueSourceContainer { - public boolean areValuesIncludedInInsertByDefault(); - - public boolean areValuesIncludedInUpdateByDefault(); - - public boolean areValuesNullableByDefault(); +public interface Sortable { + /** + * If the source of plural attribute is supposed to be sorted. + * + * @return true the attribute will be sortable or false means not. + */ + boolean isSorted(); /** - * Obtain the contained {@link RelationalValueSource} references. + * The comparator class name which will be used to sort the attribute. * - * @return The contained {@link RelationalValueSource} references. + * @return Qualified class name which implements {@link java.util.Comparator} contact. */ - public List relationalValueSources(); + String getComparatorName(); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntityContainer.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntityContainer.java index a73a9ed283..9f9120263d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntityContainer.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * Contract for elements within a {@link EntityHierarchy} which can contain sub elements. Essentially this diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntitySource.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntitySource.java index 636226758e..e83b3ec69f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SubclassEntitySource.java @@ -21,10 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole + * @author Strong Liu */ public interface SubclassEntitySource extends EntitySource { + /** + * @return the entity source for the entity that is a superclass of the entity for which this is a source + */ + EntitySource superclassEntitySource(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSource.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSource.java index b620838605..62f66e9bb4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSource.java @@ -21,17 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** - * Describes the understood natures of a singular attribute. + * Contract describing source of table information * * @author Steve Ebersole */ -public enum SingularAttributeNature { - BASIC, - COMPONENT, - MANY_TO_ONE, - ONE_TO_ONE, - ANY +public interface TableSource extends TableSpecificationSource { + /** + * Obtain the supplied table name. + * + * @return The table name, or {@code null} is no name specified. + */ + String getExplicitTableName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSpecificationSource.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSpecificationSource.java index ff18012e29..3360486313 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TableSpecificationSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,14 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** - * Contract describing source of table information + * Contract describing source of "table specification" information. * * @author Steve Ebersole + * + * @see org.hibernate.metamodel.spi.relational.TableSpecification */ -public interface TableSource { +public interface TableSpecificationSource { /** * Obtain the supplied schema name * @@ -42,21 +44,4 @@ public interface TableSource { * @return The catalog name. If {@code null}, the binder will apply the default. */ public String getExplicitCatalogName(); - - /** - * Obtain the supplied table name. - * - * @return The table name. - */ - public String getExplicitTableName(); - - /** - * Obtain the logical name of the table. This value is used to uniquely reference the table when binding - * values to the binding model. - * - * @return The logical name. Can be {@code null} in the case of the "primary table". - * - * @see RelationalValueSource#getContainingTableName() - */ - public String getLogicalName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java similarity index 62% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java index 91d408037d..309779d78b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java @@ -21,27 +21,28 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.metamodel.internal.Binder; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.type.ForeignKeyDirection; /** * Further contract for sources of {@code *-to-one} style associations. * * @author Steve Ebersole */ -public interface ToOneAttributeSource extends SingularAttributeSource, AssociationAttributeSource { - /** - * Obtain the name of the referenced entity. - * - * @return The name of the referenced entity - */ - public String getReferencedEntityName(); +public interface ToOneAttributeSource + extends SingularAttributeSource, + ToOneAttributeSourceNatureResolver, + ForeignKeyContributingSource, + FetchableAttributeSource, + AssociationSource { - /** - * Obtain the name of the referenced attribute. Typically the reference is built based on the identifier - * attribute of the {@link #getReferencedEntityName() referenced entity}, but this value allows using a different - * attribute instead. - * - * @return The name of the referenced attribute; {@code null} indicates the identifier attribute. - */ - public String getReferencedEntityAttributeName(); + public boolean isUnique(); + public boolean isUnWrapProxy(); + ForeignKeyDirection getForeignKeyDirection(); + public List getDefaultNamingStrategies(final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSourceNatureResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSourceNatureResolver.java new file mode 100644 index 0000000000..9ae901ec36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSourceNatureResolver.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.List; + +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.relational.Column; + +/** + * @author Gail Badner + */ +public interface ToOneAttributeSourceNatureResolver { + + /** + * Perform any steps to completely resolve this attribute source. + * + * If this is a {@link MappedByAssociationSource}, resolution must + * resolve the association owner, and this association must be added + * to the owner's "owned" associations. + * + * @param context + */ + void resolveToOneAttributeSource(AttributeSourceResolutionContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TypeDescriptorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TypeDescriptorSource.java new file mode 100644 index 0000000000..a9cb9dfeeb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/TypeDescriptorSource.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +import java.util.Map; + +/** + * Describes the source of a custom type description. For example, {@code } or + * {@link org.hibernate.annotations.TypeDef @TypeDefinition} + * + * @author Steve Ebersole + */ +public interface TypeDescriptorSource { + /** + * Retrieve the name of the type def. + * + * @return The name. + */ + String getName(); + + /** + * Retrieve the name of the class implementing {@link org.hibernate.type.Type}, + * {@link org.hibernate.usertype.UserType}, etc. + * + * @return The implementation class name. + */ + String getTypeImplementationClassName(); + + /** + * For what are termed "basic types" there is a registry that contain the type keyed by various + * keys. This is the mechanism that allows a "string type" to reference to by "string", "java.lang.String", + * etc in the mapping. This method returns the keys under which this type should be registered in + * that registry. + *

+ * Note that if the type def contains registration keys, it should be considered illegal for its + * corresponding {@link HibernateTypeSource} to define parameters. + * + * @return The registration keys for the type built from this type def. + */ + String[] getRegistrationKeys(); + + /** + * Types accept configuration. The values here represent the user supplied values that will be given + * to the type instance after instantiation + * + * @return The configuration parameters from the underlying source. + */ + Map getParameters(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/UniqueConstraintSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/UniqueConstraintSource.java index 0a247b09cf..66c0b6b57a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/UniqueConstraintSource.java @@ -21,7 +21,8 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; + /** * Defining a unique constraint source diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java index aeb60a31ea..a7c5fbce66 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,12 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi.source; /** * @author Steve Ebersole */ -public interface PluralAttributeElementSource { - public PluralAttributeElementNature getNature(); - +public interface VersionAttributeSource extends SingularAttributeSource { + public String getUnsavedValue(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/XsdException.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/XsdException.java index fac0104bf9..a375274a41 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/XsdException.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.spi.source; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 70e0647ce6..a6fcaa48b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -28,6 +28,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -48,6 +49,8 @@ import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; import org.hibernate.cfg.Configuration; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.spi.EntityKey; @@ -61,6 +64,7 @@ import org.hibernate.exception.spi.SQLExceptionConverter; import org.hibernate.id.IdentifierGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.FilterAliasGenerator; +import org.hibernate.internal.FilterConfiguration; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; @@ -76,6 +80,21 @@ import org.hibernate.mapping.List; import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Table; import org.hibernate.metadata.CollectionMetadata; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.ListBinding; +import org.hibernate.metamodel.spi.binding.ManyToManyPluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.PropertyMapping; @@ -107,6 +126,7 @@ import org.hibernate.type.AssociationType; import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; +import org.hibernate.type.PrimitiveType; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -616,6 +636,400 @@ public abstract class AbstractCollectionPersister initCollectionPropertyMap(); } + public AbstractCollectionPersister( + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { + + this.factory = factory; + this.cacheAccessStrategy = cacheAccessStrategy; + if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) { + cacheEntryStructure = collection.getAttribute().getNature() == PluralAttribute.Nature.MAP ? + StructuredMapCacheEntry.INSTANCE + : StructuredCollectionCacheEntry.INSTANCE; + } + else { + cacheEntryStructure = UnstructuredCacheEntry.INSTANCE; + } + + + dialect = factory.getDialect(); + sqlExceptionHelper = factory.getSQLExceptionHelper(); + if ( !collection.getHibernateTypeDescriptor().getResolvedTypeMapping().isCollectionType() ) { + throw new MappingException( + String.format( + "Unexpected resolved type for %s; expected a CollectionType; instead it is %s", + collection.getAttribute().getRole(), + collection.getHibernateTypeDescriptor().getResolvedTypeMapping() ) + ); + } + + collectionType = (CollectionType) collection.getHibernateTypeDescriptor().getResolvedTypeMapping(); + role = collection.getAttribute().getRole(); + entityName = collection.getContainer().seekEntityBinding().getEntity().getName(); + ownerPersister = factory.getEntityPersister( entityName ); + queryLoaderName = collection.getCustomLoaderName(); + // TODO: is nodeName obsolete? + //nodeName = collection.getNodeName(); + nodeName = null; + isMutable = collection.isMutable(); + + TableSpecification table = collection.getPluralAttributeKeyBinding().getCollectionTable(); + fetchMode = collection.getPluralAttributeElementBinding().getFetchMode(); + elementType = collection.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(); + // isSet = collection.isSet(); + // isSorted = collection.isSorted(); + isArray = collectionType.isArrayType(); + isPrimitiveArray = + isArray && + PrimitiveType.class.isInstance( + collection.getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping() + ); + subselectLoadable = collection.getFetchStyle() == FetchStyle.SUBSELECT; + + qualifiedTableName = table.getQualifiedName( dialect ); + + // TODO: fix this when synchronized tables are available + spaces = new String[1]; + spaces[0] = qualifiedTableName; + //int spacesSize = 1 + collection.getSynchronizedTables().size(); + //spaces = new String[spacesSize]; + //spaces[0] = qualifiedTableName; + //Iterator iter = collection.getSynchronizedTables().iterator(); + //for ( int i = 1; i < spacesSize; i++ ) { + // spaces[i] = (String) iter.next(); + //} + + sqlWhereString = StringHelper.isNotEmpty( collection.getWhere() ) ? "( " + collection.getWhere() + ") " : null; + hasWhere = sqlWhereString != null; + sqlWhereStringTemplate = hasWhere ? + Template.renderWhereStringTemplate( sqlWhereString, dialect, factory.getSqlFunctionRegistry() ) : + null; + + hasOrphanDelete = + collection.getPluralAttributeElementBinding() instanceof Cascadeable && + ( (Cascadeable) collection.getPluralAttributeElementBinding() ).getCascadeStyle().hasOrphanDelete(); + + int batch = collection.getBatchSize(); + if ( batch == -1 ) { + batch = factory.getSettings().getDefaultBatchFetchSize(); + } + batchSize = batch; + + isVersioned = collection.isIncludedInOptimisticLocking(); + + // KEY + + PluralAttributeKeyBinding keyBinding = collection.getPluralAttributeKeyBinding(); + keyType = keyBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + int keySpan = keyBinding.getRelationalValueBindings().size(); + keyColumnNames = new String[keySpan]; + keyColumnAliases = new String[keySpan]; + int k = 0; + for ( RelationalValueBinding keyRelationalValueBinding : keyBinding.getRelationalValueBindings() ) { + org.hibernate.metamodel.spi.relational.Column keyColumn = + (org.hibernate.metamodel.spi.relational.Column) keyRelationalValueBinding.getValue(); + // NativeSQL: collect key column and auto-aliases + keyColumnNames[k] = keyColumn.getColumnName().getText( dialect ); + // TODO: does the owner root table need to be in alias? + keyColumnAliases[k] = keyColumn.getAlias( + dialect, + collection.getContainer().seekEntityBinding().getPrimaryTable() + ); + // keyColumnAliases[k] = col.getAlias( dialect, collection.getOwner().getRootTable() ); + k++; + } + + // ELEMENT + + if ( elementType.isEntityType() ) { + String entityName = ( (EntityType) elementType ).getAssociatedEntityName(); + elementPersister = factory.getEntityPersister( entityName ); + } + else { + elementPersister = null; + } + elementNodeName = null; + int elementSpan = collection.getPluralAttributeElementBinding().getRelationalValueBindings() == null ? + 0 : + collection.getPluralAttributeElementBinding().getRelationalValueBindings().size(); + elementColumnAliases = new String[elementSpan]; + elementColumnNames = new String[elementSpan]; + elementColumnWriters = new String[elementSpan]; + elementColumnReaders = new String[elementSpan]; + elementColumnReaderTemplates = new String[elementSpan]; + elementFormulaTemplates = new String[elementSpan]; + elementFormulas = new String[elementSpan]; + elementColumnIsSettable = new boolean[elementSpan]; + elementColumnIsInPrimaryKey = new boolean[elementSpan]; + boolean isPureFormula = true; + boolean hasNotNullableColumns = false; + int j = 0; + if ( elementSpan > 0 ) { + for ( RelationalValueBinding relationalValueBinding : collection.getPluralAttributeElementBinding().getRelationalValueBindings() ) { + final Value value = relationalValueBinding.getValue(); + elementColumnAliases[j] = value.getAlias( dialect, table ); + if ( DerivedValue.class.isInstance( value ) ) { + DerivedValue form = (DerivedValue) value; + elementFormulaTemplates[j] = getTemplateFromString( form.getExpression(), factory); + elementFormulas[j] = form.getExpression(); + } + else { + org.hibernate.metamodel.spi.relational.Column col = + (org.hibernate.metamodel.spi.relational.Column) value; + elementColumnNames[j] = col.getColumnName().getText( dialect ); + elementColumnWriters[j] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); + elementColumnReaders[j] = col.getReadFragment() == null ? + col.getColumnName().getText( factory.getDialect() ) : + col.getReadFragment(); + elementColumnReaderTemplates[j] = getTemplateFromColumn( col, factory ); + elementColumnIsSettable[j] = true; + elementColumnIsInPrimaryKey[j] = !col.isNullable(); + if ( !col.isNullable() ) { + hasNotNullableColumns = true; + } + isPureFormula = false; + } + j++; + } + } + elementIsPureFormula = isPureFormula; + + // workaround, for backward compatibility of sets with no + // not-null columns, assume all columns are used in the + // row locator SQL + if ( !hasNotNullableColumns ) { + Arrays.fill( elementColumnIsInPrimaryKey, true ); + } + + // INDEX AND ROW SELECT + + hasIndex = collection.hasIndex(); + + indexNodeName = null; + + if ( hasIndex ) { + // NativeSQL: collect index column and auto-aliases + IndexedPluralAttributeBinding indexedBinding = (IndexedPluralAttributeBinding) collection; + PluralAttributeIndexBinding indexBinding = indexedBinding.getPluralAttributeIndexBinding(); + indexType = indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + baseIndex = indexBinding instanceof ListBinding ? ( ( ListBinding ) indexBinding ).base() : 0; + final java.util.List indexRelationalValueBindings = indexBinding.getRelationalValueBindings(); + int indexSpan = indexRelationalValueBindings.size(); + boolean hasFormulas = false; + indexColumnNames = new String[indexSpan]; + indexFormulaTemplates = new String[indexSpan]; + indexFormulas = new String[indexSpan]; + indexColumnIsSettable = new boolean[indexSpan]; + indexColumnAliases = new String[indexSpan]; + for ( int i = 0 ; i < indexSpan ; i++ ) { + final RelationalValueBinding rb = indexRelationalValueBindings.get( i ); + final Value value = rb.getValue(); + indexColumnAliases[ i ] = value.getAlias( dialect, + collection.getContainer().seekEntityBinding().getPrimaryTable() ); + if ( !rb.isDerived() ) { + indexColumnIsSettable[ i ] = true; + org.hibernate.metamodel.spi.relational.Column column = + ( org.hibernate.metamodel.spi.relational.Column ) value; + indexColumnNames[ i ] = column.getColumnName().getText( dialect ); + } else { + DerivedValue derivedValue = ( DerivedValue ) value; + indexFormulaTemplates[ i ] = getTemplateFromString( derivedValue.getExpression(), factory); + indexFormulas[ i ] = derivedValue.getExpression(); + hasFormulas = true; + } + } + this.indexContainsFormula = hasFormulas; + } else { + indexColumnIsSettable = null; + indexFormulaTemplates = null; + indexFormulas = null; + indexType = null; + indexColumnNames = null; + indexColumnAliases = null; + baseIndex = 0; + indexContainsFormula = false; + } + + hasIdentifier = collection.getAttribute().getNature() == PluralAttribute.Nature.IDBAG; + // TODO: fix this when IdBags are supported. + //if ( hasIdentifier ) { + //} + //else { + identifierType = null; + identifierColumnName = null; + identifierColumnAlias = null; + // unquotedIdentifierColumnName = null; + identifierGenerator = null; + //} + + // GENERATE THE SQL: + + // sqlSelectString = sqlSelectString(); + // sqlSelectRowString = sqlSelectRowString(); + + if ( collection.getCustomSqlInsert() == null ) { + sqlInsertRowString = generateInsertRowString(); + insertCallable = false; + insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; + } + else { + final CustomSQL customSqlInsert = collection.getCustomSqlInsert(); + sqlInsertRowString = customSqlInsert.getSql(); + insertCallable = customSqlInsert.isCallable(); + insertCheckStyle = customSqlInsert.getCheckStyle() == null + ? ExecuteUpdateResultCheckStyle.determineDefault( customSqlInsert.getSql(), insertCallable ) + : customSqlInsert.getCheckStyle(); + } + + if ( collection.getCustomSqlUpdate() == null ) { + sqlUpdateRowString = generateUpdateRowString(); + updateCallable = false; + updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; + } + else { + final CustomSQL customSqlUpdate = collection.getCustomSqlUpdate(); + sqlUpdateRowString = customSqlUpdate.getSql(); + updateCallable = customSqlUpdate.isCallable(); + updateCheckStyle = customSqlUpdate.getCheckStyle() == null + ? ExecuteUpdateResultCheckStyle.determineDefault( customSqlUpdate.getSql(), insertCallable ) + : customSqlUpdate.getCheckStyle(); + } + + if ( collection.getCustomSqlDelete() == null ) { + sqlDeleteRowString = generateDeleteRowString(); + deleteCallable = false; + deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; + } + else { + final CustomSQL customSqlDelete = collection.getCustomSqlDelete(); + sqlDeleteRowString = customSqlDelete.getSql(); + deleteCallable = customSqlDelete.isCallable(); + deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; + } + + if ( collection.getCustomSqlDeleteAll() == null ) { + sqlDeleteString = generateDeleteString(); + deleteAllCallable = false; + deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; + } + else { + final CustomSQL customSqlDeleteAll = collection.getCustomSqlDeleteAll(); + sqlDeleteString = customSqlDeleteAll.getSql(); + deleteAllCallable = customSqlDeleteAll.isCallable(); + deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; + } + + sqlSelectSizeString = generateSelectSizeString( + collection.hasIndex() && + collection.getAttribute().getNature() != PluralAttribute.Nature.MAP + ); + sqlDetectRowByIndexString = generateDetectRowByIndexString(); + sqlDetectRowByElementString = generateDetectRowByElementString(); + sqlSelectRowByIndexString = generateSelectRowByIndexString(); + + logStaticSQL(); + + isLazy = collection.getFetchTiming() != FetchTiming.IMMEDIATE; + isExtraLazy = collection.getFetchTiming() == FetchTiming.EXTRA_LAZY; + + isInverse = keyBinding.isInverse(); + if ( isArray ) { + elementClass = collection.getAttribute().getElementType().getClassReference(); + } + else { + // for non-arrays, we don't need to know the element class + elementClass = null; // elementType.returnedClass(); + } + + if ( elementType.isComponentType() ) { + elementPropertyMapping = new CompositeElementPropertyMapping( + elementColumnNames, + elementColumnReaders, + elementColumnReaderTemplates, + elementFormulaTemplates, + (CompositeType) elementType, + factory + ); + } + else if ( !elementType.isEntityType() ) { + elementPropertyMapping = new ElementPropertyMapping( + elementColumnNames, + elementType + ); + } + else { + if ( elementPersister instanceof PropertyMapping ) { // not all classpersisters implement PropertyMapping! + elementPropertyMapping = (PropertyMapping) elementPersister; + } + else { + elementPropertyMapping = new ElementPropertyMapping( + elementColumnNames, + elementType + ); + } + } + + hasOrder = collection.getOrderBy() != null; + if ( hasOrder ) { + orderByTranslation = Template.translateOrderBy( + collection.getOrderBy(), + new ColumnMapperImpl(), + factory, + dialect, + factory.getSqlFunctionRegistry() + ); + } + else { + orderByTranslation = null; + } + + // Handle any filters applied to this collection + filterHelper = new FilterHelper( collection.getFilterConfigurations(), factory ); + + if ( collection.getPluralAttributeElementBinding() + .getNature() == PluralAttributeElementBinding.Nature.MANY_TO_MANY ) { + final ManyToManyPluralAttributeElementBinding manyToManyElementBinding = + (ManyToManyPluralAttributeElementBinding) collection.getPluralAttributeElementBinding(); + manyToManyFilterHelper = new FilterHelper( manyToManyElementBinding.getFilterConfigurations(), factory ); + manyToManyWhereString = StringHelper.isNotEmpty( manyToManyElementBinding.getManyToManyWhere() ) ? + "( " +manyToManyElementBinding.getManyToManyWhere() + ")" : + null; + manyToManyWhereTemplate = manyToManyWhereString == null ? + null : + Template.renderWhereStringTemplate( + manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() + ); + + hasManyToManyOrder = manyToManyElementBinding.getManyToManyOrderBy() != null; + if ( hasManyToManyOrder ) { + manyToManyOrderByTranslation = Template.translateOrderBy( + manyToManyElementBinding.getManyToManyOrderBy(), + new ColumnMapperImpl(), + factory, + dialect, + factory.getSqlFunctionRegistry() + ); + } + else { + manyToManyOrderByTranslation = null; + } + } + else { + manyToManyFilterHelper = new FilterHelper( Collections.emptyList(), factory ); + manyToManyWhereString = null; + manyToManyWhereTemplate = null; + hasManyToManyOrder = false; + manyToManyOrderByTranslation = null; + } + + initCollectionPropertyMap(); + } + private class ColumnMapperImpl implements ColumnMapper { @Override public SqlValueReference[] map(String reference) { @@ -671,6 +1085,24 @@ public abstract class AbstractCollectionPersister } } + protected static String getTemplateFromString(String string, SessionFactoryImplementor factory) { + return string == null ? + null : + Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() ); + } + + public String getTemplateFromColumn(org.hibernate.metamodel.spi.relational.Column column, SessionFactoryImplementor factory) { + String templateString; + if ( column.getReadFragment() != null ) { + templateString = getTemplateFromString( column.getReadFragment(), factory ); + } + else { + String columnName = column.getColumnName().getText( factory.getDialect() ); + templateString = Template.TEMPLATE + '.' + columnName; + } + return templateString; + } + @Override public void postInstantiate() throws MappingException { initializer = queryLoaderName == null ? diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index c0b7582a2b..c77ec9f21b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -50,6 +50,8 @@ import org.hibernate.loader.collection.BatchingCollectionInitializerBuilder; import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.SubselectCollectionLoader; import org.hibernate.mapping.Collection; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; import org.hibernate.persister.entity.Joinable; import org.hibernate.pretty.MessageHelper; import org.hibernate.sql.Delete; @@ -77,6 +79,15 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { super( collection, cacheAccessStrategy, cfg, factory ); } + @SuppressWarnings( {"UnusedDeclaration"}) + public BasicCollectionPersister( + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { + super( collection, cacheAccessStrategy, metadataImplementor, factory ); + } + /** * Generate the SQL DELETE that deletes all rows */ diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index cf86a134e7..7728ffb4ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -50,6 +50,10 @@ import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.SubselectOneToManyLoader; import org.hibernate.loader.entity.CollectionElementLoader; import org.hibernate.mapping.Collection; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.pretty.MessageHelper; @@ -93,6 +97,29 @@ public class OneToManyPersister extends AbstractCollectionPersister { keyIsUpdateable = collection.getKey().isUpdateable(); } + @SuppressWarnings( {"UnusedDeclaration"}) + public OneToManyPersister( + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { + super( collection, cacheAccessStrategy, metadataImplementor, factory ); + if ( collection.getPluralAttributeElementBinding().getNature() != + PluralAttributeElementBinding.Nature.ONE_TO_MANY ) { + throw new AssertionError( + String.format( "Unexpected plural attribute nature; expected=(%s), actual=(%s)", + PluralAttributeElementBinding.Nature.ONE_TO_MANY, + collection.getPluralAttributeElementBinding().getNature() + ) + ); + } + final PluralAttributeKeyBinding keyBinding = collection.getPluralAttributeKeyBinding(); + cascadeDeleteEnabled = keyBinding.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete(); + keyIsNullable = keyBinding.isNullable(); + keyIsUpdateable = keyBinding.isUpdatable(); + } + + /** * Generate the SQL UPDATE that updates all the foreign keys to null */ diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 4f432b28c0..f56898b01f 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -68,6 +68,7 @@ import org.hibernate.engine.internal.CacheHelper; import org.hibernate.engine.internal.StatefulPersistenceContext; import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; @@ -105,13 +106,21 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Selectable; import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metamodel.binding.AssociationAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.Value; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Fetchable; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper; import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; @@ -127,6 +136,7 @@ import org.hibernate.sql.SelectFragment; import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.Template; import org.hibernate.sql.Update; +import org.hibernate.tool.schema.internal.TemporaryTableExporter; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.InDatabaseValueGenerationStrategy; import org.hibernate.tuple.InMemoryValueGenerationStrategy; @@ -178,7 +188,7 @@ public abstract class AbstractEntityPersister private final boolean hasSubselectLoadableCollections; protected final String rowIdName; - private final Set lazyProperties; + private final Set lazyProperties; // The optional SQL string defined in the where attribute private final String sqlWhereString; @@ -238,8 +248,8 @@ public abstract class AbstractEntityPersister private final Set affectingFetchProfileNames = new HashSet(); - private final Map uniqueKeyLoaders = new HashMap(); - private final Map lockers = new HashMap(); + private final Map uniqueKeyLoaders = new HashMap(); + private final Map lockers = new HashMap(); private final Map loaders = new HashMap(); // SQL strings @@ -281,8 +291,8 @@ public abstract class AbstractEntityPersister private final String temporaryIdTableName; private final String temporaryIdTableDDL; - private final Map subclassPropertyAliases = new HashMap(); - private final Map subclassPropertyColumnNames = new HashMap(); + private final Map subclassPropertyAliases = new HashMap(); + private final Map subclassPropertyColumnNames = new HashMap(); protected final BasicEntityPropertyMapping propertyMapping; @@ -394,6 +404,19 @@ public abstract class AbstractEntityPersister return result; } + protected static void initializeCustomSql( + CustomSQL customSql, + int i, + String[] sqlStrings, + boolean[] callable, + ExecuteUpdateResultCheckStyle[] checkStyles) { + sqlStrings[i] = customSql != null ? customSql.getSql(): null; + callable[i] = customSql != null && customSql.isCallable(); + checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ? + customSql.getCheckStyle() : + ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] ); + } + protected String getSQLSnapshotSelectString() { return sqlSnapshotSelectString; } @@ -585,13 +608,13 @@ public abstract class AbstractEntityPersister propertySelectable = new boolean[hydrateSpan]; propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][]; - HashSet thisClassProperties = new HashSet(); + HashSet thisClassProperties = new HashSet(); - lazyProperties = new HashSet(); - ArrayList lazyNames = new ArrayList(); - ArrayList lazyNumbers = new ArrayList(); - ArrayList lazyTypes = new ArrayList(); - ArrayList lazyColAliases = new ArrayList(); + lazyProperties = new HashSet(); + ArrayList lazyNames = new ArrayList(); + ArrayList lazyNumbers = new ArrayList(); + ArrayList lazyTypes = new ArrayList(); + ArrayList lazyColAliases = new ArrayList(); iter = persistentClass.getPropertyClosureIterator(); i = 0; @@ -844,8 +867,7 @@ public abstract class AbstractEntityPersister this.cacheAccessStrategy = cacheAccessStrategy; this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy; this.isLazyPropertiesCacheable = - entityBinding.getHierarchyDetails().getCaching() == null ? - false : + entityBinding.getHierarchyDetails().getCaching() == null || entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties(); this.entityMetamodel = new EntityMetamodel( entityBinding, this, factory ); this.entityTuplizer = this.entityMetamodel.getTuplizer(); @@ -860,7 +882,7 @@ public abstract class AbstractEntityPersister // IDENTIFIER - identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding().getSimpleValueSpan(); + identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getColumnCount(); rootTableKeyColumnNames = new String[identifierColumnSpan]; rootTableKeyColumnReaders = new String[identifierColumnSpan]; rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; @@ -870,9 +892,12 @@ public abstract class AbstractEntityPersister loaderName = entityBinding.getCustomLoaderName(); - int i = 0; - for ( org.hibernate.metamodel.relational.Column col : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { - rootTableKeyColumnNames[i] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + for ( int i = 0; i < identifierColumnSpan; i++ ) { + org.hibernate.metamodel.spi.relational.Column col = entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() + .getPrimaryKey() + .getColumns() + .get( i ); + rootTableKeyColumnNames[i] = col.getColumnName().getText( factory.getDialect() ); if ( col.getReadFragment() == null ) { rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i]; rootTableKeyColumnReaderTemplates[i] = getTemplateFromColumn( col, factory ); @@ -881,19 +906,29 @@ public abstract class AbstractEntityPersister rootTableKeyColumnReaders[i] = col.getReadFragment(); rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( rootTableKeyColumnReaders[i], factory ); } - identifierAliases[i] = col.getAlias( factory.getDialect() ); - i++; + identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() ); } // VERSION if ( entityBinding.isVersioned() ) { - final Value versioningValue = entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getValue(); - if ( ! org.hibernate.metamodel.relational.Column.class.isInstance( versioningValue ) ) { - throw new AssertionFailure( "Bad versioning attribute binding : " + versioningValue ); + final BasicAttributeBinding versionAttributeBinding = entityBinding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding(); + if ( versionAttributeBinding.getRelationalValueBindings().size() > 1 ) { + throw new AssertionFailure( + "Bad versioning attribute binding, expecting single column but found " + + versionAttributeBinding.getRelationalValueBindings().size() + ); } - org.hibernate.metamodel.relational.Column versionColumn = org.hibernate.metamodel.relational.Column.class.cast( versioningValue ); - versionColumnName = versionColumn.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + final Value versioningValue = versionAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + if ( ! org.hibernate.metamodel.spi.relational.Column.class.isInstance( versioningValue ) ) { + throw new AssertionFailure( + "Bad versioning attribute binding, expecting column but found [" + versioningValue + "]" + ); + } + org.hibernate.metamodel.spi.relational.Column versionColumn = org.hibernate.metamodel.spi.relational.Column.class.cast( versioningValue ); + versionColumnName = versionColumn.getColumnName().getText( factory.getDialect() ); } else { versionColumnName = null; @@ -920,34 +955,24 @@ public abstract class AbstractEntityPersister propertySelectable = new boolean[hydrateSpan]; propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][]; - HashSet thisClassProperties = new HashSet(); + HashSet thisClassProperties = new HashSet(); lazyProperties = new HashSet(); - ArrayList lazyNames = new ArrayList(); - ArrayList lazyNumbers = new ArrayList(); - ArrayList lazyTypes = new ArrayList(); - ArrayList lazyColAliases = new ArrayList(); + ArrayList lazyNames = new ArrayList(); + ArrayList lazyNumbers = new ArrayList(); + ArrayList lazyTypes = new ArrayList(); + ArrayList lazyColAliases = new ArrayList(); - i = 0; + int i = 0; boolean foundFormula = false; - for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - // entity identifier is not considered a "normal" property - continue; - } + for ( AttributeBinding attributeBinding : entityBinding.getNonIdAttributeBindingClosure() ) { + thisClassProperties.add( attributeBinding ); - if ( ! attributeBinding.getAttribute().isSingular() ) { - // collections handled separately - continue; - } + propertySubclassNames[i] = attributeBinding.getContainer().seekEntityBinding().getEntity().getName(); - final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; - - thisClassProperties.add( singularAttributeBinding ); - - propertySubclassNames[i] = ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName(); - - int span = singularAttributeBinding.getSimpleValueSpan(); + int span = attributeBinding.getAttribute().isSingular() ? + ( (SingularAttributeBinding) attributeBinding).getRelationalValueBindings().size() : + 0; propertyColumnSpans[i] = span; String[] colNames = new String[span]; @@ -958,23 +983,30 @@ public abstract class AbstractEntityPersister boolean[] propertyColumnInsertability = new boolean[span]; boolean[] propertyColumnUpdatability = new boolean[span]; - int k = 0; + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = ( SingularAttributeBinding ) attributeBinding; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - colAliases[k] = valueBinding.getSimpleValue().getAlias( factory.getDialect() ); - if ( valueBinding.isDerived() ) { - foundFormula = true; - formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getSimpleValue() ).getExpression(), factory ); + int k = 0; + + for ( RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + colAliases[k] = valueBinding.getValue().getAlias( + factory.getDialect(), + valueBinding.getTable() + ); + if ( valueBinding.isDerived() ) { + foundFormula = true; + formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getValue() ).getExpression(), factory ); + } + else { + org.hibernate.metamodel.spi.relational.Column col = (org.hibernate.metamodel.spi.relational.Column) valueBinding.getValue(); + colNames[k] = col.getColumnName().getText( factory.getDialect() ); + colReaderTemplates[k] = getTemplateFromColumn( col, factory ); + colWriters[k] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); + } + propertyColumnInsertability[k] = valueBinding.isIncludeInInsert(); + propertyColumnUpdatability[k] = valueBinding.isIncludeInUpdate(); + k++; } - else { - org.hibernate.metamodel.relational.Column col = ( org.hibernate.metamodel.relational.Column ) valueBinding.getSimpleValue(); - colNames[k] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); - colReaderTemplates[k] = getTemplateFromColumn( col, factory ); - colWriters[k] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); - } - propertyColumnInsertability[k] = valueBinding.isIncludeInInsert(); - propertyColumnUpdatability[k] = valueBinding.isIncludeInUpdate(); - k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = formulaTemplates; @@ -985,25 +1017,24 @@ public abstract class AbstractEntityPersister propertyColumnUpdateable[i] = propertyColumnUpdatability; propertyColumnInsertable[i] = propertyColumnInsertability; - if ( lazyAvailable && singularAttributeBinding.isLazy() ) { - lazyProperties.add( singularAttributeBinding.getAttribute().getName() ); - lazyNames.add( singularAttributeBinding.getAttribute().getName() ); + if ( lazyAvailable && attributeBinding.isLazy() ) { + lazyProperties.add( attributeBinding.getAttribute().getName() ); + lazyNames.add( attributeBinding.getAttribute().getName() ); lazyNumbers.add( i ); - lazyTypes.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping()); + lazyTypes.add( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping()); lazyColAliases.add( colAliases ); } + propertySelectable[i] = !attributeBinding.isBackRef(); - // TODO: fix this when backrefs are working - //propertySelectable[i] = singularAttributeBinding.isBackRef(); - propertySelectable[i] = true; + propertyUniqueness[i] = attributeBinding.isAlternateUniqueKey(); - propertyUniqueness[i] = singularAttributeBinding.isAlternateUniqueKey(); - - // TODO: Does this need AttributeBindings wired into lobProperties? Currently in Property only. + // TODO: set lobProperties correctly. + //if (attributeBinding.isLob() && getFactory().getDialect().forceLobAsLastValue() ) { + // lobProperties.add( i ); + //} i++; - } hasFormulaProperties = foundFormula; lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases ); @@ -1036,27 +1067,29 @@ public abstract class AbstractEntityPersister List columnSelectables = new ArrayList(); List propNullables = new ArrayList(); - for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - // entity identifier is not considered a "normal" property - continue; - } - - if ( ! attributeBinding.getAttribute().isSingular() ) { - // collections handled separately - continue; - } - - final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; - - names.add( singularAttributeBinding.getAttribute().getName() ); - classes.add( ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName() ); - boolean isDefinedBySubclass = ! thisClassProperties.contains( singularAttributeBinding ); + for ( AttributeBinding attributeBinding : entityBinding.getNonIdEntitiesAttributeBindingClosure() ) { + names.add( attributeBinding.getAttribute().getName() ); + classes.add( ( (EntityBinding) attributeBinding.getContainer() ).getEntity().getName() ); + boolean isDefinedBySubclass = ! thisClassProperties.contains( attributeBinding ); definedBySubclass.add( isDefinedBySubclass ); - propNullables.add( singularAttributeBinding.isNullable() || isDefinedBySubclass ); //TODO: is this completely correct? - types.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - - final int span = singularAttributeBinding.getSimpleValueSpan(); + final boolean propIsNullable; + final List relationalValueBindings; + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + propIsNullable = + singularAttributeBinding.isOptional() || + singularAttributeBinding.isNullable() || + isDefinedBySubclass; + relationalValueBindings = singularAttributeBinding.getRelationalValueBindings(); + } + else { + // plural attributes are considered nullable + propIsNullable = true; + relationalValueBindings = Collections.emptyList(); + } + propNullables.add( propIsNullable ); + types.add( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + final int span = relationalValueBindings.size(); String[] cols = new String[ span ]; String[] readers = new String[ span ]; String[] readerTemplates = new String[ span ]; @@ -1064,34 +1097,40 @@ public abstract class AbstractEntityPersister int[] colnos = new int[ span ]; int[] formnos = new int[ span ]; int l = 0; - Boolean lazy = singularAttributeBinding.isLazy() && lazyAvailable; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { + Boolean lazy = attributeBinding.isLazy() && lazyAvailable; + + for ( RelationalValueBinding valueBinding : relationalValueBindings ) { if ( valueBinding.isDerived() ) { - DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getSimpleValue() ); + DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getValue() ); String template = getTemplateFromString( derivedValue.getExpression(), factory ); formnos[l] = formulaTemplates.size(); colnos[l] = -1; formulaTemplates.add( template ); forms[l] = template; + // TODO: should be derivedValue.getText( factory.getDialect() ). formulas.add( derivedValue.getExpression() ); - formulaAliases.add( derivedValue.getAlias( factory.getDialect() ) ); + formulaAliases.add( derivedValue.getAlias( factory.getDialect(), null ) ); formulasLazy.add( lazy ); } else { - org.hibernate.metamodel.relational.Column col = org.hibernate.metamodel.relational.Column.class.cast( valueBinding.getSimpleValue() ); - String colName = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + org.hibernate.metamodel.spi.relational.Column col = org.hibernate.metamodel.spi.relational.Column.class.cast( valueBinding.getValue() ); + String colName = col.getColumnName().getText( factory.getDialect() ); colnos[l] = columns.size(); //before add :-) formnos[l] = -1; columns.add( colName ); cols[l] = colName; - aliases.add( col.getAlias( factory.getDialect() ) ); + aliases.add( + col.getAlias( + factory.getDialect(), + valueBinding.getTable() + ) + ); columnsLazy.add( lazy ); - // TODO: properties only selectable if they are non-plural??? - columnSelectables.add( singularAttributeBinding.getAttribute().isSingular() ); + columnSelectables.add( ! attributeBinding.isBackRef() ); readers[l] = col.getReadFragment() == null ? - col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) : + col.getColumnName().getText( factory.getDialect() ) : col.getReadFragment(); String readerTemplate = getTemplateFromColumn( col, factory ); readerTemplates[l] = readerTemplate; @@ -1106,14 +1145,26 @@ public abstract class AbstractEntityPersister propColumnNumbers.add( colnos ); propFormulaNumbers.add( formnos ); - if ( singularAttributeBinding.isAssociation() ) { - AssociationAttributeBinding associationAttributeBinding = - ( AssociationAttributeBinding ) singularAttributeBinding; - cascades.add( associationAttributeBinding.getCascadeStyle() ); - joinedFetchesList.add( associationAttributeBinding.getFetchMode() ); + CascadeStyle cascadeStyle = null; + if ( attributeBinding.isCascadeable() ) { + if ( attributeBinding.getAttribute().isSingular() ) { + cascadeStyle = ( (Cascadeable) attributeBinding ).getCascadeStyle(); + } + else { + PluralAttributeElementBinding pluralAttributeElementBinding = + ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding(); + cascadeStyle = ( (Cascadeable) pluralAttributeElementBinding).getCascadeStyle(); + } + } + if ( cascadeStyle == null ) { + cascadeStyle = CascadeStyles.NONE; + } + cascades.add( cascadeStyle ); + + if ( attributeBinding instanceof Fetchable ) { + joinedFetchesList.add( ( (Fetchable) attributeBinding ).getFetchMode() ); } else { - cascades.add( CascadeStyles.NONE ); joinedFetchesList.add( FetchMode.SELECT ); } } @@ -1145,15 +1196,25 @@ public abstract class AbstractEntityPersister propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass ); - List filterDefaultConditions = new ArrayList(); - for ( FilterDefinition filterDefinition : entityBinding.getFilterDefinitions() ) { - filterDefaultConditions.add(new FilterConfiguration(filterDefinition.getFilterName(), - filterDefinition.getDefaultFilterCondition(), true, null, null, null)); - } - filterHelper = new FilterHelper( filterDefaultConditions, factory); + filterHelper = new FilterHelper( entityBinding.getFilterConfigurations(), factory); - temporaryIdTableName = null; - temporaryIdTableDDL = null; + temporaryIdTableName = TemporaryTableExporter.generateTableName( + factory.getDialect(), + entityBinding.getPrimaryTable() + ); + TableSpecification primaryTable = entityBinding.getPrimaryTable(); + if ( factory.getDialect().supportsTemporaryTables() && primaryTable instanceof Table ) { + temporaryIdTableDDL = factory + .getDialect() + .getTemporaryTableExporter() + .getSqlCreateStrings( + Table.class.cast( primaryTable ), + factory.getServiceRegistry().getService( JdbcEnvironment.class ) + )[0]; + } + else { + temporaryIdTableDDL = null; + } this.cacheEntryHelper = buildCacheEntryHelper(); } @@ -1164,13 +1225,13 @@ public abstract class AbstractEntityPersister Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() ); } - public String getTemplateFromColumn(org.hibernate.metamodel.relational.Column column, SessionFactoryImplementor factory) { + public String getTemplateFromColumn(org.hibernate.metamodel.spi.relational.Column column, SessionFactoryImplementor factory) { String templateString; if ( column.getReadFragment() != null ) { templateString = getTemplateFromString( column.getReadFragment(), factory ); } else { - String columnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + String columnName = column.getColumnName().getText( factory.getDialect() ); templateString = Template.TEMPLATE + '.' + columnName; } return templateString; @@ -2285,12 +2346,11 @@ public abstract class AbstractEntityPersister /** * Must be called by subclasses, at the end of their constructors */ - protected void initSubclassPropertyAliasesMap(EntityBinding model) throws MappingException { + protected void initSubclassPropertyAliasesMap(EntityBinding entityBinding) throws MappingException { // ALIASES - // TODO: Fix when subclasses are working (HHH-6337) - //internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosureIterator() ); + internalInitSubclassPropertyAliasesMap( null, entityBinding.getEntitiesAttributeBindingClosure() ); // aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id' if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) { @@ -2378,6 +2438,59 @@ public abstract class AbstractEntityPersister } + protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop){ + return prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop ); + } + + private void internalInitSubclassPropertyAliasesMap(String path, AttributeBinding[] attributeBindings) { + for ( AttributeBinding prop : attributeBindings ) { + if ( isIdentifierAttributeBinding( prop ) ) { + // ID propertie aliases are dealt with elsewhere. + continue; + } + if ( ! prop.getAttribute().isSingular() ) { + // skip plural attributes + continue; + } + SingularAttributeBinding singularProp = (SingularAttributeBinding) prop; + String propname = path == null ? prop.getAttribute().getName() : path + "." + prop.getAttribute().getName(); + if ( prop instanceof CompositeAttributeBinding ) { + CompositeAttributeBinding component = (CompositeAttributeBinding) prop; + AttributeBinding[] abs = new AttributeBinding[component.attributeBindingSpan()]; + int i=0; + for(AttributeBinding ab : component.attributeBindings()){ + abs[i++] = ab; + } + internalInitSubclassPropertyAliasesMap( propname, abs ); + } + else { + int span = singularProp.getRelationalValueBindings().size(); + String[] aliases = new String[span]; + String[] cols = new String[span]; + int l = 0; + for ( RelationalValueBinding relationalValueBinding : singularProp.getRelationalValueBindings() ) { + aliases[l] = relationalValueBinding.getValue().getAlias( + getFactory().getDialect(), + relationalValueBinding.getTable() + ); + if ( relationalValueBinding.isDerived() ) { + cols[l] = ( (DerivedValue) relationalValueBinding.getValue() ).getExpression(); // TODO: skip formulas? + } + else { + cols[l] = + ( (org.hibernate.metamodel.spi.relational.Column) relationalValueBinding.getValue() ) + .getColumnName().getText( getFactory().getDialect() ); + } + l++; + } + + subclassPropertyAliases.put( propname, aliases ); + subclassPropertyColumnNames.put( propname, cols ); + } + } + + } + public Object loadByUniqueKey( String propertyName, Object uniqueKey, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java index 61357afdac..1a12a2e995 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java @@ -36,7 +36,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.type.AbstractType; import org.hibernate.type.Type; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index d90331606e..6288d4a8b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -25,9 +25,11 @@ package org.hibernate.persister.entity; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -37,6 +39,7 @@ import org.hibernate.MappingException; import org.hibernate.QueryException; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.hibernate.engine.FetchStyle; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.Mapping; @@ -56,7 +59,17 @@ import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; import org.hibernate.mapping.Value; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Hierarchical; +import org.hibernate.metamodel.spi.domain.Superclass; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.InFragment; import org.hibernate.sql.Insert; @@ -78,8 +91,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { private static final String IMPLICIT_DISCRIMINATOR_ALIAS = "clazz_"; private static final Object NULL_DISCRIMINATOR = new MarkerObject(""); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject(""); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; // the class hierarchy structure private final int tableSpan; @@ -650,6 +661,18 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { return mapping; } + private String[][] buildSubclassNamesBySubclassTableMapping(EntityBinding entityBinding, SessionFactoryImplementor factory) { + // this value represents the number of subclasses (and not the class itself) + final int numberOfSubclassTables = subclassTableNameClosure.length - coreTableSpan; + if ( numberOfSubclassTables == 0 ) { + return new String[0][]; + } + + final String[][] mapping = new String[numberOfSubclassTables][]; + processPersistentClassHierarchy( entityBinding, true, factory, mapping ); + return mapping; + } + private Set processPersistentClassHierarchy( PersistentClass persistentClass, boolean isBase, @@ -688,6 +711,44 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { return classNames; } + private Set processPersistentClassHierarchy( + EntityBinding entityBinding, + boolean isBase, + SessionFactoryImplementor factory, + String[][] mapping) { + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // collect all the class names that indicate that the "main table" of the given PersistentClass should be + // included when one of the collected class names is used in TREAT + final Set classNames = new HashSet(); + + for ( EntityBinding subEntityBinding : entityBinding.getDirectSubEntityBindings() ) { + final Set subclassSubclassNames = processPersistentClassHierarchy( + subEntityBinding, + false, + factory, + mapping + ); + classNames.addAll( subclassSubclassNames ); + } + + classNames.add( entityBinding.getEntityName() ); + + if ( ! isBase ) { + Hierarchical superType = entityBinding.getEntity().getSuperType(); + while ( superType != null ) { + if ( Superclass.class.isInstance( superType ) ) { + classNames.add( superType.getClassReference().getName() ); + } + superType = superType.getSuperType(); + } + + associateSubclassNamesToSubclassTableIndexes( entityBinding, classNames, mapping, factory ); + } + + return classNames; + } + private void associateSubclassNamesToSubclassTableIndexes( PersistentClass persistentClass, Set classNames, @@ -714,6 +775,23 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } } + private void associateSubclassNamesToSubclassTableIndexes( + EntityBinding entityBinding, + Set classNames, + String[][] mapping, + SessionFactoryImplementor factory) { + + final String tableName = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); + + associateSubclassNamesToSubclassTableIndex( tableName, classNames, mapping ); + + for ( SecondaryTable secondaryTable : entityBinding.getSecondaryTables().values() ) { + final String secondaryTableName = + secondaryTable.getSecondaryTableReference().getQualifiedName( factory.getDialect() ); + associateSubclassNamesToSubclassTableIndex( secondaryTableName, classNames, mapping ); + } + } + private void associateSubclassNamesToSubclassTableIndex( String tableName, Set classNames, @@ -754,43 +832,416 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { + super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - // TODO: implement!!! initializing final fields to null to make compiler happy - tableSpan = -1; - tableNames = null; - naturalOrderTableNames = null; - tableKeyColumns = null; - tableKeyColumnReaders = null; - tableKeyColumnReaderTemplates = null; - naturalOrderTableKeyColumns = null; - naturalOrderTableKeyColumnReaders = null; - naturalOrderTableKeyColumnReaderTemplates = null; - naturalOrderCascadeDeleteEnabled = null; - spaces = null; - subclassClosure = null; - subclassTableNameClosure = null; - subclassTableKeyColumnClosure = null; - isClassOrSuperclassTable = null; - naturalOrderPropertyTableNumbers = null; - propertyTableNumbers = null; - subclassPropertyTableNumberClosure = null; - subclassColumnTableNumberClosure = null; - subclassFormulaTableNumberClosure = null; - subclassTableSequentialSelect = null; - subclassTableIsLazyClosure = null; - discriminatorValues = null; - notNullColumnNames = null; - notNullColumnTableNumbers = null; - constraintOrderedTableNames = null; - constraintOrderedKeyColumnNames = null; - discriminatorValue = null; - discriminatorSQLString = null; - discriminatorType = StandardBasicTypes.INTEGER; - explicitDiscriminatorColumnName = null; - discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; - coreTableSpan = -1; - isNullableTable = null; - subclassNamesBySubclassTable = null; + + assertOptimisticLockStyle(); + + final boolean isCascadeDeleteDefault = factory.getDialect().supportsCascadeDelete(); + + final EntityBinding[] entityBindings = entityBinding.getEntityBindingClosure(); + final TableSpecification[] tables = entityBinding.getTableClosure(); + final SecondaryTable[] secondaryTables = entityBinding.getSecondaryTableClosure(); + final String[] synchronizedTableNames = entityBinding.getSynchronizedTableNameClosure(); + final AttributeBinding[] attributeBindings = entityBinding.getNonIdAttributeBindingClosure(); + //todo the count of these two are not equal, which they should be + final EntityBinding[] preOrderSubEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure(); + final EntityBinding[] postOrderSubEntityBindings = entityBinding.getPostOrderSubEntityBindingClosure(); + final TableSpecification[] subTables = entityBinding.getPreOrderSubTableClosure(); + final SecondaryTable[] subSecondaryTables = entityBinding.getSubEntitySecondaryTables(); + final AttributeBinding[] allAttributeBindings = entityBinding.getNonIdEntitiesAttributeBindingClosure(); + + final int idColumnSpan = getIdentifierColumnSpan(); + coreTableSpan = tables.length; + final int secondaryTableSpan = secondaryTables.length; + tableSpan = coreTableSpan + secondaryTableSpan; + final int subclassSpan = postOrderSubEntityBindings.length; + final int subclassSecondaryTableSpan = subSecondaryTables.length; + final int subTableSpan = subclassSpan + subclassSecondaryTableSpan; + final int allTableSpan = tableSpan + subTableSpan; + final int hydrateSpan = getPropertySpan(); + isClassOrSuperclassTable = new boolean[allTableSpan]; + subclassTableSequentialSelect = new boolean[allTableSpan]; + subclassTableIsLazyClosure = new boolean[allTableSpan]; + naturalOrderTableNames = new String[tableSpan]; + naturalOrderCascadeDeleteEnabled = new boolean[tableSpan]; + + naturalOrderTableKeyColumns = new String[tableSpan][]; + naturalOrderTableKeyColumnReaders = new String[tableSpan][]; + naturalOrderTableKeyColumnReaderTemplates = new String[tableSpan][]; + //custom sql + customSQLInsert = new String[tableSpan]; + customSQLUpdate = new String[tableSpan]; + customSQLDelete = new String[tableSpan]; + insertCallable = new boolean[tableSpan]; + updateCallable = new boolean[tableSpan]; + deleteCallable = new boolean[tableSpan]; + insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + subclassClosure = new String[subclassSpan+1]; + subclassClosure[subclassSpan] = getEntityName(); + isNullableTable = new boolean[secondaryTableSpan]; + naturalOrderPropertyTableNumbers = new int[hydrateSpan]; + propertyTableNumbers = new int[hydrateSpan]; + constraintOrderedTableNames = new String[allTableSpan]; + constraintOrderedKeyColumnNames = new String[allTableSpan][]; + /** + * 1. core table names + * 2. direct sub entity table names + * 3. core joined table names + * 4. direct sub entity joined table names + */ + final String[] naturalOrderSubclassTableNameClosure = new String[allTableSpan]; + final String[][] naturalOrderSubclassTableKeyColumnClosure = new String[allTableSpan][]; + + + int tableIndex = 0; + int allTableIndex =0; + //first, process tables / entitybindings mapped directly by the current entitybinding and its super entitybindings + for ( int i = 0; i < coreTableSpan; i++, tableIndex++, allTableIndex++ ) { + final TableSpecification table = tables[i]; + final EntityBinding currentEntityBinding = entityBindings[i]; + naturalOrderTableNames[tableIndex] = table.getQualifiedName( factory.getDialect() ); + naturalOrderCascadeDeleteEnabled[tableIndex] = currentEntityBinding.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete(); + naturalOrderTableKeyColumns[tableIndex] = new String[idColumnSpan]; + naturalOrderTableKeyColumnReaders[tableIndex] = new String[idColumnSpan]; + naturalOrderTableKeyColumnReaderTemplates[tableIndex] = new String[idColumnSpan]; + PrimaryKey primaryKey = table.getPrimaryKey(); + resolvePkColumnNames( + factory, + primaryKey, + naturalOrderTableKeyColumns[tableIndex], + naturalOrderTableKeyColumnReaders[tableIndex], + naturalOrderTableKeyColumnReaderTemplates[tableIndex] + ); + final EntityBinding eb = entityBindings[i]; + //Custom SQL + initializeCustomSql( eb.getCustomInsert(), tableIndex, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( eb.getCustomUpdate(), tableIndex, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( eb.getCustomDelete(), tableIndex, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + isClassOrSuperclassTable[allTableIndex] = true;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table ); + subclassTableSequentialSelect[allTableIndex] = false; + subclassTableIsLazyClosure[allTableIndex] = false; + } + + //#1 + System.arraycopy( naturalOrderTableNames, 0, naturalOrderSubclassTableNameClosure, 0, coreTableSpan ); + System.arraycopy( naturalOrderTableKeyColumns, 0, naturalOrderSubclassTableKeyColumnClosure, 0, coreTableSpan ); + //--------------------------------- directly sub entities + final String[] naturalOrderSubTableNames = new String[subclassSpan]; + final String[][] naturalOrderSubTableKeyColumns = new String[subclassSpan][idColumnSpan]; + + for ( int i = 0; i < subclassSpan; i++, allTableIndex++ ) { + final EntityBinding subEntityBinding = preOrderSubEntityBindings[i]; //todo post order?? + final TableSpecification table = subEntityBinding.getPrimaryTable(); + naturalOrderSubTableNames[i] = table.getQualifiedName( factory.getDialect() ); + + final PrimaryKey pk = table.getPrimaryKey(); + for(int j=0;j= 0; i--, currentPosition++ ) { + constraintOrderedTableNames[currentPosition] = naturalOrderSubclassTableNameClosure[i]; + constraintOrderedKeyColumnNames[currentPosition] = naturalOrderSubclassTableKeyColumnClosure[i]; + } + subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan ); + subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan ); + + // PROPERTIES + + + ArrayList columnTableNumbers = new ArrayList(); + ArrayList formulaTableNumbers = new ArrayList(); + ArrayList propTableNumbers = new ArrayList(); + for(int i=0;i valueBindings; + if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { + SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast( + attributeBinding + ); + valueBindings = singularAttributeBinding.getRelationalValueBindings(); + } + else { + valueBindings = Collections.EMPTY_LIST; + } + final TableSpecification table; + if ( valueBindings.isEmpty() ) { + table = attributeBinding.getContainer().seekEntityBinding().getPrimaryTable(); + } + else { + // TODO: Can relational value bindings for an attribute binding be in more than one table? + // For now, just get the table from the first one. + table = valueBindings.get( 0 ).getTable(); + } + + final String tableName = table.getQualifiedName( factory.getDialect() ); + if ( i < hydrateSpan ) { + propertyTableNumbers[i] = getTableId( tableName, tableNames ); + naturalOrderPropertyTableNumbers[i] = getTableId( tableName, naturalOrderTableNames ); + } + final int tableNumberInSubclass = getTableId( tableName, subclassTableNameClosure ); + propTableNumbers.add( tableNumberInSubclass ); + for ( RelationalValueBinding vb : valueBindings ) { + if ( vb.isDerived() ) { + formulaTableNumbers.add( tableNumberInSubclass ); + } + else { + columnTableNumbers.add( tableNumberInSubclass ); + } + } + } + + + + subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers ); + subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers ); + subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers ); + // SUBCLASSES + + // DISCRIMINATOR + + if ( entityBinding.isPolymorphic() ) { + final EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); + if ( discriminator != null ) { + log.debug( "Encountered explicit discriminator mapping for joined inheritance" ); + + final org.hibernate.metamodel.spi.relational.Value relationalValue = discriminator.getRelationalValue(); + if ( DerivedValue.class.isInstance( relationalValue ) ) { + throw new MappingException( "Discriminator formulas on joined inheritance hierarchies not supported at this time" ); + } + else { + final org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) relationalValue; + explicitDiscriminatorColumnName = column.getColumnName().getText( factory.getDialect() ); + discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() ); + } + discriminatorType = + (DiscriminatorType) discriminator.getExplicitHibernateTypeDescriptor().getResolvedTypeMapping(); + if ( entityBinding.isDiscriminatorMatchValueNull() ) { + discriminatorValue = NULL_DISCRIMINATOR; + discriminatorSQLString = InFragment.NULL; + } + else if ( entityBinding.isDiscriminatorMatchValueNotNull() ) { + discriminatorValue = NOT_NULL_DISCRIMINATOR; + discriminatorSQLString = InFragment.NOT_NULL; + } + else { + try { + discriminatorValue = discriminatorType.stringToObject( entityBinding.getDiscriminatorMatchValue() ); + discriminatorSQLString = discriminatorType.objectToSQLString( discriminatorValue, factory.getDialect() ); + } + catch (ClassCastException cce) { + throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() ); + } + catch (Exception e) { + throw new MappingException("Could not format discriminator value to SQL string", e); + } + } + } + else { + explicitDiscriminatorColumnName = null; + discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; + discriminatorType = StandardBasicTypes.INTEGER; + try { + discriminatorValue = entityBinding.getSubEntityBindingId(); + discriminatorSQLString = discriminatorValue.toString(); + } + catch ( Exception e ) { + throw new MappingException( "Could not format discriminator value to SQL string", e ); + } + } + subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() ); + discriminatorValues = new String[subclassSpan+1]; + discriminatorValues[subclassSpan] = discriminatorSQLString; + notNullColumnTableNumbers = new int[subclassSpan+1]; + final int id = getTableId( + tableNames[0], //the current entitybinding's primary table name + subclassTableNameClosure + ); + notNullColumnTableNumbers[subclassSpan] = id; + notNullColumnNames = new String[subclassSpan+1]; + notNullColumnNames[subclassSpan] = subclassTableKeyColumnClosure[id][0]; + } + else { + explicitDiscriminatorColumnName = null; + discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; + discriminatorValues = null; + notNullColumnTableNumbers = null; + notNullColumnNames = null; + discriminatorType = StandardBasicTypes.INTEGER; + discriminatorValue = null; + discriminatorSQLString = null; + } + + for ( int k = 0; k < postOrderSubEntityBindings.length; k++ ) { + final EntityBinding eb = postOrderSubEntityBindings[k]; + subclassClosure[k] = eb.getEntityName(); + try { + if ( entityBinding.isPolymorphic() ) { + // we now use subclass ids that are consistent across all + // persisters for a class hierarchy, so that the use of + // "foo.class = Bar" works in HQL + Integer subclassId = eb.getSubEntityBindingId(); + subclassesByDiscriminatorValue.put( subclassId, eb.getEntityName() ); + discriminatorValues[k] = subclassId.toString(); + int id = getTableId( + eb.getPrimaryTable().getQualifiedName( factory.getDialect() ), + subclassTableNameClosure + ); + notNullColumnTableNumbers[k] = id; + notNullColumnNames[k] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); + if(notNullColumnNames[k] == null){ + System.out.println(); + } + } + } + catch ( Exception e ) { + throw new MappingException( "Error parsing discriminator value", e ); + } + } + + subclassNamesBySubclassTable = buildSubclassNamesBySubclassTableMapping( entityBinding, factory ); + + initLockers(); + initSubclassPropertyAliasesMap( entityBinding ); + + postConstruct( mapping ); + } + + + private void resolvePkColumnNames(SessionFactoryImplementor factory, PrimaryKey primaryKey, String[] columns, String[] readers, String[] templates) { + for ( int k = 0; k < primaryKey.getColumnSpan(); k++ ) { + org.hibernate.metamodel.spi.relational.Column column = primaryKey.getColumns().get( k ); + columns[k] = column.getColumnName().getText( factory.getDialect() ); + readers[k] = column.getReadExpr( factory.getDialect() ); + templates[k] = column.getTemplate( + factory.getDialect(), + factory.getSqlFunctionRegistry() + ); + } + } + + private void assertOptimisticLockStyle() { + if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) { + throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" ); + } } protected boolean isNullableTable(int j) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 8196261aaa..7483936bb5 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -36,12 +36,14 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.hibernate.engine.FetchStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.DynamicFilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.util.MarkerObject; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; @@ -52,14 +54,15 @@ import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; import org.hibernate.mapping.Value; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.TableSpecification; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.InFragment; import org.hibernate.sql.Insert; import org.hibernate.sql.SelectFragment; @@ -127,14 +130,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final String[][] constraintOrderedKeyColumnNames; //private final Map propertyTableNumbersByName = new HashMap(); - private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); + private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); - private final Map sequentialSelectStringsByEntityName = new HashMap(); + private final Map sequentialSelectStringsByEntityName = new HashMap(); private static final Object NULL_DISCRIMINATOR = new MarkerObject(""); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject(""); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; //INITIALIZATION: @@ -475,9 +476,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { // CLASS + TABLE - // TODO: fix when joins are working (HHH-6391) - //joinSpan = entityBinding.getJoinClosureSpan() + 1; - joinSpan = 1; + joinSpan = entityBinding.getSecondaryTableClosureSpan() + 1; qualifiedTableNames = new String[joinSpan]; isInverseTable = new boolean[joinSpan]; isNullableTable = new boolean[joinSpan]; @@ -507,7 +506,26 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { // JOINS - // TODO: add join stuff when HHH-6391 is working + int j = 1; + for ( SecondaryTable join : entityBinding.getSecondaryTableClosure() ) { + qualifiedTableNames[j] = join.getSecondaryTableReference().getQualifiedName( factory.getDialect() ); + isInverseTable[j] = join.isInverse(); + isNullableTable[j] = join.isOptional(); + cascadeDeleteEnabled[j] = join.isCascadeDeleteEnabled() && + factory.getDialect().supportsCascadeDelete(); + + initializeCustomSql( join.getCustomInsert(), j, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( join.getCustomUpdate(), j, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( join.getCustomDelete(), j, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + + final List joinColumns = join.getForeignKeyReference().getSourceColumns(); + keyColumnNames[j] = new String[ joinColumns.size() ]; + int i = 0; + for ( org.hibernate.metamodel.spi.relational.Column joinColumn : joinColumns ) { + keyColumnNames[j][i++] = joinColumn.getColumnName().getText( factory.getDialect() ); + } + j++; + } constraintOrderedTableNames = new String[qualifiedTableNames.length]; constraintOrderedKeyColumnNames = new String[qualifiedTableNames.length][]; @@ -518,7 +536,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { spaces = ArrayHelper.join( qualifiedTableNames, - ArrayHelper.toStringArray( entityBinding.getSynchronizedTableNames() ) + entityBinding.getSynchronizedTableNames() ); final boolean lazyAvailable = isInstrumented(); @@ -539,8 +557,24 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { isNullables.add(Boolean.FALSE); isLazies.add(Boolean.FALSE); - // TODO: add join stuff when HHH-6391 is working - + for ( SecondaryTable join : entityBinding.getEntitiesSecondaryTableClosure() ) { + final boolean isConcrete = entityBinding.isClassOrSuperclassSecondaryTable( join ); + isConcretes.add( isConcrete ); + final boolean isDeferred = join.getFetchStyle() != FetchStyle.JOIN; + isDeferreds.add( isDeferred ); + isInverses.add( join.isInverse() ); + isNullables.add( join.isOptional() ); + isLazies.add( lazyAvailable && join.isLazy() ); + hasDeferred = isDeferred && !isConcrete; + subclassTables.add( join.getSecondaryTableReference().getQualifiedName( factory.getDialect() ) ); + final List joinColumns = join.getForeignKeyReference().getSourceColumns(); + String[] keyCols = new String[ joinColumns.size() ]; + int i = 0; + for ( org.hibernate.metamodel.spi.relational.Column joinColumn : joinColumns ) { + keyCols[i++] = joinColumn.getColumnName().getText( factory.getDialect() ); + } + joinKeyColumns.add(keyCols); + } subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds); subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables); @@ -554,11 +588,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { // DISCRIMINATOR if ( entityBinding.isPolymorphic() ) { - SimpleValue discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getBoundValue(); + EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); + org.hibernate.metamodel.spi.relational.Value discriminatorRelationalValue = discriminator.getRelationalValue(); if ( discriminatorRelationalValue == null ) { throw new MappingException("discriminator mapping required for single table polymorphic persistence"); } - forceDiscriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator().isForced(); + forceDiscriminator = discriminator.isForced(); if ( DerivedValue.class.isInstance( discriminatorRelationalValue ) ) { DerivedValue formula = ( DerivedValue ) discriminatorRelationalValue; discriminatorFormula = formula.getExpression(); @@ -569,39 +604,34 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorAlias = "clazz_"; } else { - org.hibernate.metamodel.relational.Column column = ( org.hibernate.metamodel.relational.Column ) discriminatorRelationalValue; - discriminatorColumnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) discriminatorRelationalValue; + discriminatorColumnName = column.getColumnName().getText( factory.getDialect() ); discriminatorColumnReaders = column.getReadFragment() == null ? - column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) : + column.getColumnName().getText( factory.getDialect() ) : column.getReadFragment(); discriminatorColumnReaderTemplate = getTemplateFromColumn( column, factory ); - discriminatorAlias = column.getAlias( factory.getDialect() ); + discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() ); discriminatorFormula = null; discriminatorFormulaTemplate = null; } - discriminatorType = entityBinding.getHierarchyDetails() - .getEntityDiscriminator() + discriminatorType = discriminator .getExplicitHibernateTypeDescriptor() .getResolvedTypeMapping(); - if ( entityBinding.getDiscriminatorMatchValue() == null ) { + + if ( entityBinding.isDiscriminatorMatchValueNull() ) { discriminatorValue = NULL_DISCRIMINATOR; discriminatorSQLValue = InFragment.NULL; discriminatorInsertable = false; } - else if ( entityBinding.getDiscriminatorMatchValue().equals( NULL_STRING ) ) { - discriminatorValue = NOT_NULL_DISCRIMINATOR; - discriminatorSQLValue = InFragment.NOT_NULL; - discriminatorInsertable = false; - } - else if ( entityBinding.getDiscriminatorMatchValue().equals( NOT_NULL_STRING ) ) { + else if ( entityBinding.isDiscriminatorMatchValueNotNull() ) { discriminatorValue = NOT_NULL_DISCRIMINATOR; discriminatorSQLValue = InFragment.NOT_NULL; discriminatorInsertable = false; } else { - discriminatorInsertable = entityBinding.getHierarchyDetails().getEntityDiscriminator().isInserted() + discriminatorInsertable = discriminator.isInserted() && ! DerivedValue.class.isInstance( discriminatorRelationalValue ); try { DiscriminatorType dtype = ( DiscriminatorType ) discriminatorType; @@ -634,48 +664,50 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { propertyTableNumbers = new int[ getPropertySpan() ]; int i=0; - for( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { + for( AttributeBinding attributeBinding : entityBinding.getNonIdAttributeBindingClosure() ) { // TODO: fix when joins are working (HHH-6391) //propertyTableNumbers[i++] = entityBinding.getJoinNumber( attributeBinding); - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - continue; // skip identifier binding + final int tableNumber; + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + tableNumber = entityBinding.getSecondaryTableNumber( singularAttributeBinding ); } - if ( ! attributeBinding.getAttribute().isSingular() ) { - continue; + else { + tableNumber = 0; } - propertyTableNumbers[ i++ ] = 0; + propertyTableNumbers[ i++ ] = tableNumber; } //TODO: code duplication with JoinedSubclassEntityPersister - ArrayList columnJoinNumbers = new ArrayList(); - ArrayList formulaJoinedNumbers = new ArrayList(); - ArrayList propertyJoinNumbers = new ArrayList(); + ArrayList columnJoinNumbers = new ArrayList(); + ArrayList formulaJoinedNumbers = new ArrayList(); + ArrayList propertyJoinNumbers = new ArrayList(); - for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) { - if ( ! attributeBinding.getAttribute().isSingular() ) { - continue; + for ( AttributeBinding attributeBinding : entityBinding.getNonIdEntitiesAttributeBindingClosure() ) { + final String entityName = attributeBinding.getContainer().seekEntityBinding().getEntityName(); + String path = StringHelper.isEmpty( attributeBinding.getContainer().getPathBase() ) ? + entityName + '.' + attributeBinding.getAttribute().getName() : + entityName + '.' + attributeBinding.getContainer().getPathBase() + '.' + attributeBinding.getAttribute().getName(); + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + int join = entityBinding.getSecondaryTableNumber( singularAttributeBinding ); + propertyJoinNumbers.add( join ); + // We need the name of the actual entity that contains this attribute binding. + //TODO it should be folder.children but now it is ".children" + propertyTableNumbersByNameAndSubclass.put( path, join ); + for ( RelationalValueBinding relationalValueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + if ( relationalValueBinding.isDerived() ) { + formulaJoinedNumbers.add( join ); + } + else { + columnJoinNumbers.add( join ); + } + } } - SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; - - // TODO: fix when joins are working (HHH-6391) - //int join = entityBinding.getJoinNumber(singularAttributeBinding); - int join = 0; - propertyJoinNumbers.add(join); - - //propertyTableNumbersByName.put( singularAttributeBinding.getName(), join ); - propertyTableNumbersByNameAndSubclass.put( - singularAttributeBinding.getContainer().getPathBase() + '.' + singularAttributeBinding.getAttribute().getName(), - join - ); - - for ( SimpleValueBinding simpleValueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - if ( DerivedValue.class.isInstance( simpleValueBinding.getSimpleValue() ) ) { - formulaJoinedNumbers.add( join ); - } - else { - columnJoinNumbers.add( join ); - } + else { + propertyJoinNumbers.add( 0 ); + propertyTableNumbersByNameAndSubclass.put( path, 0 ); } } subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers); @@ -725,19 +757,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { postConstruct( mapping ); } - private static void initializeCustomSql( - CustomSQL customSql, - int i, - String[] sqlStrings, - boolean[] callable, - ExecuteUpdateResultCheckStyle[] checkStyles) { - sqlStrings[i] = customSql != null ? customSql.getSql(): null; - callable[i] = sqlStrings[i] != null && customSql.isCallable(); - checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ? - customSql.getCheckStyle() : - ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] ); - } - protected boolean isInverseTable(int j) { return isInverseTable[j]; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 1569254186..60946898c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -53,7 +54,9 @@ import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.sql.SelectFragment; import org.hibernate.sql.SimpleSelect; import org.hibernate.type.StandardBasicTypes; @@ -250,16 +253,125 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { super(entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - // TODO: implement!!! initializing final fields to null to make compiler happy. - subquery = null; - tableName = null; - subclassClosure = null; - spaces = null; - subclassSpaces = null; - discriminatorValue = null; - discriminatorSQLValue = null; - constraintOrderedTableNames = null; - constraintOrderedKeyColumnNames = null; + if ( getIdentifierGenerator() instanceof IdentityGenerator ) { + throw new MappingException( + "Cannot use identity column key generation with mapping for: " + + getEntityName() + ); + } + tableName = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); + + + //Custom SQL + // Custom sql + customSQLInsert = new String[1]; + customSQLUpdate = new String[1]; + customSQLDelete = new String[1]; + insertCallable = new boolean[1]; + updateCallable = new boolean[1]; + deleteCallable = new boolean[1]; + insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + + initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( entityBinding.getCustomDelete(), 0, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + //discriminator + { + discriminatorValue = entityBinding.getSubEntityBindingId(); + discriminatorSQLValue = String.valueOf( discriminatorValue ); + } + + // PROPERTIES + + int subclassSpan = entityBinding.getSubEntityBindingClosureSpan() + 1; + subclassClosure = new String[subclassSpan]; + subclassClosure[0] = getEntityName(); + + // SUBCLASSES + subclassByDiscriminatorValue.put( + entityBinding.getSubEntityBindingId(), + entityBinding.getEntityName() + ); + if ( entityBinding.isPolymorphic() ) { + int k=1; + for(EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure()){ + subclassClosure[k++] = subEntityBinding.getEntityName(); + subclassByDiscriminatorValue.put( subEntityBinding.getSubEntityBindingId(), subEntityBinding.getEntityName() ); + } + } + + + //SPACES + //TODO: i'm not sure, but perhaps we should exclude + // abstract denormalized tables? + + String[] synchronizedTableNames = entityBinding.getSynchronizedTableNames(); + int spacesSize = 1 +synchronizedTableNames.length; + spaces = new String[spacesSize]; + spaces[0] = tableName; + if ( ! ArrayHelper.isEmpty( synchronizedTableNames ) ) { + System.arraycopy( synchronizedTableNames, 0, spaces, 1, spacesSize ); + } + + HashSet subclassTables = new HashSet(); + final EntityBinding[] subEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure(); + /* + TODO: here we actually need all entitybindings in the hierarchy, for example: + A + / \ + B C + / \ + D E + + if the current entity is A, then here we need to process all A,B,C,D,E + but if the current entity D, then here we need D,B,A + if the current entity is B, then still A,B,D + */ + + + EntityBinding[] ebs = ArrayHelper.join( entityBinding.getEntityBindingClosure(), subEntityBindings ); + for ( EntityBinding subEntityBinding : ebs ) { + subclassTables.add( subEntityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ) ); + } + subclassSpaces = ArrayHelper.toStringArray( subclassTables ); + + subquery = generateSubquery( entityBinding ); + + if ( isMultiTable() ) { + int idColumnSpan = getIdentifierColumnSpan(); + ArrayList tableNames = new ArrayList(); + ArrayList keyColumns = new ArrayList(); + if ( !isAbstract() ) { + tableNames.add( tableName ); + keyColumns.add( getIdentifierColumnNames() ); + } + ebs = ArrayHelper.join( new EntityBinding[]{entityBinding}, subEntityBindings ); + for(final EntityBinding eb : ebs){ + TableSpecification tab = eb.getPrimaryTable(); + if ( isNotAbstractUnionTable( eb ) ) { + String tableName = tab.getQualifiedName( factory.getDialect() ); + tableNames.add( tableName ); + String[] key = new String[idColumnSpan]; + List columns = tab.getPrimaryKey().getColumns(); + for ( int k = 0; k < idColumnSpan; k++ ) { + key[k] = columns.get( k ).getColumnName().getText( factory.getDialect() ); + } + keyColumns.add( key ); + } + } + + constraintOrderedTableNames = ArrayHelper.toStringArray( tableNames ); + constraintOrderedKeyColumnNames = ArrayHelper.to2DStringArray( keyColumns ); + } + else { + constraintOrderedTableNames = new String[] { tableName }; + constraintOrderedKeyColumnNames = new String[][] { getIdentifierColumnNames() }; + } + initLockers(); + initSubclassPropertyAliasesMap(entityBinding); + postConstruct(mapping); } public Serializable[] getQuerySpaces() { @@ -414,6 +526,106 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { return new int[ getPropertySpan() ]; } + private boolean isNotAbstractUnionTable(EntityBinding entityBinding) { +// return !entityBinding.isAbstract() && entityBinding.getHierarchyDetails() +// .getInheritanceType() != InheritanceType.TABLE_PER_CLASS; + return !entityBinding.isAbstract(); + } + private void visitEntityHierarchy(EntityBinding entityBinding, Callback callback){ + EntityBinding rootEntityBinding = entityBinding.getHierarchyDetails().getRootEntityBinding(); + callback.execute( rootEntityBinding ); + visitSubEntityBindings( rootEntityBinding, callback ); + } + private void visitSubEntityBindings(EntityBinding superEntityBinding, Callback callback){ + callback.execute( superEntityBinding ); + Iterable entityBindings= superEntityBinding.getDirectSubEntityBindings(); +// for(EntityBinding entityBinding : entityBindings){ +// callback.execute( entityBinding ); +// } + for(EntityBinding entityBinding : entityBindings){ + visitSubEntityBindings( entityBinding, callback ); + } + } + private static interface Callback{ + void execute(EntityBinding entityBinding); + } + protected String generateSubquery(EntityBinding entityBinding){ + final Dialect dialect = getFactory().getDialect(); + + if ( !entityBinding.hasSubEntityBindings() ) { + return entityBinding.getPrimaryTable().getQualifiedName( dialect ); + } + + final HashSet columns = new LinkedHashSet(); +// Iterable subEntityBindings = entityBinding.getHierarchyDetails()..getEntityBindingClosure(); + +// for(EntityBinding eb : subEntityBindings){ +// if ( isNotAbstractUnionTable( eb ) ) { +// TableSpecification table = entityBinding.getPrimaryTable(); +// for ( Value v : table.values() ) { +// if ( org.hibernate.metamodel.spi.relational.Column.class.isInstance( v ) ) { +// columns.add( org.hibernate.metamodel.spi.relational.Column.class.cast( v ) ); +// } +// } +// } +// } + + visitSubEntityBindings( + entityBinding, new Callback() { + @Override + public void execute(EntityBinding eb) { + if ( isNotAbstractUnionTable( eb ) ) { + TableSpecification table = eb.getPrimaryTable(); + for ( Value v : table.values() ) { + if ( org.hibernate.metamodel.spi.relational.Column.class.isInstance( v ) ) { + columns.add( org.hibernate.metamodel.spi.relational.Column.class.cast( v ) ); + } + } + } + } + } + ); + + + final StringBuilder buf = new StringBuilder() + .append("( "); + + visitSubEntityBindings( entityBinding, new Callback() { + @Override + public void execute(EntityBinding eb) { + TableSpecification table = eb.getPrimaryTable(); + if ( isNotAbstractUnionTable( eb )) { + //TODO: move to .sql package!! + buf.append("select "); + for(org.hibernate.metamodel.spi.relational.Column column : columns){ + if(!table.hasValue( column )){ + buf.append( dialect.getSelectClauseNullString(column.getJdbcDataType().getTypeCode()) ) + .append(" as "); + } + buf.append( column.getColumnName().getText( dialect ) ); + buf.append( ", " ); + } + buf.append( eb.getSubEntityBindingId() ) + .append( " as clazz_" ); + buf.append(" from ") + .append( table.getQualifiedName( dialect )); + buf.append(" union "); + if ( dialect.supportsUnionAll() ) { + buf.append("all "); + } + } + } + } ); + + + if ( buf.length() > 2 ) { + //chop the last union (all) + buf.setLength( buf.length() - ( dialect.supportsUnionAll() ? 11 : 7 ) ); + } + + return buf.append(" )").toString(); + } + protected String generateSubquery(PersistentClass model, Mapping mapping) { Dialect dialect = getFactory().getDialect(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java index 41550e06bf..f3b1a24df8 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java @@ -36,10 +36,10 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.spi.PersisterClassResolver; @@ -99,7 +99,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi /** * The constructor signature for {@link CollectionPersister} implementations using - * a {@link org.hibernate.metamodel.binding.AbstractPluralAttributeBinding} + * a {@link org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding} * * @todo still need to make collection persisters EntityMode-aware * @todo make EntityPersister *not* depend on {@link SessionFactoryImplementor} if possible. @@ -125,27 +125,29 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi public EntityPersister createEntityPersister( PersistentClass metadata, EntityRegionAccessStrategy cacheAccessStrategy, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, SessionFactoryImplementor factory, Mapping cfg) { Class persisterClass = metadata.getEntityPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata ); } - return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, cfg ); + return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, naturalIdAccessStrategy, factory, cfg ); } @Override @SuppressWarnings( {"unchecked"}) - public EntityPersister createEntityPersister(EntityBinding metadata, - EntityRegionAccessStrategy cacheAccessStrategy, - SessionFactoryImplementor factory, - Mapping cfg) { + public EntityPersister createEntityPersister( + EntityBinding metadata, + EntityRegionAccessStrategy cacheAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, + SessionFactoryImplementor factory, + Mapping cfg) { Class persisterClass = metadata.getCustomEntityPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata ); } - return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, null, factory, cfg ); + return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, naturalIdAccessStrategy, factory, cfg ); } // TODO: change metadata arg type to EntityBinding when new metadata is integrated @@ -208,12 +210,12 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi PluralAttributeBinding collectionMetadata, CollectionRegionAccessStrategy cacheAccessStrategy, SessionFactoryImplementor factory) throws HibernateException { - Class persisterClass = collectionMetadata.getCollectionPersisterClass(); + Class persisterClass = collectionMetadata.getExplicitPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getCollectionPersisterClass( collectionMetadata ); } - return create( persisterClass, COLLECTION_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, collectionMetadata, cacheAccessStrategy, factory ); + return create( persisterClass, COLLECTION_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, collectionMetadata, cacheAccessStrategy, factory ); } // TODO: change collectionMetadata arg type to AbstractPluralAttributeBinding when new metadata is integrated diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java index 8c7118a2b4..56d34cf383 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java @@ -31,9 +31,9 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; import org.hibernate.mapping.SingleTableSubclass; import org.hibernate.mapping.UnionSubclass; -import org.hibernate.metamodel.binding.CollectionElementNature; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; import org.hibernate.persister.collection.BasicCollectionPersister; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.OneToManyPersister; @@ -126,7 +126,7 @@ public class StandardPersisterClassResolver implements PersisterClassResolver { @Override public Class getCollectionPersisterClass(PluralAttributeBinding metadata) { - return metadata.getCollectionElement().getCollectionElementNature() == CollectionElementNature.ONE_TO_MANY + return metadata.getPluralAttributeElementBinding().getNature() == PluralAttributeElementBinding.Nature.ONE_TO_MANY ? oneToManyPersister() : basicCollectionPersister(); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java index 3ce6e660a0..04b29b2860 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java @@ -25,8 +25,8 @@ package org.hibernate.persister.spi; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.Service; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java index d03b20816a..bd97fef1bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java @@ -32,9 +32,9 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.Service; @@ -60,6 +60,7 @@ public interface PersisterFactory extends Service { * * @param model The O/R mapping metamodel definition for the entity * @param cacheAccessStrategy The caching strategy for this entity + * @param naturalIdAccessStrategy The caching strategy for accessing this entity's natural ID * @param factory The session factory * @param cfg The overall mapping * @@ -89,6 +90,7 @@ public interface PersisterFactory extends Service { public EntityPersister createEntityPersister( EntityBinding model, EntityRegionAccessStrategy cacheAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, SessionFactoryImplementor factory, Mapping cfg) throws HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index fb01a6a292..f2f144f228 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -38,7 +38,7 @@ import org.hibernate.HibernateException; import org.hibernate.QueryException; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; diff --git a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java index bc5969935a..dae34e9da1 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java @@ -30,7 +30,7 @@ import org.hibernate.MappingException; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; /** * A factory for building/retrieving PropertyAccessor instances. diff --git a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java index c16c9b04b8..6a0dc72211 100644 --- a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java @@ -33,7 +33,7 @@ import org.hibernate.event.service.spi.DuplicationStrategy; import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.ServiceContributingIntegrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.secure.internal.DisabledJaccServiceImpl; import org.hibernate.secure.internal.JaccPreDeleteEventListener; import org.hibernate.secure.internal.JaccPreInsertEventListener; diff --git a/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java b/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java index 5f9d75668e..b40850d015 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java @@ -29,9 +29,9 @@ import java.util.Properties; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.ValueHolder; import org.hibernate.internal.util.config.ConfigurationException; import org.hibernate.service.internal.JaxbProcessor; diff --git a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java index 9df6799c3c..5a5c9060d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java +++ b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java @@ -36,6 +36,7 @@ import org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProvi import org.hibernate.engine.jdbc.cursor.internal.RefCursorSupportInitiator; import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryInitiator; import org.hibernate.engine.jdbc.dialect.internal.DialectResolverInitiator; +import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator; import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator; import org.hibernate.engine.jndi.internal.JndiServiceInitiator; import org.hibernate.engine.transaction.internal.TransactionFactoryInitiator; @@ -47,6 +48,7 @@ import org.hibernate.persister.internal.PersisterClassResolverInitiator; import org.hibernate.persister.internal.PersisterFactoryInitiator; import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator; import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator; +import org.hibernate.tool.schema.internal.SchemaManagementToolInitiator; /** * Central definition of the standard set of service initiators defined by Hibernate. @@ -76,9 +78,12 @@ public final class StandardServiceInitiators { serviceInitiators.add( DialectResolverInitiator.INSTANCE ); serviceInitiators.add( DialectFactoryInitiator.INSTANCE ); serviceInitiators.add( BatchBuilderInitiator.INSTANCE ); + serviceInitiators.add( JdbcEnvironmentInitiator.INSTANCE ); serviceInitiators.add( JdbcServicesInitiator.INSTANCE ); serviceInitiators.add( RefCursorSupportInitiator.INSTANCE ); + serviceInitiators.add( SchemaManagementToolInitiator.INSTANCE ); + serviceInitiators.add( MutableIdentifierGeneratorFactoryInitiator.INSTANCE); serviceInitiators.add( JtaPlatformResolverInitiator.INSTANCE ); diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java b/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java index 898ede4efc..3bae3a71f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java @@ -50,11 +50,11 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.config.ConfigurationException; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.XsdException; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.XsdException; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java index ab12132940..8d1c00ebfa 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java @@ -25,7 +25,7 @@ package org.hibernate.service.internal; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java index 2f0dd5ae04..61e985b87e 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java @@ -25,7 +25,7 @@ package org.hibernate.service.internal; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.spi.ServiceBinding; import org.hibernate.service.spi.ServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java index 9e169360aa..e6b2d1a82c 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java @@ -25,7 +25,7 @@ package org.hibernate.service.spi; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; /** diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java index dbf86a1ab4..628cc8f1a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java @@ -25,7 +25,7 @@ package org.hibernate.service.spi; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.internal.SessionFactoryServiceRegistryImpl; diff --git a/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java b/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java index 067d479a59..2d21e7bdd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java @@ -29,7 +29,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; import org.hibernate.stat.spi.StatisticsFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java index 3130430c3d..cb72dacc56 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java @@ -37,10 +37,13 @@ import java.sql.SQLWarning; import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; @@ -55,13 +58,11 @@ import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ConfigHelper; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.ServiceRegistry; - +import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.jboss.logging.Logger; /** @@ -72,7 +73,10 @@ import org.jboss.logging.Logger; * @author Steve Ebersole */ public class SchemaExport { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SchemaExport.class.getName()); + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + SchemaExport.class.getName() + ); private static final String DEFAULT_IMPORT_FILE = "/import.sql"; public static enum Type { @@ -96,15 +100,17 @@ public class SchemaExport { private final String[] dropSQL; private final String[] createSQL; private final String importFiles; + + private final ClassLoaderService classLoaderService; private final List exceptions = new ArrayList(); private Formatter formatter; private ImportSqlCommandExtractor importSqlCommandExtractor = ImportSqlCommandExtractorInitiator.DEFAULT_EXTRACTOR; - private String outputFile; + private String outputFile = null; private String delimiter; - private boolean haltOnError; + private boolean haltOnError = false; public SchemaExport(ServiceRegistry serviceRegistry, Configuration configuration) { this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( @@ -113,6 +119,8 @@ public class SchemaExport { this.sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlExceptionHelper = serviceRegistry.getService( JdbcServices.class ).getSqlExceptionHelper(); + + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); this.importFiles = ConfigurationHelper.getString( AvailableSettings.HBM2DDL_IMPORT_FILES, @@ -125,31 +133,72 @@ public class SchemaExport { this.createSQL = configuration.generateSchemaCreationScript( dialect ); } - public SchemaExport(MetadataImplementor metadata) { + public SchemaExport(MetadataImplementor metadata, Connection connection){ ServiceRegistry serviceRegistry = metadata.getServiceRegistry(); - this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( - serviceRegistry.getService( ConnectionProvider.class ) - ); - JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); + if ( connection != null ) { + this.connectionHelper = new SuppliedConnectionHelper( connection ); + } + else { + this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( + serviceRegistry.getService( ConnectionProvider.class ) + ); + } + JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); this.sqlStatementLogger = jdbcServices.getSqlStatementLogger(); this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper(); + + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + + final Map settings = serviceRegistry.getService( ConfigurationService.class ).getSettings(); this.importFiles = ConfigurationHelper.getString( AvailableSettings.HBM2DDL_IMPORT_FILES, - serviceRegistry.getService( ConfigurationService.class ).getSettings(), + settings, DEFAULT_IMPORT_FILE ); - final Dialect dialect = jdbcServices.getDialect(); - this.dropSQL = metadata.getDatabase().generateDropSchemaScript( dialect ); - this.createSQL = metadata.getDatabase().generateSchemaCreationScript( dialect ); + // uses the schema management tool service to generate the create/drop scripts + // longer term this class should instead just leverage the tool for its execution phase... + + SchemaManagementTool schemaManagementTool = serviceRegistry.getService( SchemaManagementTool.class ); + final List commands = new ArrayList(); + final org.hibernate.tool.schema.spi.Target target = new org.hibernate.tool.schema.spi.Target() { + @Override + public boolean acceptsImportScriptActions() { + return false; + } + + @Override + public void prepare() { + commands.clear(); + } + + @Override + public void accept(String command) { + commands.add( command ); + } + + @Override + public void release() { + } + }; + + schemaManagementTool.getSchemaDropper( settings ).doDrop( metadata.getDatabase(), false, target ); + this.dropSQL = commands.toArray( new String[ commands.size() ] ); + + schemaManagementTool.getSchemaCreator( settings ).doCreation( metadata.getDatabase(), false, target ); + this.createSQL = commands.toArray( new String[commands.size()] ); + } + public SchemaExport(MetadataImplementor metadata) { + this(metadata, null); } /** * Create a schema exporter for the given Configuration * * @param configuration The configuration from which to build a schema export. + * * @throws HibernateException Indicates problem preparing for schema export. */ public SchemaExport(Configuration configuration) { @@ -162,12 +211,12 @@ public class SchemaExport { * * @param configuration The configuration from which to build a schema export. * @param properties The properties from which to configure connectivity etc. - * @throws HibernateException Indicates problem preparing for schema export. * + * @throws HibernateException Indicates problem preparing for schema export. * @deprecated properties may be specified via the Configuration object */ @Deprecated - public SchemaExport(Configuration configuration, Properties properties) throws HibernateException { + public SchemaExport(Configuration configuration, Properties properties) throws HibernateException { final Dialect dialect = Dialect.getDialect( properties ); Properties props = new Properties(); @@ -178,6 +227,8 @@ public class SchemaExport { this.sqlStatementLogger = new SqlStatementLogger( false, true ); this.formatter = FormatStyle.DDL.getFormatter(); this.sqlExceptionHelper = new SqlExceptionHelper(); + + this.classLoaderService = new ClassLoaderServiceImpl(); this.importFiles = ConfigurationHelper.getString( AvailableSettings.HBM2DDL_IMPORT_FILES, @@ -194,6 +245,7 @@ public class SchemaExport { * * @param configuration The configuration to use. * @param connection The JDBC connection to use. + * * @throws HibernateException Indicates problem preparing for schema export. */ public SchemaExport(Configuration configuration, Connection connection) throws HibernateException { @@ -202,6 +254,8 @@ public class SchemaExport { this.sqlStatementLogger = new SqlStatementLogger( false, true ); this.formatter = FormatStyle.DDL.getFormatter(); this.sqlExceptionHelper = new SqlExceptionHelper(); + + this.classLoaderService = new ClassLoaderServiceImpl(); this.importFiles = ConfigurationHelper.getString( AvailableSettings.HBM2DDL_IMPORT_FILES, @@ -224,6 +278,7 @@ public class SchemaExport { this.importFiles = ""; this.sqlStatementLogger = new SqlStatementLogger( false, true ); this.sqlExceptionHelper = new SqlExceptionHelper(); + this.classLoaderService = new ClassLoaderServiceImpl(); this.formatter = FormatStyle.DDL.getFormatter(); } @@ -231,6 +286,7 @@ public class SchemaExport { * For generating a export script file, this is the file which will be written. * * @param filename The name of the file to which to write the export script. + * * @return this */ public SchemaExport setOutputFile(String filename) { @@ -242,6 +298,7 @@ public class SchemaExport { * Set the end of statement delimiter * * @param delimiter The delimiter + * * @return this */ public SchemaExport setDelimiter(String delimiter) { @@ -253,6 +310,7 @@ public class SchemaExport { * Should we format the sql strings? * * @param format Should we format SQL strings + * * @return this */ public SchemaExport setFormat(boolean format) { @@ -264,6 +322,7 @@ public class SchemaExport { * Set import.sql command extractor. By default {@link SingleLineSqlCommandExtractor} is used. * * @param importSqlCommandExtractor import.sql command extractor. + * * @return this */ public SchemaExport setImportSqlCommandExtractor(ImportSqlCommandExtractor importSqlCommandExtractor) { @@ -275,6 +334,7 @@ public class SchemaExport { * Should we stop once an error occurs? * * @param haltOnError True if export should stop after error. + * * @return this */ public SchemaExport setHaltOnError(boolean haltOnError) { @@ -343,14 +403,19 @@ public class SchemaExport { LOG.runningHbm2ddlSchemaExport(); final List importFileReaders = new ArrayList(); - for ( String currentFile : importFiles.split(",") ) { + for ( String currentFile : importFiles.split( "," ) ) { try { final String resourceName = currentFile.trim(); - InputStream stream = ConfigHelper.getResourceAsStream( resourceName ); - importFileReaders.add( new NamedReader( resourceName, stream ) ); + InputStream stream = classLoaderService.locateResourceStream( resourceName ); + if ( stream != null ) { + importFileReaders.add( new NamedReader( resourceName, stream ) ); + } + else { + LOG.debugf( "Import file not found: %s", currentFile ); + } } catch ( HibernateException e ) { - LOG.debugf("Import file not found: %s", currentFile); + LOG.debugf( "Import file not found: %s", currentFile ); } } @@ -373,14 +438,14 @@ public class SchemaExport { } if ( type.doCreate() ) { perform( createSQL, exporters ); - if ( ! importFileReaders.isEmpty() ) { + if ( !importFileReaders.isEmpty() ) { for ( NamedReader namedReader : importFileReaders ) { importScript( namedReader, exporters ); } } } } - catch (Exception e) { + catch ( Exception e ) { exceptions.add( e ); LOG.schemaExportUnsuccessful( e ); } @@ -390,7 +455,7 @@ public class SchemaExport { try { exporter.release(); } - catch (Exception ignore) { + catch ( Exception ignore ) { } } @@ -399,17 +464,17 @@ public class SchemaExport { try { namedReader.getReader().close(); } - catch (Exception ignore) { + catch ( Exception ignore ) { } } - LOG.schemaExportComplete(); + LOG.schemaExportComplete(); } } private void perform(String[] sqlCommands, List exporters) { for ( String sqlCommand : sqlCommands ) { String formatted = formatter.format( sqlCommand ); - if ( delimiter != null ) { + if ( delimiter != null ) { formatted += delimiter; } sqlStatementLogger.logStatement( sqlCommand, formatter ); @@ -417,7 +482,7 @@ public class SchemaExport { try { exporter.export( formatted ); } - catch (Exception e) { + catch ( Exception e ) { if ( haltOnError ) { throw new HibernateException( "Error during DDL export", e ); } @@ -432,11 +497,11 @@ public class SchemaExport { private void importScript(NamedReader namedReader, List exporters) throws Exception { BufferedReader reader = new BufferedReader( namedReader.getReader() ); String[] statements = importSqlCommandExtractor.extractCommands( reader ); - if (statements != null) { + if ( statements != null ) { for ( String statement : statements ) { if ( statement != null ) { String trimmedSql = statement.trim(); - if ( trimmedSql.endsWith( ";" )) { + if ( trimmedSql.endsWith( ";" ) ) { trimmedSql = trimmedSql.substring( 0, statement.length() - 1 ); } if ( !StringHelper.isEmpty( trimmedSql ) ) { @@ -448,7 +513,10 @@ public class SchemaExport { } } catch ( Exception e ) { - throw new ImportScriptException( "Error during statement execution (file: '" + namedReader.getName() + "'): " + trimmedSql, e ); + throw new ImportScriptException( + "Error during statement execution (file: '" + namedReader.getName() + "'): " + trimmedSql, + e + ); } } } @@ -479,9 +547,13 @@ public class SchemaExport { final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper(); String formatted = formatter.format( sql ); - if (delimiter != null) formatted += delimiter; - if (script) System.out.println(formatted); - LOG.debug(formatted); + if ( delimiter != null ) { + formatted += delimiter; + } + if ( script ) { + System.out.println( formatted ); + } + LOG.debug( formatted ); if ( outputFile != null ) { fileOutput.write( formatted + "\n" ); } @@ -490,12 +562,12 @@ public class SchemaExport { statement.executeUpdate( sql ); try { SQLWarning warnings = statement.getWarnings(); - if ( warnings != null) { + if ( warnings != null ) { sqlExceptionHelper.logAndClearWarnings( connectionHelper.getConnection() ); } } - catch( SQLException sqle ) { - LOG.unableToLogSqlWarnings(sqle); + catch ( SQLException sqle ) { + LOG.unableToLogSqlWarnings( sqle ); } } @@ -509,7 +581,9 @@ public class SchemaExport { public static void main(String[] args) { try { - Configuration cfg = new Configuration(); + final Configuration cfg = new Configuration(); + final StandardServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); + final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); boolean script = true; boolean drop = false; @@ -559,7 +633,7 @@ public class SchemaExport { } else if ( args[i].startsWith( "--naming=" ) ) { cfg.setNamingStrategy( - ( NamingStrategy ) ReflectHelper.classForName( args[i].substring( 9 ) ) + ( NamingStrategy ) classLoaderService.classForName( args[i].substring( 9 ) ) .newInstance() ); } @@ -583,11 +657,10 @@ public class SchemaExport { cfg.setProperties( props ); } - if (importFile != null) { + if ( importFile != null ) { cfg.setProperty( AvailableSettings.HBM2DDL_IMPORT_FILES, importFile ); } - StandardServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); try { SchemaExport se = new SchemaExport( serviceRegistry, cfg ) .setHaltOnError( halt ) @@ -604,18 +677,26 @@ public class SchemaExport { } } catch ( Exception e ) { - LOG.unableToCreateSchema(e); + LOG.unableToCreateSchema( e ); e.printStackTrace(); } } /** - * Returns a List of all Exceptions which occured during the export. + * Returns a List of all Exceptions which occurred during the export. * - * @return A List containig the Exceptions occured during the export + * @return A List containing the Exceptions occurred during the export */ public List getExceptions() { return exceptions; } + + public String[] getCreateSqlScripts() { + return createSQL; + } + + public String[] getDropSqlScripts() { + return dropSQL; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java new file mode 100644 index 0000000000..e4013a73f6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * JDBC column metadata + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public class ColumnInformationImpl implements ColumnInformation { + private final TableInformation containingTableInformation; + private final Identifier columnIdentifier; + + private final int typeCode; + private final String typeName; + private final int columnSize; + private final int decimalDigits; + private final TruthValue nullable; + + public ColumnInformationImpl( + TableInformation containingTableInformation, + Identifier columnIdentifier, + int typeCode, + String typeName, + int columnSize, + int decimalDigits, + TruthValue nullable) { + this.containingTableInformation = containingTableInformation; + this.columnIdentifier = columnIdentifier; + this.typeCode = typeCode; + this.typeName = typeName; + this.columnSize = columnSize; + this.decimalDigits = decimalDigits; + this.nullable = nullable; + } + + @Override + public TableInformation getContainingTableInformation() { + return containingTableInformation; + } + + @Override + public Identifier getColumnIdentifier() { + return columnIdentifier; + } + + @Override + public int getTypeCode() { + return typeCode; + } + + @Override + public String getTypeName() { + return typeName; + } + + @Override + public int getColumnSize() { + return columnSize; + } + + @Override + public int getDecimalDigits() { + return decimalDigits; + } + + @Override + public TruthValue getNullable() { + return nullable; + } + + public String toString() { + return "ColumnInformation(" + columnIdentifier + ')'; + } + +} + + + + + + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java new file mode 100644 index 0000000000..b36c451260 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java @@ -0,0 +1,77 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * @author Steve Ebersole + */ +public class DatabaseInformationImpl implements DatabaseInformation, ExtractionContext.RegisteredObjectAccess { + private final Map tables = new HashMap(); + private final Map sequences = new HashMap(); + + public DatabaseInformationImpl() { + } + + // DatabaseInformation implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public TableInformation getTableInformation(ObjectName tableName) { + return locateRegisteredTableInformation( tableName ); + } + + @Override + public SequenceInformation getSequenceInformation(ObjectName sequenceName) { + return locateRegisteredSequenceInformation( sequenceName ); + } + + + // RegisteredObjectAccess implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public TableInformation locateRegisteredTableInformation(ObjectName tableName) { + return tables.get( tableName ); + } + + public void registerTableInformation(TableInformation tableInformation) { + tables.put( tableInformation.getName(), tableInformation ); + } + + @Override + public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName) { + return sequences.get( sequenceName ); + } + + public void registerSequenceInformation(SequenceInformation sequenceInformation) { + sequences.put( sequenceInformation.getSequenceName(), sequenceInformation ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java new file mode 100644 index 0000000000..a8f96851a9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; + +/** + * @author Steve Ebersole + */ +public class ExtractionContextImpl implements ExtractionContext { + private final JdbcEnvironment jdbcEnvironment; + private final JdbcConnectionAccess jdbcConnectionAccess; + private final RegisteredObjectAccess registeredTableAccess; + + private Connection jdbcConnection; + private DatabaseMetaData jdbcDatabaseMetaData; + + public ExtractionContextImpl( + JdbcEnvironment jdbcEnvironment, + JdbcConnectionAccess jdbcConnectionAccess, + RegisteredObjectAccess registeredTableAccess) { + this.jdbcEnvironment = jdbcEnvironment; + this.jdbcConnectionAccess = jdbcConnectionAccess; + this.registeredTableAccess = registeredTableAccess; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + @Override + public Connection getJdbcConnection() { + if ( jdbcConnection == null ) { + try { + jdbcConnection = jdbcConnectionAccess.obtainConnection(); + } + catch (SQLException e) { + throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC Connection" ); + } + } + return jdbcConnection; + } + + @Override + public DatabaseMetaData getJdbcDatabaseMetaData() { + if ( jdbcDatabaseMetaData == null ) { + try { + jdbcDatabaseMetaData = getJdbcConnection().getMetaData(); + } + catch (SQLException e) { + throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC DatabaseMetaData" ); + } + } + return jdbcDatabaseMetaData; + } + + @Override + public RegisteredObjectAccess getRegisteredObjectAccess() { + return registeredTableAccess; + } + + public void cleanup() { + if ( jdbcDatabaseMetaData != null ) { + jdbcDatabaseMetaData = null; + } + + if ( jdbcConnection != null ) { + try { + jdbcConnectionAccess.releaseConnection( jdbcConnection ); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java new file mode 100644 index 0000000000..a07d53a2b0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; + +/** + * @author Steve Ebersole + */ +public class ForeignKeyInformationImpl implements ForeignKeyInformation { + private final Identifier fkIdentifier; + private final List columnMappingList; + + public ForeignKeyInformationImpl( + Identifier fkIdentifier, + List columnMappingList) { + this.fkIdentifier = fkIdentifier; + this.columnMappingList = columnMappingList; + } + + @Override + public Identifier getForeignKeyIdentifier() { + return fkIdentifier; + } + + @Override + public Iterable getColumnReferenceMappings() { + return columnMappingList; + } + + public static class ColumnReferenceMappingImpl implements ColumnReferenceMapping { + private final ColumnInformation referencing; + private final ColumnInformation referenced; + + public ColumnReferenceMappingImpl(ColumnInformation referencing, ColumnInformation referenced) { + this.referencing = referencing; + this.referenced = referenced; + } + + @Override + public ColumnInformation getReferencingColumnMetadata() { + return referencing; + } + + @Override + public ColumnInformation getReferencedColumnMetadata() { + return referenced; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java new file mode 100644 index 0000000000..b995cd0c43 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +/** + * @author Steve Ebersole + */ +public class IndexInformationImpl implements IndexInformation { + private final Identifier indexIdentifier; + private final List columnList; + + public IndexInformationImpl(Identifier indexIdentifier, List columnList) { + this.indexIdentifier = indexIdentifier; + this.columnList = columnList; + } + + @Override + public Identifier getIndexIdentifier() { + return indexIdentifier; + } + + @Override + public List getIndexedColumns() { + return columnList; + } + + public static Builder builder(Identifier indexIdentifier) { + return new Builder( indexIdentifier ); + } + + public static class Builder { + private final Identifier indexIdentifier; + private final List columnList = new ArrayList(); + + public Builder(Identifier indexIdentifier) { + this.indexIdentifier = indexIdentifier; + } + + public Builder addColumn(ColumnInformation columnInformation) { + columnList.add( columnInformation ); + return this; + } + + public IndexInformationImpl build() { + if ( columnList.isEmpty() ) { + throw new SchemaManagementException( + "Attempt to resolve JDBC metadata failed to find columns for index [" + indexIdentifier.getText() + "]" + ); + } + return new IndexInformationImpl( indexIdentifier, Collections.unmodifiableList( columnList ) ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java new file mode 100644 index 0000000000..8148cf9b94 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; + +/** + * @author Steve Ebersole + */ +public class PrimaryKeyInformationImpl implements PrimaryKeyInformation { + private final Identifier identifier; + private final Iterable columns; + + public PrimaryKeyInformationImpl(Identifier identifier, Iterable columns) { + this.identifier = identifier; + this.columns = columns; + } + + @Override + public Identifier getPrimaryKeyIdentifier() { + return identifier; + } + + @Override + public Iterable getColumns() { + return columns; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java new file mode 100644 index 0000000000..254c12ffb7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; + +/** + * For now we only collect sequence name. If all databases support it, would really like to see INCREMENT here as well. + * + * @author Steve Ebersole + */ +public class SequenceInformationImpl implements SequenceInformation { + private final ObjectName sequenceName; + private final int incrementSize; + + public SequenceInformationImpl(ObjectName sequenceName, int incrementSize) { + this.sequenceName = sequenceName; + this.incrementSize = incrementSize; + } + + @Override + public ObjectName getSequenceName() { + return sequenceName; + } + + @Override + public int getIncrementSize() { + return incrementSize; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java new file mode 100644 index 0000000000..2d9bb58aee --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java @@ -0,0 +1,429 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.hibernate.JDBCException; +import org.hibernate.TruthValue; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; +import org.hibernate.tool.schema.extract.spi.SchemaExtractionException; +import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +/** + * Implementation of the SchemaMetaDataExtractor contract which uses the standard JDBC {@link java.sql.DatabaseMetaData} + * API for extraction. + * + * @author Steve Ebersole + */ +public class StandardJdbcDatabaseMetaDataExtractor implements SchemaMetaDataExtractor { + private final String[] tableTypes; + + private final ExtractionContext extractionContext; + + public StandardJdbcDatabaseMetaDataExtractor(ExtractionContext extractionContext) { + this.extractionContext = extractionContext; + + ConfigurationService configService = extractionContext.getJdbcEnvironment().getServiceRegistry() + .getService( ConfigurationService.class ); + if (ConfigurationHelper.getBoolean( AvailableSettings.ENABLE_SYNONYMS, configService.getSettings(), false ) ) { + tableTypes = new String[] { "TABLE", "VIEW", "SYNONYM" }; + } + else { + tableTypes = new String[] { "TABLE", "VIEW" }; + } + } + + protected IdentifierHelper identifierHelper() { + return extractionContext.getJdbcEnvironment().getIdentifierHelper(); + } + + protected JDBCException convertSQLException(SQLException sqlException, String message) { + return extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( sqlException, message ); + } + + @Override + public Iterable getTables(String catalogFilter, String schemaFilter) { + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables( + catalogFilter, + schemaFilter, + null, + tableTypes + ); + + final List results = new ArrayList(); + + try { + while ( resultSet.next() ) { + final Identifier catalogIdentifier = identifierHelper().fromMetaDataCatalogName( + resultSet.getString( + "TABLE_CAT" + ) + ); + final Identifier schemaIdentifier = identifierHelper().fromMetaDataSchemaName( + resultSet.getString( + "TABLE_SCHEM" + ) + ); + final Identifier tableIdentifier = identifierHelper().fromMetaDataObjectName( + resultSet.getString( + "TABLE_NAME" + ) + ); + final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier ); + TableInformation tableInformation = new TableInformationImpl( + this, + tableName, + isPhysicalTableType( resultSet.getString( "TABLE_TYPE" ) ), + resultSet.getString( "REMARKS" ) + ); + results.add( tableInformation ); + } + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + + return results; + } + catch (SQLException sqlException) { + throw convertSQLException( sqlException, "Error accessing table metadata" ); + } + } + + protected boolean isPhysicalTableType(String tableType) { + return "TABLE".equalsIgnoreCase( tableType ); + } + + @Override + public Iterable getColumns(TableInformation tableInformation) { + final List results = new ArrayList(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ), + "%" + ); + + try { + while ( resultSet.next() ) { + final String columnName = resultSet.getString( "COLUMN_NAME" ); + if ( columnName == null ) { + continue; + } + + results.add( + new ColumnInformationImpl( + tableInformation, + Identifier.toIdentifier( columnName ), + resultSet.getInt( "DATA_TYPE" ), + new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(), + resultSet.getInt( "COLUMN_SIZE" ), + resultSet.getInt("DECIMAL_DIGITS"), + interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) ) + ) + ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( e, "Error accessing column metadata: " + tableInformation.getName().toString() ); + } + + return results; + } + + private TruthValue interpretTruthValue(String nullable) { + if ( "yes".equalsIgnoreCase( nullable ) ) { + return TruthValue.TRUE; + } + else if ( "no".equalsIgnoreCase( nullable ) ) { + return TruthValue.FALSE; + } + return TruthValue.UNKNOWN; + } + + @Override + public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) { + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getPrimaryKeys( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ) + ); + + final List pkColumns = new ArrayList(); + boolean firstPass = true; + Identifier pkIdentifier = null; + + try { + while ( resultSet.next() ) { + final String currentPkName = resultSet.getString( "PK_NAME" ); + final Identifier currentPkIdentifier = currentPkName == null + ? null + : identifierHelper().fromMetaDataObjectName( currentPkName ); + if ( firstPass ) { + pkIdentifier = currentPkIdentifier; + firstPass = false; + } + else { + if ( !EqualsHelper.equals( pkIdentifier, currentPkIdentifier ) ) { + throw new SchemaExtractionException( + String.format( + "Encountered primary keys differing name on table %s", + tableInformation.getName().toText() + ) + ); + } + } + + final int columnPosition = resultSet.getInt( "KEY_SEQ" ); + final String columnName = resultSet.getString( "COLUMN_NAME" ); + + final Identifier columnIdentifier = identifierHelper().fromMetaDataObjectName( columnName ); + final ColumnInformation column = tableInformation.getColumn( columnIdentifier ); + pkColumns.add( columnPosition-1, column ); + } + } + finally { + resultSet.close(); + } + + if ( firstPass ) { + // we did not find any results (no pk) + return null; + } + else { + // validate column list is properly contiguous + for ( int i = 0; i < pkColumns.size(); i++ ) { + if ( pkColumns.get( i ) == null ) { + throw new SchemaExtractionException( "Primary Key information was missing for KEY_SEQ = " + ( i+1) ); + } + } + + // build the return + return new PrimaryKeyInformationImpl( pkIdentifier, pkColumns ); + } + } + catch (SQLException e) { + throw convertSQLException( e, "Error while reading primary key meta data for " + tableInformation.getName().toText() ); + } + } + + @Override + public Iterable getIndexes(TableInformation tableInformation) { + final Map builders = new HashMap(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getIndexInfo( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ), + false, // DO NOT limit to just unique + true // DO require up-to-date results + ); + + try { + while ( resultSet.next() ) { + if ( resultSet.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic ) { + continue; + } + + final Identifier indexIdentifier = Identifier.toIdentifier( resultSet.getString( "INDEX_NAME" ) ); + IndexInformationImpl.Builder builder = builders.get( indexIdentifier ); + if ( builder == null ) { + builder = IndexInformationImpl.builder( indexIdentifier ); + builders.put( indexIdentifier, builder ); + } + + final Identifier columnIdentifier = Identifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) ); + final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier ); + if ( columnInformation == null ) { + throw new SchemaManagementException( + "Could not locate column information using identifier [" + columnIdentifier.getText() + "]" + ); + } + builder.addColumn( columnInformation ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( + e, + "Error accessing index information: " + tableInformation.getName().toString() + ); + } + + final List indexes = new ArrayList(); + for ( IndexInformationImpl.Builder builder : builders.values() ) { + IndexInformationImpl index = builder.build(); + indexes.add( index ); + } + return indexes; + } + + @Override + public Iterable getForeignKeys(TableInformation tableInformation) { + final Map fkBuilders = new HashMap(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getImportedKeys( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ) + ); + + // todo : need to account for getCrossReference() as well... + + try { + while ( resultSet.next() ) { + // IMPL NOTE : The builder is mainly used to collect the column reference mappings + final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) ); + ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier ); + if ( fkBuilder == null ) { + fkBuilder = generateForeignKeyBuilder( fkIdentifier ); + fkBuilders.put( fkIdentifier, fkBuilder ); + } + + final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" ); + + final TableInformation pkTableInformation = extractionContext.getRegisteredObjectAccess() + .locateRegisteredTableInformation( incomingPkTableName ); + + if ( pkTableInformation == null ) { + // the assumption here is that we have not seen this table already based on fully-qualified name + // during previous step of building all table metadata so most likely this is + // not a match based solely on schema/catalog and that another row in this result set + // should match. + continue; + } + + final Identifier fkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "FKCOLUMN_NAME" ) ); + final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) ); + + fkBuilder.addColumnMapping( + tableInformation.getColumn( fkColumnIdentifier ), + pkTableInformation.getColumn( pkColumnIdentifier ) + ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( + e, + "Error accessing column metadata: " + tableInformation.getName().toString() + ); + } + + final List fks = new ArrayList(); + for ( ForeignKeyBuilder fkBuilder : fkBuilders.values() ) { + ForeignKeyInformation fk = fkBuilder.build(); + fks.add( fk ); + } + return fks; + } + + private ForeignKeyBuilder generateForeignKeyBuilder(Identifier fkIdentifier) { + return new ForeignKeyBuilderImpl( fkIdentifier ); + } + + protected static interface ForeignKeyBuilder { + public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced); + + public ForeignKeyInformation build(); + } + + protected static class ForeignKeyBuilderImpl implements ForeignKeyBuilder { + private final Identifier fkIdentifier; + private final List columnMappingList = new ArrayList(); + + public ForeignKeyBuilderImpl(Identifier fkIdentifier) { + this.fkIdentifier = fkIdentifier; + } + + @Override + public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) { + columnMappingList.add( new ForeignKeyInformationImpl.ColumnReferenceMappingImpl( referencing, referenced ) ); + return this; + } + + @Override + public ForeignKeyInformationImpl build() { + if ( columnMappingList.isEmpty() ) { + throw new SchemaManagementException( + "Attempt to resolve foreign key metadata from JDBC metadata failed to find " + + "column mappings for foreign key named [" + fkIdentifier.getText() + "]" + ); + } + return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList ); + } + } + + private ObjectName extractKeyTableName(ResultSet resultSet, String prefix) throws SQLException { + final String incomingCatalogName = resultSet.getString( prefix + "TABLE_SCHEM" ); + final String incomingSchemaName = resultSet.getString( prefix + "TABLE_CATALOG" ); + final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" ); + + return new ObjectName( + Identifier.toIdentifier( incomingCatalogName ), Identifier.toIdentifier( incomingSchemaName ), + Identifier.toIdentifier( incomingTableName ) + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java new file mode 100644 index 0000000000..933f94c2ed --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java @@ -0,0 +1,163 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; +import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * Provides access to information about existing schema objects (tables, sequences etc) of existing database. + * + * @author Christoph Sturm + * @author Max Rydahl Andersen + * @author Steve Ebersole + */ +public class TableInformationImpl implements TableInformation { + private final SchemaMetaDataExtractor metaDataExtractor; + private final ObjectName tableName; + private final boolean physicalTable; + private final String comment; + + private Map columns; + private PrimaryKeyInformation primaryKey; + private Map foreignKeys; + private Map indexes; + + private boolean wasPrimaryKeyLoaded = false; // to avoid multiple db reads since primary key can be null. + + public TableInformationImpl( + SchemaMetaDataExtractor metaDataExtractor, + ObjectName tableName, + boolean physicalTable, + String comment) { + this.metaDataExtractor = metaDataExtractor; + this.tableName = tableName; + this.physicalTable = physicalTable; + this.comment = comment; + } + + @Override + public ObjectName getName() { + return tableName; + } + + @Override + public boolean isPhysicalTable() { + return physicalTable; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public Iterable getColumns() { + return columns().values(); + } + + protected Map columns() { + if ( this.columns == null ) { + final Map columnMap = new HashMap(); + final Iterable columnInformationItr = metaDataExtractor.getColumns( this ); + for ( ColumnInformation columnInformation : columnInformationItr ) { + columnMap.put( columnInformation.getColumnIdentifier(), columnInformation ); + } + this.columns = columnMap; + } + return this.columns; + } + + @Override + public ColumnInformation getColumn(Identifier columnIdentifier) { + return columns().get( columnIdentifier ); + } + + @Override + public PrimaryKeyInformation getPrimaryKey() { + if ( ! wasPrimaryKeyLoaded ) { + primaryKey = metaDataExtractor.getPrimaryKey( this ); + wasPrimaryKeyLoaded = true; + } + return primaryKey; + } + + @Override + public Iterable getForeignKeys() { + return foreignKeys().values(); + } + + protected Map foreignKeys() { + if ( foreignKeys == null ) { + final Map fkMap = new HashMap(); + final Iterable fks = metaDataExtractor.getForeignKeys( this ); + for ( ForeignKeyInformation fk : fks ) { + fkMap.put( fk.getForeignKeyIdentifier(), fk ); + } + this.foreignKeys = fkMap; + } + return foreignKeys; + } + + @Override + public ForeignKeyInformation getForeignKey(Identifier fkIdentifier) { + return foreignKeys().get( fkIdentifier ); + } + + @Override + public Iterable getIndexes() { + return indexes().values(); + } + + protected Map indexes() { + if ( indexes == null ) { + final Map indexMap = new HashMap(); + final Iterable indexes = metaDataExtractor.getIndexes( this ); + for ( IndexInformation index : indexes ) { + indexMap.put( index.getIndexIdentifier(), index ); + } + this.indexes = indexMap; + } + return indexes; + } + + @Override + public IndexInformation getIndex(Identifier indexName) { + return indexes().get( indexName ); + } + + @Override + public String toString() { + return "TableInformationImpl(" + tableName.toString() + ')'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java new file mode 100644 index 0000000000..2a6d5b3ed0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; + +/** + * Temporary implementation that works for H2. + * + * @author Steve Ebersole + */ +public class TemporarySequenceInformationExtractor implements SequenceInformationExtractor { + @Override + public Iterable extractMetadata(ExtractionContext extractionContext) throws SQLException { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + final Statement statement = extractionContext.getJdbcConnection().createStatement(); + try { + ResultSet resultSet = statement.executeQuery( + "select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME, INCREMENT " + + "from information_schema.sequences" + ); + try { + final List sequenceInformationList = new ArrayList(); + while ( resultSet.next() ) { + sequenceInformationList.add( + new SequenceInformationImpl( + new ObjectName( + identifierHelper.fromMetaDataCatalogName( + resultSet.getString( "SEQUENCE_CATALOG" ) + ), + identifierHelper.fromMetaDataSchemaName( + resultSet.getString( "SEQUENCE_SCHEMA" ) + ), + identifierHelper.fromMetaDataCatalogName( + resultSet.getString( "SEQUENCE_NAME" ) + ) + ), + resultSet.getInt( "INCREMENT" ) + ) + ); + } + return sequenceInformationList; + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java rename to hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java index 7a0ab7ea6a..cb7d093f23 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,8 +21,8 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.attribute; +package org.hibernate.tool.schema.extract; /** - * This package contains binding code for attributes. + * Defines a model of schema information extracted from the database through JDBC. */ diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java new file mode 100644 index 0000000000..a2cf37da0f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java @@ -0,0 +1,92 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing table columns + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public interface ColumnInformation { + /** + * Access to the containing table. + * + * @return The containing table information + */ + public TableInformation getContainingTableInformation(); + + /** + * The simple (not qualified) column name. + * + * @return The column simple identifier. + */ + public Identifier getColumnIdentifier(); + + /** + * Is the column nullable. The database is allowed to report unknown, hence the use of TruthValue + * + * @return nullability. + */ + public TruthValue getNullable(); + + /** + * The JDBC type-code. + * + * @return JDBC type-code + */ + public int getTypeCode(); + + /** + * The database specific type name. + * + * @return Type name + */ + public String getTypeName(); + + // todo : wrap these in org.hibernate.metamodel.spi.relational.Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * The column size (length). + * + * @return The column length + */ + public int getColumnSize(); + + /** + * The precision, for numeric types + * + * @return The numeric precision + */ + public int getDecimalDigits(); +} + + + + + + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java new file mode 100644 index 0000000000..0691964e55 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Provides access to information about existing schema objects (tables, sequences etc) of existing database. + * + * @author Christoph Sturm + * @author Teodor Danciu + * @author Steve Ebersole + */ +public interface DatabaseInformation { + /** + * Obtain reference to the named TableInformation + * + * @param tableName The qualified table name + * + * @return The table information. May return {@code null} if not found. + */ + public TableInformation getTableInformation(ObjectName tableName); + + /** + * Obtain reference to the named SequenceInformation + * + * @param sequenceName The qualified sequence name + * + * @return The sequence information. May return {@code null} if not found. + */ + public SequenceInformation getSequenceInformation(ObjectName sequenceName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java new file mode 100644 index 0000000000..c89f85f6f9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java @@ -0,0 +1,148 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.hibernate.dialect.H2Dialect; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl; +import org.hibernate.tool.schema.extract.internal.ExtractionContextImpl; +import org.hibernate.tool.schema.extract.internal.StandardJdbcDatabaseMetaDataExtractor; +import org.hibernate.tool.schema.extract.internal.TemporarySequenceInformationExtractor; + +/** + * Acts as the entry point into building {@link DatabaseInformation} instances. The correlation is 1-to-1 between + * DatabaseInformationBuilder and DatabaseInformation, meaning a given DatabaseInformationBuilder should only be used + * to build a single DatabaseInformation instance. + * + * @author Steve Ebersole + */ +public class DatabaseInformationBuilder { + private final DatabaseInformationImpl databaseInformation; + private final ExtractionContext extractionContext; + + private final SchemaMetaDataExtractor metaDataExtractor; + + public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, final Connection jdbcConnection) { + this( + jdbcEnvironment, + new JdbcConnectionAccess() { + @Override + public Connection obtainConnection() throws SQLException { + return jdbcConnection; + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + // nothing to do, we don't "own" the connection + } + + @Override + public boolean supportsAggressiveRelease() { + return false; + } + } + ); + } + + public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, JdbcConnectionAccess jdbcConnectionAccess) { + this.databaseInformation = new DatabaseInformationImpl(); + this.extractionContext = new ExtractionContextImpl( jdbcEnvironment, jdbcConnectionAccess, databaseInformation ); + + // todo : make this pluggable... + metaDataExtractor = new StandardJdbcDatabaseMetaDataExtractor( extractionContext ); + } + + public DatabaseInformationBuilder prepareAll() { + return prepare( SchemaMetaDataExtractor.ALL_CATALOGS_FILTER, SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER ); + } + + public DatabaseInformationBuilder prepareCatalogAndSchema(Schema.Name schemaName) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + identifierHelper.toMetaDataCatalogName( schemaName.getCatalog() ), + identifierHelper.toMetaDataSchemaName( schemaName.getSchema() ) + ); + } + + public DatabaseInformationBuilder prepareCatalog(Identifier catalog) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + identifierHelper.toMetaDataCatalogName( catalog ), + SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER + ); + } + + public DatabaseInformationBuilder prepareSchema(Identifier schema) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + SchemaMetaDataExtractor.ALL_CATALOGS_FILTER, + identifierHelper.toMetaDataSchemaName( schema ) + ); + } + + private DatabaseInformationBuilder prepare(String catalog, String schema) { + // todo : apply filtering + + for ( TableInformation tableInformation : metaDataExtractor.getTables( catalog, schema ) ) { + databaseInformation.registerTableInformation( tableInformation ); + } + + final Iterable sequences = extractSequences(); + if ( sequences != null ) { + for ( SequenceInformation sequenceInformation : sequences ) { + databaseInformation.registerSequenceInformation( sequenceInformation ); + } + } + + return this; + } + + private Iterable extractSequences() { + if (!extractionContext.getJdbcEnvironment().getDialect().getClass().isAssignableFrom( H2Dialect.class )) { + // TODO: the temporary impl below is for H2 only + return null; + } + + // todo : temporary impl!!! + final TemporarySequenceInformationExtractor seqExtractor = new TemporarySequenceInformationExtractor(); + try { + return seqExtractor.extractMetadata( extractionContext ); + } + catch (SQLException e) { + throw extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( e, "Unable to access sequence information" ); + } + } + + public DatabaseInformation build() { + return databaseInformation; + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java new file mode 100644 index 0000000000..0e437b7d93 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Defines a context for performing extraction including providing access to information about ongoing extraction as + * well as to delegates needed in performing extraction. + * + * @author Steve Ebersole + */ +public interface ExtractionContext { + public JdbcEnvironment getJdbcEnvironment(); + public Connection getJdbcConnection(); + public DatabaseMetaData getJdbcDatabaseMetaData(); + + public static interface RegisteredObjectAccess { + public TableInformation locateRegisteredTableInformation(ObjectName tableName); + public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName); + } + + public RegisteredObjectAccess getRegisteredObjectAccess(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java new file mode 100644 index 0000000000..92e076e004 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * @author Steve Ebersole + */ +public interface ForeignKeyInformation { + /** + * Obtain the identifier for this FK. + * + * @return The FK identifier. + */ + public Identifier getForeignKeyIdentifier(); + + /** + * Get the column mappings that define the reference. Returned in sequential order. + * + * @return The sequential column reference mappings. + */ + public Iterable getColumnReferenceMappings(); + + public static interface ColumnReferenceMapping { + /** + * Obtain the information about the referencing column (the source column, which points to + * the referenced column). + * + * @return The referencing column. + */ + public ColumnInformation getReferencingColumnMetadata(); + + /** + * Obtain the information about the referenced column (the target side). + * + * @return The referenced column + */ + public ColumnInformation getReferencedColumnMetadata(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java new file mode 100644 index 0000000000..c804047daf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing index in the database + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public interface IndexInformation { + /** + * Obtain the identifier for this index. + * + * @return The index identifier. + */ + public Identifier getIndexIdentifier(); + + /** + * Obtain the columns indexed under this index. Returned in sequential order. + * + * @return The columns + */ + public List getIndexedColumns(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java new file mode 100644 index 0000000000..e7b7ceaa94 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing primary key for a table + * + * @author Steve Ebersole + */ +public interface PrimaryKeyInformation { + /** + * Obtain the identifier for this PK. + * + * @return The PK identifier. + */ + public Identifier getPrimaryKeyIdentifier(); + + /** + * Obtain the columns making up the primary key. Returned in sequential order. + * + * @return The columns + */ + public Iterable getColumns(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java new file mode 100644 index 0000000000..20ffba88e0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.HibernateException; + +/** + * @author Steve Ebersole + */ +public class SchemaExtractionException extends HibernateException { + public SchemaExtractionException(String message) { + super( message ); + } + + public SchemaExtractionException(String message, Throwable root) { + super( message, root ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java new file mode 100644 index 0000000000..1f0da19695 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.tool.schema.extract.internal.TableInformationImpl; + +/** + * Contract for extracting information about objects in the database schema(s). To an extent, the contract largely + * mirrors parts of the JDBC {@link java.sql.DatabaseMetaData} contract. THe intention is to insulate callers + * from {@link java.sql.DatabaseMetaData} since on many databases there are better ways to get information from + * the meta schema. + * + * NOTE : Concepts here taken largely from the {@code MetaDataDialect} class Hibernate Tools. + * + * @author Steve Ebersole + */ +public interface SchemaMetaDataExtractor { + public static final String ALL_CATALOGS_FILTER = null; + public static final String SANS_CATALOG_FILTER = ""; + + public static final String ALL_SCHEMAS_FILTER = null; + public static final String SANS_SCHEMA_FILTER = ""; + + /** + * Return information about all matching tables + * + * @param catalogFilter Filter to be applied for the catalog to which tables belong. Can be either the + * name of the catalog to match or one of 2 special values:

    + *
  1. + * {@code null} ({@link #ALL_CATALOGS_FILTER}) - Indicates that tables from all catalogs should be returned + *
  2. + *
  3. + * {@code ""} (empty String) ({@link #SANS_CATALOG_FILTER}) - Indicates that only tables without a catalog + * should be returned + *
  4. + *
+ * @param schemaFilter Filter to be applied for the schema to which tables belong. Can be either the + * name of the schema to match or one of 2 special values:
    + *
  1. + * {@code null} ({@link #ALL_SCHEMAS_FILTER}) - Indicates that tables from all schemas should be returned + *
  2. + *
  3. + * {@code ""} (empty String) ({@link #SANS_SCHEMA_FILTER}) - Indicates that only tables without a schema + * should be returned + *
  4. + *
+ * + * @return iterator with map elements that has "TABLE_NAME", "TABLE_SCHEMA", "TABLE_CAT", "TABLE_TYPE" keys. + */ + public Iterable getTables(String catalogFilter, String schemaFilter); + + /** + * Return information about columns for the given table. Typically called from the TableInformation itself + * as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate columns + * + * @return The extracted column information + */ + public Iterable getColumns(TableInformation tableInformation); + + /** + * Extract information about the given table's primary key. + * + * @param tableInformation The table for which to locate primary key information, + * + * @return The extracted primary key information + */ + public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation); + + /** + * Extract information about indexes defined against the given table. Typically called from the TableInformation + * itself as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate indexes + * + * @return The extracted index information + */ + public Iterable getIndexes(TableInformation tableInformation); + + /** + * Extract information about foreign keys defined on the given table (targeting or point-at other tables). + * Typically called from the TableInformation itself as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate foreign-keys + * + * @return The extracted foreign-key information + */ + public Iterable getForeignKeys(TableInformation tableInformation); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java new file mode 100644 index 0000000000..56b329aa45 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Access to information about existing sequences. + * + * @author Steve Ebersole + */ +public interface SequenceInformation { + /** + * The qualified sequence name. + * + * @return The sequence name + */ + public ObjectName getSequenceName(); + + /** + * Retrieve the extracted increment-size defined for the sequence. + * + * @return The extracted increment size; use a negative number to indicate the increment could not be extracted. + */ + public int getIncrementSize(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java new file mode 100644 index 0000000000..f63edd1243 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.SQLException; + +/** + * Because JDBC (at least up to an including Java 7, JDBC 4) still does not have support for obtaining information + * about sequences from DatabaseMetaData. + * + * @author Steve Ebersole + */ +public interface SequenceInformationExtractor { + /** + * Get the information about sequences. + * + * @param extractionContext Access to resources needed to perform the extraction + * + * @return The extracted information about existing sequences. + * + * @throws SQLException Don't bother handling SQLExceptions (unless you want to), we will deal with them in the + * caller. + */ + public Iterable extractMetadata(ExtractionContext extractionContext) throws SQLException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java new file mode 100644 index 0000000000..3146abc67b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Provides access to information about existing tables in the database + * + * @author Christoph Sturm + * @author Max Rydahl Andersen + * @author Steve Ebersole + */ +public interface TableInformation { + /** + * Get the qualified name of the table. + * + * @return The qualified table name + */ + public ObjectName getName(); + + /** + * Does this information describe a physical table as opposed to a view, etc? + * + * @return {@code true} if this is a physical table; {@code false} otherwise. + */ + public boolean isPhysicalTable(); + + /** + * Get the comments/remarks defined for the table. + * + * @return The table comments + */ + public String getComment(); + + /** + * Get an iterable over all of the table's columns. + * + * @return All of the table's columns + */ + public Iterable getColumns(); + + /** + * Retrieve the named ColumnInformation + * + * @param columnIdentifier The column identifier (simple name) + * + * @return The matching column information. May return {@code null} + */ + public ColumnInformation getColumn(Identifier columnIdentifier); + + /** + * Retrieve information about the table's primary key, if one is defined (aka, may return {@code null}). + * + * @return The primary key information, or {@code null} if the table did not define a primary key. + */ + public PrimaryKeyInformation getPrimaryKey(); + + /** + * Obtain an iterable over all the table's defined foreign keys. + * + * @return The iterable. + */ + public Iterable getForeignKeys(); + + /** + * Retrieve the named ForeignKeyInformation + * + * @param keyName The foreign key identifier (simple name) + * + * @return The matching foreign key information. May return {@code null} + */ + public ForeignKeyInformation getForeignKey(Identifier keyName); + + /** + * Obtain an iterable over all the table's defined indexes. + * + * @return The iterable. + */ + public Iterable getIndexes(); + + /** + * Obtain an iterable over all the table's defined indexes + */ + public IndexInformation getIndex(Identifier indexName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java new file mode 100644 index 0000000000..fef39ec96c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.Map; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.tool.schema.spi.SchemaCreator; +import org.hibernate.tool.schema.spi.SchemaDropper; +import org.hibernate.tool.schema.spi.SchemaManagementTool; +import org.hibernate.tool.schema.spi.SchemaMigrator; +import org.hibernate.tool.schema.spi.SchemaValidator; + +/** + * The standard Hibernate implementation for performing schema management. + * + * @author Steve Ebersole + */ +public class HibernateSchemaManagementTool implements SchemaManagementTool, ServiceRegistryAwareService { + + private ServiceRegistry serviceRegistry; + + @Override + public SchemaCreator getSchemaCreator(Map options) { + return new SchemaCreatorImpl(); + } + + @Override + public SchemaDropper getSchemaDropper(Map options) { + return new SchemaDropperImpl(); + } + + @Override + public SchemaMigrator getSchemaMigrator(Map options) { + return new SchemaMigratorImpl(); + } + + @Override + public SchemaValidator getSchemaValidator(Map options) { + final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); + return new SchemaValidatorImpl(dialect); + } + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.serviceRegistry = serviceRegistry; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java new file mode 100644 index 0000000000..5a3cf12dd7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java @@ -0,0 +1,175 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.InitCommand; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.tool.schema.spi.SchemaCreator; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.Target; + +/** + * This is functionally nothing more than the creation script from the older SchemaExport class (plus some + * additional stuff in the script). + * + * @author Steve Ebersole + */ +public class SchemaCreatorImpl implements SchemaCreator { + + @Override + public void doCreation(Database database, boolean createSchemas, List targets) throws SchemaManagementException { + doCreation( database, createSchemas, targets.toArray( new Target[ targets.size() ] ) ); + } + + @Override + public void doCreation(Database database, boolean createSchemas, Target... targets) + throws SchemaManagementException { + final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment(); + final Dialect dialect = jdbcEnvironment.getDialect(); + + for ( Target target : targets ) { + target.prepare(); + } + + final Set exportIdentifiers = new HashSet( 50 ); + + // first, create each schema + for ( Schema schema : database.getSchemas() ) { + if ( createSchemas ) { + applySqlStrings( targets, dialect.getCreateSchemaCommand( schema.getName().getSchema().getText( dialect ) ) ); + } + } + + // next, create all "before table" auxiliary objects + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlCreateStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + // then, create all schema objects: tables, sequences, constraints, etc + for ( Schema schema : database.getSchemas() ) { + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + applySqlStrings( targets, dialect.getSequenceExporter().getSqlCreateStrings( sequence, jdbcEnvironment ) ); + } + + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + checkExportIdentifier( table, exportIdentifiers ); + applySqlStrings( targets, dialect.getTableExporter().getSqlCreateStrings( table, jdbcEnvironment ) ); + + for ( Index index : table.getIndexes() ) { + checkExportIdentifier( index, exportIdentifiers ); + applySqlStrings( targets, dialect.getIndexExporter().getSqlCreateStrings( index, jdbcEnvironment ) ); + } + + for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { + checkExportIdentifier( uniqueKey, exportIdentifiers ); + applySqlStrings( targets, dialect.getUniqueDelegate() + .getAlterTableToAddUniqueKeyCommand( uniqueKey ) ); + } + + } + + for ( Table table : schema.getTables() ) { + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + // only add the foreign key if its source and target are both physical tables + // and if the target table does not have any denormalized tables. + if ( Table.class.isInstance( foreignKey.getTable() ) && + Table.class.isInstance( foreignKey.getTargetTable() ) ) { + Table sourceTable = Table.class.cast( foreignKey.getTable() ); + Table targetTable = Table.class.cast( foreignKey.getTargetTable() ); + if ( sourceTable.isPhysicalTable() && + targetTable.isPhysicalTable() && + !targetTable.hasDenormalizedTables() ) { + checkExportIdentifier( foreignKey, exportIdentifiers ); + applySqlStrings( targets, dialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, jdbcEnvironment ) ); + } + } + } + } + } + + // next, create all "after table" auxiliary objects + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && !auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlCreateStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + // and finally add all init commands + for ( InitCommand initCommand : database.getInitCommands() ) { + applySqlStrings( targets, initCommand.getInitCommands() ); + } + + for ( Target target : targets ) { + target.release(); + } + } + + private static void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( "SQL strings added more than once for: " + exportIdentifier ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private static void applySqlStrings(Target[] targets, String... sqlStrings) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java new file mode 100644 index 0000000000..068aad842c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java @@ -0,0 +1,169 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.tool.schema.spi.SchemaDropper; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.Target; + +/** + * This is functionally nothing more than the creation script from the older SchemaExport class (plus some + * additional stuff in the script). + * + * @author Steve Ebersole + */ +public class SchemaDropperImpl implements SchemaDropper { + + @Override + public void doDrop(Database database, boolean dropSchemas, List targets) throws SchemaManagementException { + doDrop( database, dropSchemas, targets.toArray( new Target[ targets.size() ] ) ); + } + + @Override + public void doDrop(Database database, boolean dropSchemas, Target... targets) throws SchemaManagementException { + final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment(); + final Dialect dialect = jdbcEnvironment.getDialect(); + + for ( Target target : targets ) { + target.prepare(); + } + + final Set exportIdentifiers = new HashSet( 50 ); + + // NOTE : init commands are irrelevant for dropping... + + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && ! auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlDropStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + for ( Schema schema : database.getSchemas() ) { + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + if ( dialect.dropConstraints() ) { + // we need to drop constraints prior to dropping table + + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + // only add the foreign key if its source and target are both physical tables + // and if the target table does not have any denormalized tables. + if ( Table.class.isInstance( foreignKey.getTable() ) && + Table.class.isInstance( foreignKey.getTargetTable() ) ) { + Table sourceTable = Table.class.cast( foreignKey.getTable() ); + Table targetTable = Table.class.cast( foreignKey.getTargetTable() ); + if ( sourceTable.isPhysicalTable() && + targetTable.isPhysicalTable() && + !targetTable.hasDenormalizedTables() ) { + checkExportIdentifier( foreignKey, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getForeignKeyExporter().getSqlDropStrings( foreignKey, jdbcEnvironment ) + ); + } + } + } + + for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { + checkExportIdentifier( uniqueKey, exportIdentifiers ); + applySqlStrings( targets, dialect.getUniqueDelegate() + .getAlterTableToDropUniqueKeyCommand( uniqueKey ) ); + } + + for ( Index index : table.getIndexes() ) { + checkExportIdentifier( index, exportIdentifiers ); + applySqlStrings( targets, dialect.getIndexExporter().getSqlDropStrings( index, jdbcEnvironment ) ); + } + } + + checkExportIdentifier( table, exportIdentifiers ); + applySqlStrings( targets, dialect.getTableExporter().getSqlDropStrings( table, jdbcEnvironment ) ); + } + + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + applySqlStrings( targets, dialect.getSequenceExporter().getSqlDropStrings( sequence, jdbcEnvironment ) ); + } + } + + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && ! auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlDropStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); } + } + + for ( Schema schema : database.getSchemas() ) { + if ( dropSchemas ) { + applySqlStrings( targets, dialect.getDropSchemaCommand( schema.getName().getSchema().getText( dialect ) ) ); + } + } + + for ( Target target : targets ) { + target.release(); + } + } + + private static void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( "SQL strings added more than once for: " + exportIdentifier ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private static void applySqlStrings(Target[] targets, String... sqlStrings) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java new file mode 100644 index 0000000000..7c5ae9e25e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.Map; + +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.tool.schema.spi.SchemaManagementTool; + +/** + * @author Steve Ebersole + */ +public class SchemaManagementToolInitiator implements StandardServiceInitiator { + public static final SchemaManagementToolInitiator INSTANCE = new SchemaManagementToolInitiator(); + + public SchemaManagementTool initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + final Object setting = configurationValues.get( AvailableSettings.SCHEMA_MANAGEMENT_TOOL ); + SchemaManagementTool tool = registry.getService( StrategySelector.class ).resolveStrategy( SchemaManagementTool.class, setting ); + if ( tool == null ) { + tool = new HibernateSchemaManagementTool(); + } + + return tool; + } + + @Override + public Class getServiceInitiated() { + return SchemaManagementTool.class; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java new file mode 100644 index 0000000000..60e93efc88 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java @@ -0,0 +1,189 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.SchemaMigrator; +import org.hibernate.tool.schema.spi.Target; + + +/** + * @author Steve Ebersole + */ +public class SchemaMigratorImpl implements SchemaMigrator { + @Override + public void doMigration( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) throws SchemaManagementException { + + for ( Target target : targets ) { + target.prepare(); + } + + doMigrationToTargets( database, existingDatabase, createSchemas, targets ); + + for ( Target target : targets ) { + target.release(); + } + } + + + protected void doMigrationToTargets( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) { + + final Set exportIdentifiers = new HashSet( 50 ); + + for ( Schema schema : database.getSchemas() ) { + if ( createSchemas ) { + // todo : add dialect method for getting a CREATE SCHEMA command and use it here + } + + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + checkExportIdentifier( table, exportIdentifiers ); + final TableInformation tableInformation = existingDatabase.getTableInformation( table.getTableName() ); + if ( tableInformation == null ) { + createTable( table, database.getJdbcEnvironment(), targets ); + } + else { + migrateTable( table, tableInformation, targets, database.getJdbcEnvironment() ); + } + + // todo : handle org.hibernate.mapping.Table.sqlCommentStrings + } + + for ( Table table : schema.getTables() ) { + final TableInformation tableInformation = existingDatabase.getTableInformation( table.getTableName() ); + if ( tableInformation == null ) { + // big problem... + throw new SchemaManagementException( "BIG PROBLEM" ); + } + + for ( Index index : table.getIndexes() ) { + // todo : + } + + if ( !database.getJdbcEnvironment().getDialect().hasAlterTable() ) { + continue; + } + + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + final ForeignKeyInformation foreignKeyInformation = findMatchingForeignKey( foreignKey, tableInformation ); + // todo : .. implement + } + } + + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + final SequenceInformation sequenceInformation = existingDatabase.getSequenceInformation( sequence.getName() ); + if ( sequenceInformation != null ) { + // nothing we really can do... + continue; + } + + applySqlStrings( + database.getJdbcEnvironment().getDialect().getSequenceExporter().getSqlCreateStrings( + sequence, + database.getJdbcEnvironment() + ), + targets + ); + } + } + } + + private ForeignKeyInformation findMatchingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) { + throw new NotYetImplementedException(); + } + + private void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( + String.format( + "Export identifier [%s] encountered more than once", + exportIdentifier + ) + ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private void createTable(Table table, JdbcEnvironment jdbcEnvironment, List targets) { + applySqlStrings( + jdbcEnvironment.getDialect().getTableExporter().getSqlCreateStrings( table, jdbcEnvironment ), + targets + ); + } + + private static void applySqlStrings(String[] sqlStrings, List targets) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } + + + protected void migrateTable( + Table table, + TableInformation tableInformation, + List targets, + JdbcEnvironment jdbcEnvironment) { + applySqlStrings( + table.sqlAlterStrings( tableInformation, jdbcEnvironment ), + targets + ); + + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java new file mode 100644 index 0000000000..bb07edac6c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java @@ -0,0 +1,146 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.SchemaValidator; + +/** + * @author Steve Ebersole + */ +public class SchemaValidatorImpl implements SchemaValidator { + + private final Dialect dialect; + + public SchemaValidatorImpl(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public void doValidation(Database database, DatabaseInformation databaseInformation) { + for ( Schema schema : database.getSchemas() ) { + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + final TableInformation tableInformation = databaseInformation.getTableInformation( + table.getTableName() + ); + validateTable( table, tableInformation ); + } + } + + for ( Schema schema : database.getSchemas() ) { + for ( Sequence sequence : schema.getSequences() ) { + final SequenceInformation sequenceInformation = databaseInformation.getSequenceInformation( + sequence.getName() + ); + validateSequence( sequence, sequenceInformation ); + } + } + } + + protected void validateTable(Table table, TableInformation tableInformation) { + if ( tableInformation == null ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: missing table [%s]", + table.getTableName().toText() + ) + ); + } + + for ( Value value : table.values() ) { + if ( Column.class.isInstance( value ) ) { + final Column column = (Column) value; + final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() ); + if ( columnInformation == null ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: missing column [%s] in table [%s]", + column.getColumnName().getText(), + table.getTableName().toText() + ) + ); + } + + validateColumnType( table, column, columnInformation ); + } + } + } + + protected void validateColumnType(Table table, Column column, ColumnInformation columnInformation) { + // this is the old Hibernate check... + final boolean typesMatch = column.getJdbcDataType().getTypeCode() == columnInformation.getTypeCode() + || column.getSqlTypeString(dialect).toLowerCase().startsWith( columnInformation.getTypeName().toLowerCase() ); + if ( !typesMatch ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: wrong column type encountered in column [%s] in table [%s]; found [%s], but expecting [%s]", + column.getColumnName().getText(), + table.getTableName().toText(), + columnInformation.getTypeName().toLowerCase(), + column.getSqlType().toLowerCase() + ) + ); + } + + // but I think a better check involves checks against type code and then the type code family, not + // just the type name. + // + // See org.hibernate.type.descriptor.sql.JdbcTypeFamilyInformation + + } + + protected void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) { + if ( sequenceInformation == null ) { + throw new SchemaManagementException( + String.format( "Schema-validation: missing sequence [%s]", sequence.getName().toText() ) + ); + } + + if ( sequenceInformation.getIncrementSize() > 0 + && sequence.getIncrementSize() != sequenceInformation.getIncrementSize() ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: sequence [%s] defined inconsistent increment-size; found [%s] but expecting [%s]", + sequence.getName().toText(), + sequenceInformation.getIncrementSize(), + sequence.getIncrementSize() + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java new file mode 100644 index 0000000000..90954b38a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardAuxiliaryDatabaseObjectExporter implements Exporter { + private final Dialect dialect; + + public StandardAuxiliaryDatabaseObjectExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(AuxiliaryDatabaseObject object, JdbcEnvironment jdbcEnvironment) { + return object.sqlCreateStrings( dialect ); + } + + @Override + public String[] getSqlDropStrings(AuxiliaryDatabaseObject object, JdbcEnvironment jdbcEnvironment) { + return object.sqlDropStrings( dialect ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java new file mode 100644 index 0000000000..9e3e60ddfb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java @@ -0,0 +1,106 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardForeignKeyExporter implements Exporter { + private final Dialect dialect; + + public StandardForeignKeyExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(ForeignKey foreignKey, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.hasAlterTable() ) { + return NO_COMMANDS; + } + + final int numberOfColumns = foreignKey.getColumnSpan(); + final String[] columnNames = new String[ numberOfColumns ]; + final String[] targetColumnNames = new String[ numberOfColumns ]; + + int position = 0; + for ( ForeignKey.ColumnMapping columnMapping : foreignKey.getColumnMappings() ) { + columnNames[position] = columnMapping.getSourceColumn().getColumnName().getText( dialect ); + targetColumnNames[position] = columnMapping.getTargetColumn().getColumnName().getText( dialect ); + position++; + } + + + final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) foreignKey.getSourceTable() ).getTableName() + ); + final String targetTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ((Table) foreignKey.getTargetTable()).getTableName() + ); + + final StringBuilder buffer = new StringBuilder( "alter table " ) + .append( sourceTableName ) + .append( + dialect.getAddForeignKeyConstraintString( + foreignKey.getName(), + columnNames, + targetTableName, + targetColumnNames, + foreignKey.referencesPrimaryKey() + ) + ); + + // TODO: If a dialect does not support cascade-delete, can it support other actions? (HHH-6428) + // For now, assume not. + if ( dialect.supportsCascadeDelete() ) { + if ( foreignKey.getDeleteRule() != ForeignKey.ReferentialAction.NO_ACTION ) { + buffer.append( " on delete " ).append( foreignKey.getDeleteRule().getActionString() ); + } + if ( foreignKey.getUpdateRule() != ForeignKey.ReferentialAction.NO_ACTION ) { + buffer.append( " on update " ).append( foreignKey.getUpdateRule().getActionString() ); + } + } + + return new String[] { buffer.toString() }; + } + + @Override + public String[] getSqlDropStrings(ForeignKey foreignKey, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.hasAlterTable() ) { + return NO_COMMANDS; + } + + final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) foreignKey.getSourceTable() ).getTableName() + ); + return new String[] { + "alter table " + sourceTableName + dialect.getDropForeignKeyString() + foreignKey.getName() + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java new file mode 100644 index 0000000000..0e9a4f429c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardIndexExporter implements Exporter { + private final Dialect dialect; + + public StandardIndexExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Index index, JdbcEnvironment jdbcEnvironment) { + // todo : pass in JdbcEnvironment so we can access naming helpers... + // specifically here, StringHelper.unqualify can be incorrect. + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + StringBuilder buf = new StringBuilder() + .append( "create index " ) + .append( dialect.qualifyIndexName() ? index.getName() : StringHelper.unqualify( index.getName() ) ) + .append( " on " ) + .append( tableName ) + .append( " (" ); + + boolean first = true; + for ( Column column : index.getColumns() ) { + if ( first ) { + first = false; + } + else { + buf.append( ", " ); + } + buf.append( ( column.getColumnName().getText( dialect ) ) ); + } + buf.append( ")" ); + return new String[] { buf.toString() }; + } + + @Override + public String[] getSqlDropStrings(Index index, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + return new String[] { + "drop index " + StringHelper.qualify( tableName, index.getName() ) + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java new file mode 100644 index 0000000000..6a74b5e254 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardSequenceExporter implements Exporter { + private final Dialect dialect; + + public StandardSequenceExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Sequence sequence, JdbcEnvironment jdbcEnvironment) { + return dialect.getCreateSequenceStrings( + jdbcEnvironment.getQualifiedObjectNameSupport().formatName( sequence.getName() ), + sequence.getInitialValue(), + sequence.getIncrementSize() + ); + } + + @Override + public String[] getSqlDropStrings(Sequence sequence, JdbcEnvironment jdbcEnvironment) { + return dialect.getDropSequenceStrings( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( sequence.getName() ) ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java new file mode 100644 index 0000000000..eeab57f2be --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java @@ -0,0 +1,183 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.CheckConstraint; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardTableExporter implements Exporter
{ + protected final Dialect dialect; + + public StandardTableExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Table table, JdbcEnvironment jdbcEnvironment) { + boolean hasPrimaryKey = table.getPrimaryKey().getColumns().iterator().hasNext(); + StringBuilder buf = + new StringBuilder(tableCreateString( hasPrimaryKey )) + .append( ' ' ) + .append( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( table.getTableName() ) ) + .append( " (" ); + + + boolean isPrimaryKeyIdentity = + hasPrimaryKey && + table.getPrimaryKey().getColumnSpan() == 1 && + table.getPrimaryKey().getColumns().get( 0 ).isIdentity(); + + // Try to find out the name of the primary key in case the dialect needs it to create an identity + String pkColName = null; + if ( hasPrimaryKey ) { + Column pkColumn = table.getPrimaryKey().getColumns().iterator().next(); + pkColName = pkColumn.getColumnName().getText( dialect ); + } + + boolean isFirst = true; + for ( Column col : table.sortedColumns() ) { + if ( isFirst ) { + isFirst = false; + } + else { + buf.append( ", " ); + } + String colName = col.getColumnName().getText( dialect ); + + buf.append( colName ).append( ' ' ); + + if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { + // to support dialects that have their own identity data type + if ( dialect.hasDataTypeInIdentityColumn() ) { + buf.append( col.getSqlTypeString( dialect ) ); + } + buf.append( ' ' ) + .append( dialect.getIdentityColumnString( col.getJdbcDataType().getTypeCode() ) ); + } + else { + buf.append( col.getSqlTypeString( dialect ) ); + + String defaultValue = col.getDefaultValue(); + if ( defaultValue != null ) { + buf.append( " default " ).append( defaultValue ); + } + + if ( col.isNullable() ) { + buf.append( dialect.getNullColumnString() ); + } + else { + buf.append( " not null" ); + } + + } + //only create unique constraint for non-pk column + if ( table.hasUniqueKey( col ) && !colName.equals( pkColName )) { + buf.append( dialect.getUniqueDelegate().getColumnDefinitionUniquenessFragment( col ) ); + } + + if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) { + buf.append( " check (" ) + .append( col.getCheckCondition() ) + .append( ")" ); + } + + String columnComment = col.getComment(); + if ( columnComment != null ) { + buf.append( dialect.getColumnComment( columnComment ) ); + } + } + if ( hasPrimaryKey ) { + buf.append( ", " ) + .append( table.getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) ); + } + + buf.append( dialect.getUniqueDelegate().getTableCreationUniqueConstraintsFragment( table ) ); + + applyTableCheck( table, buf ); + + buf.append( ')' ); + applyTableTypeString( buf ); + + List sqlStrings = new ArrayList(); + sqlStrings.add( buf.toString() ); + + applyComments( table, sqlStrings ); + + return sqlStrings.toArray( new String[ sqlStrings.size() ] ); + } + + protected void applyComments(Table table, List sqlStrings) { + for ( String comment : table.getComments() ) { + if ( comment != null ) { + sqlStrings.add( dialect.getTableComment( comment ) ); + } + } + } + + protected void applyTableTypeString(StringBuilder buf) { + buf.append( dialect.getTableTypeString() ); + } + + protected void applyTableCheck(Table table, StringBuilder buf) { + if ( dialect.supportsTableCheck() ) { + for ( CheckConstraint checkConstraint : table.getCheckConstraints() ) { + buf.append( ", check (" ) + .append( checkConstraint ) + .append( ')' ); + } + } + } + + protected String tableCreateString(boolean hasPrimaryKey) { + return hasPrimaryKey ? dialect.getCreateTableString() : dialect.getCreateMultisetTableString(); + + } + + @Override + public String[] getSqlDropStrings(Table table, JdbcEnvironment jdbcEnvironment) { + StringBuilder buf = new StringBuilder( "drop table " ); + if ( dialect.supportsIfExistsBeforeTableName() ) { + buf.append( "if exists " ); + } + + buf.append( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( table.getTableName() ) ) + .append( dialect.getCascadeConstraintsString() ); + + if ( dialect.supportsIfExistsAfterTableName() ) { + buf.append( " if exists" ); + } + + return new String[] { buf.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java new file mode 100644 index 0000000000..532c822261 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + + +import java.util.List; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Strong Liu + */ +public class TemporaryTableExporter extends StandardTableExporter { + + public TemporaryTableExporter(Dialect dialect) { + super(dialect); + } + + @Override + public String[] getSqlCreateStrings(Table exportable, JdbcEnvironment jdbcEnvironment) { + if ( dialect.supportsTemporaryTables() ) { + String temperaryTableName = generateTableName( dialect, exportable ); + Table table = new Table( + exportable.getSchema(), + Identifier.toIdentifier( temperaryTableName ), + Identifier.toIdentifier( temperaryTableName ) + ); + for ( final Column column : exportable.getPrimaryKey().getColumns() ) { + Column clone = table.createColumn( column.getColumnName() ); + clone.setCheckCondition( column.getCheckCondition() ); + clone.setIdentity( column.isIdentity() ); + clone.setSize( column.getSize() ); + clone.setSqlType( column.getSqlType() ); + clone.setJdbcDataType( column.getJdbcDataType() ); + clone.setNullable( column.isNullable() ); + clone.setComment( column.getComment() ); + clone.setDefaultValue( column.getDefaultValue() ); + clone.setReadFragment( column.getReadFragment() ); + clone.setWriteFragment( column.getWriteFragment() ); + } + return super.getSqlCreateStrings( table, jdbcEnvironment ); + } + return null; + } + + @Override + protected String tableCreateString(boolean hasPrimaryKey) { + return dialect.getCreateTemporaryTableString(); + } + + @Override + protected void applyTableCheck(Table table, StringBuilder buf) { + // N/A + } + + @Override + protected void applyComments(Table table, List sqlStrings) { + // N/A + } + + @Override + protected void applyTableTypeString(StringBuilder buf) { + buf.append( " " ).append( dialect.getCreateTemporaryTablePostfix() ); + } + + @Override + public String[] getSqlDropStrings(Table exportable, JdbcEnvironment jdbcEnvironment) { + return null; + } + + public static String generateTableName(final Dialect dialect, final TableSpecification primaryTable) { + return dialect.generateTemporaryTableName( primaryTable.getLogicalName().getText() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java new file mode 100644 index 0000000000..12d72e9f2c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java @@ -0,0 +1 @@ +package org.hibernate.tool.schema; \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java new file mode 100644 index 0000000000..10408f392e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Exportable; + +/** + * Defines a contract for exporting of database objects (tables, sequences, etc) for use in SQL {@code CREATE} and + * {@code DROP} scripts + * + * @author Steve Ebersole + */ +public interface Exporter { + public static final String[] NO_COMMANDS = new String[0]; + + /** + * Get the commands needed for creation. + * + * @return The commands needed for creation scripting. + */ + public String[] getSqlCreateStrings(T exportable, JdbcEnvironment jdbcEnvironment); + + /** + * Get the commands needed for dropping. + * + * @return The commands needed for drop scripting. + */ + public String[] getSqlDropStrings(T exportable, JdbcEnvironment jdbcEnvironment); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java new file mode 100644 index 0000000000..4ee9713996 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; + +/** + * Service delegate for handling schema creation. + * + * @author Steve Ebersole + */ +public interface SchemaCreator { + /** + * Perform the creation to the specified targets + * + * @param database The Hibernate relational model to create + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * @param targets The targets for creation + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doCreation(Database database, boolean createSchemas, Target... targets) throws SchemaManagementException; + + /** + * Perform the creation to the specified targets + * + * + * @param database The Hibernate relational model to create + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * + * @param targets The targets for creation + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doCreation(Database database, boolean createSchemas, List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java new file mode 100644 index 0000000000..1b5305fb36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; + +/** + * Service delegate for handling schema dropping. + * + * @author Steve Ebersole + */ +public interface SchemaDropper { + /** + * Perform the drop to the specified targets + * + * @param database The Hibernate relational model to drop + * @param dropSchemas Should the schema(s) actually be dropped also ({@code DROP SCHEMA})? + * @param targets The targets for drop + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doDrop(Database database, boolean dropSchemas, Target... targets) throws SchemaManagementException; + + /** + * Perform the drop to the specified targets + * + * @param database The Hibernate relational model to drop + * @param dropSchemas Should the schema(s) actually be dropped also ({@code DROP SCHEMA})? + * @param targets The targets for drop + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doDrop(Database database, boolean dropSchemas, List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java rename to hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java index 50e5edd443..3798b13d84 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,19 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.tool.schema.spi; + +import org.hibernate.HibernateException; /** + * Indicates a problem in performing schema management. + * * @author Steve Ebersole - * @author Gail Badner */ -public class ManyToAnyCollectionElement extends AbstractCollectionElement { - ManyToAnyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); +public class SchemaManagementException extends HibernateException { + public SchemaManagementException(String message) { + super( message ); } - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.MANY_TO_ANY; + public SchemaManagementException(String message, Throwable root) { + super( message, root ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java new file mode 100644 index 0000000000..2bda8df226 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.Map; + +import org.hibernate.service.Service; + +/** + * Contract for schema management tool integration. + * + * @author Steve Ebersole + */ +public interface SchemaManagementTool extends Service { + public SchemaCreator getSchemaCreator(Map options); + public SchemaDropper getSchemaDropper(Map options); + public SchemaMigrator getSchemaMigrator(Map options); + public SchemaValidator getSchemaValidator(Map options); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java new file mode 100644 index 0000000000..dc34db162d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; + +/** + * Service delegate for handling schema migration. + * + * @author Steve Ebersole + */ +public interface SchemaMigrator { + /** + * Perform a migration to the specified targets. + * + * @param database The current Hibernate relational model + * @param existingDatabase Access to the information about the existing database. + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * @param targets The migration targets + * + * @throws SchemaManagementException + */ + public void doMigration( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java similarity index 60% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java rename to hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java index 9b0b6dc770..fb45ce754a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,25 +21,24 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.tool.schema.spi; -import java.io.Serializable; - -import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; /** - * Auxiliary database objects (i.e., triggers, stored procedures, etc) defined - * in the mappings. Allows Hibernate to manage their lifecycle as part of - * creating/dropping the schema. + * Service delegate for handling schema validations * * @author Steve Ebersole */ -public interface AuxiliaryDatabaseObject extends Exportable, Serializable { +public interface SchemaValidator { /** - * Does this database object apply to the given dialect? + * Handle schema validation requests * - * @param dialect The dialect to check against. - * @return True if this database object does apply to the given dialect. + * @param database The current Hibernate relational model + * @param databaseInformation Access to the existing database information. + * + * @throws SchemaManagementException */ - boolean appliesToDialect(Dialect dialect); + public void doValidation(Database database, DatabaseInformation databaseInformation) throws SchemaManagementException; } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java new file mode 100644 index 0000000000..b351653c90 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +/** + * Describes the target of schema management actions. Typically this would be a stream/writer or the database + * Connection + * + * @author Steve Ebersole + */ +public interface Target { + /** + * Does this target accept actions coming from an import script? If {@code false}, actions are not + * sent to this target's {@link #accept(String)} method + * + * @return {@code true} if import script actions should be sent to this target; {@code false} if they should not. + */ + public boolean acceptsImportScriptActions(); + + /** + * Prepare for accepting actions + * + * @throws SchemaManagementException If there is a problem preparing the target. + */ + public void prepare(); + + /** + * Accept a management action. For stream/writer-based targets, this would indicate to write the action; for + * JDBC based targets, it would indicate to execute the action + * + * @param action The action to perform. + * + * @throws SchemaManagementException If there is a problem accepting the action. + */ + public void accept(String action); + + /** + * Release the target after all actions have been processed. + * + * @throws SchemaManagementException If there is a problem releasing the target. + */ + public void release(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java b/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java index 2b3b7ad8a2..bcf652a587 100755 --- a/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java @@ -31,7 +31,7 @@ import java.util.Map; import java.util.Set; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; public class DynamicMapInstantiator implements Instantiator { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java index 7ebf894a05..7dd9e79deb 100755 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java @@ -35,7 +35,9 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; import org.jboss.logging.Logger; @@ -71,6 +73,33 @@ public class PojoInstantiator implements Instantiator, Serializable { } } + public PojoInstantiator( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + ReflectionOptimizer.InstantiationOptimizer optimizer) { + if ( isIdentifierMapper ) { + final EntityIdentifier entityIdentifier = + compositeAttributeBindingContainer.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + this.mappedClass = entityIdentifier.getIdClassClass(); + } + else { + this.mappedClass = compositeAttributeBindingContainer.getClassReference(); + } + this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); + this.optimizer = optimizer; + + this.proxyInterface = null; + this.embeddedIdentifier = false; + + try { + constructor = ReflectHelper.getDefaultConstructor(mappedClass); + } + catch ( PropertyNotFoundException pnfe ) { + LOG.noDefaultConstructor(mappedClass.getName()); + constructor = null; + } + } + public PojoInstantiator(PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) { this.mappedClass = persistentClass.getMappedClass(); this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); @@ -90,8 +119,8 @@ public class PojoInstantiator implements Instantiator, Serializable { public PojoInstantiator(EntityBinding entityBinding, ReflectionOptimizer.InstantiationOptimizer optimizer) { this.mappedClass = entityBinding.getEntity().getClassReference(); this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); - this.proxyInterface = entityBinding.getProxyInterfaceType().getValue(); - this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded(); + this.proxyInterface = entityBinding.getProxyInterfaceType() == null ? null : entityBinding.getProxyInterfaceType().getValue(); + this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite(); this.optimizer = optimizer; try { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java index c9b5d50990..9af11cca65 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java @@ -28,7 +28,6 @@ import java.lang.reflect.Constructor; import org.hibernate.EntityMode; import org.hibernate.FetchMode; import org.hibernate.HibernateException; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.internal.UnsavedValueFactory; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; @@ -40,17 +39,19 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AssociationAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Fetchable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; +import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.entity.EntityBasedAssociationAttribute; import org.hibernate.tuple.entity.EntityBasedBasicAttribute; import org.hibernate.tuple.entity.EntityBasedCompositionAttribute; @@ -117,48 +118,62 @@ public final class PropertyFactory { * Generates an IdentifierProperty representation of the for a given entity mapping. * * @param mappedEntity The mapping definition of the entity. - * @param generator The identifier value generator to use for this identifier. + * @param generator The identifier value generator to use for this identifier + * @param sessionFactory The session factory. * @return The appropriate IdentifierProperty definition. + * + * TODO: remove session factory parameter. */ public static IdentifierProperty buildIdentifierProperty( EntityBinding mappedEntity, - IdentifierGenerator generator) { + IdentifierGenerator generator, + SessionFactoryImplementor sessionFactory) { - final BasicAttributeBinding property = mappedEntity.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + final SingularAttributeBinding attributeBinding = + mappedEntity.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); // TODO: the following will cause an NPE with "virtual" IDs; how should they be set? // (steve) virtual attributes will still be attributes, they will simply be marked as virtual. - // see org.hibernate.metamodel.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute() + // see org.hibernate.metamodel.spi.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute() - final String mappedUnsavedValue = property.getUnsavedValue(); - final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); + final String mappedUnsavedValue = mappedEntity.getHierarchyDetails().getEntityIdentifier().getUnsavedValue(); + final Type type; + if ( mappedEntity.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper() ) { + type = sessionFactory.getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( ( (CompositeAttributeBinding) attributeBinding ), true, true ) + ); + } + else { + type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + } IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( mappedUnsavedValue, - getGetter( property ), + getGetter( attributeBinding ), type, getConstructor( mappedEntity ) - ); + ); - if ( property == null ) { + if ( attributeBinding.getAttribute().isSynthetic() ) { // this is a virtual id property... return new IdentifierProperty( - type, - mappedEntity.getHierarchyDetails().getEntityIdentifier().isEmbedded(), + type, + mappedEntity.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite() && + mappedEntity.getHierarchyDetails().getEntityIdentifier().getIdClassClass() == null, mappedEntity.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper(), unsavedValue, generator - ); + ); } else { return new IdentifierProperty( - property.getAttribute().getName(), + attributeBinding.getAttribute().getName(), null, type, - mappedEntity.getHierarchyDetails().getEntityIdentifier().isEmbedded(), + mappedEntity.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite(), unsavedValue, generator - ); + ); } } @@ -211,15 +226,50 @@ public final class PropertyFactory { * Generates a VersionProperty representation for an entity mapping given its * version mapping Property. * - * @param property The version mapping Property. * @param lazyAvailable Is property lazy loading currently available. * @return The appropriate VersionProperty definition. */ public static VersionProperty buildVersionProperty( EntityPersister persister, - BasicAttributeBinding property, + SessionFactoryImplementor sessionFactory, + int attributeNumber, + EntityBinding entityBinding, boolean lazyAvailable) { - throw new NotYetImplementedException(); + final BasicAttributeBinding property = entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(); + final String mappedUnsavedValue = entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue(); + final VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue( + mappedUnsavedValue, + getGetter( property ), + (VersionType) property.getHibernateTypeDescriptor().getResolvedTypeMapping(), + getConstructor( (EntityBinding) property.getContainer() ) + ); + + boolean lazy = lazyAvailable && property.isLazy(); + + final CascadeStyle cascadeStyle = property.isCascadeable() + ? ( (Cascadeable) property ).getCascadeStyle() + : CascadeStyles.NONE; + + // TODO: set value generation strategy properly + return new VersionProperty( + persister, + sessionFactory, + attributeNumber, + property.getAttribute().getName(), + property.getHibernateTypeDescriptor().getResolvedTypeMapping(), + new BaselineAttributeInformation.Builder() + .setLazy( lazy ) + .setInsertable( true ) + .setUpdateable( true ) + .setValueGenerationStrategy( null ) + .setNullable( property.isNullable() || property.isOptional() ) + .setDirtyCheckable( !lazy ) + .setVersionable( property.isIncludedInOptimisticLocking() ) + .setCascadeStyle( cascadeStyle ) + .createInformation(), + + unsavedValue + ); } public static enum NonIdentifierAttributeNature { @@ -326,6 +376,109 @@ public final class PropertyFactory { } } + public static NonIdentifierAttribute buildEntityBasedAttribute( + EntityPersister persister, + SessionFactoryImplementor sessionFactory, + int attributeNumber, + AttributeBinding property, + boolean lazyAvailable) { + final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); + final NonIdentifierAttributeNature nature = decode( type ); + final boolean alwaysDirtyCheck = type.isAssociationType() && + ( (AssociationType) type ).isAlwaysDirtyChecked(); + final String name = property.getAttribute().getName(); + final BaselineAttributeInformation.Builder builder = new BaselineAttributeInformation.Builder(); + final FetchMode fetchMode = Fetchable.class.isInstance( property ) + ? ( (Fetchable) property ).getFetchMode() + : FetchMode.DEFAULT; + builder.setFetchMode( fetchMode ).setVersionable( property.isIncludedInOptimisticLocking() ) + .setLazy( lazyAvailable && property.isLazy() ); + if ( property.getAttribute().isSingular() ) { + //basic, association, composite + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) property; + final CascadeStyle cascadeStyle = singularAttributeBinding.isCascadeable() + ? ( (Cascadeable) singularAttributeBinding ).getCascadeStyle() + : CascadeStyles.NONE; + + // TODO: set value generation strategy properly + builder.setInsertable( singularAttributeBinding.isIncludedInInsert() ) + .setUpdateable( singularAttributeBinding.isIncludedInUpdate() ) + .setValueGenerationStrategy( null ) + .setNullable( singularAttributeBinding.isNullable() || singularAttributeBinding.isOptional() ) + .setDirtyCheckable( + alwaysDirtyCheck || singularAttributeBinding.isIncludedInUpdate() + ) + .setCascadeStyle( cascadeStyle ); + switch ( nature ) { + case BASIC: { + return new EntityBasedBasicAttribute( + persister, + sessionFactory, + attributeNumber, + name, + type, + builder.createInformation() + ); + } + case COMPOSITE: { + return new EntityBasedCompositionAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (CompositeType) type, + builder.createInformation() + ); + } + case ENTITY: + case ANY: { + return new EntityBasedAssociationAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (AssociationType) type, + builder.createInformation() + ); + } + default: { + throw new HibernateException( "Internal error" ); + } + } + } + else { + final AbstractPluralAttributeBinding pluralAttributeBinding = (AbstractPluralAttributeBinding) property; + final CascadeStyle cascadeStyle; + if ( pluralAttributeBinding.isCascadeable() ) { + final Cascadeable elementBinding = + (Cascadeable) pluralAttributeBinding.getPluralAttributeElementBinding(); + cascadeStyle = elementBinding.getCascadeStyle(); + } + else { + cascadeStyle = CascadeStyles.NONE; + } + + // TODO: set value generation strategy properly + builder.setInsertable( pluralAttributeBinding.getPluralAttributeKeyBinding().isInsertable() ) + .setUpdateable( pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable() ) + .setValueGenerationStrategy( null ) + .setNullable( true ) + .setDirtyCheckable( + alwaysDirtyCheck || pluralAttributeBinding.getPluralAttributeKeyBinding() + .isUpdatable() + ) + .setCascadeStyle( cascadeStyle ); + return new EntityBasedAssociationAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (AssociationType) type, + builder.createInformation() + ); + } + } + private static NonIdentifierAttributeNature decode(Type type) { if ( type.isAssociationType() ) { AssociationType associationType = (AssociationType) type; @@ -401,22 +554,23 @@ public final class PropertyFactory { if ( property.getAttribute().isSingular() ) { final SingularAttributeBinding singularAttributeBinding = ( SingularAttributeBinding ) property; - final CascadeStyle cascadeStyle = singularAttributeBinding.isAssociation() - ? ( (AssociationAttributeBinding) singularAttributeBinding ).getCascadeStyle() + final CascadeStyle cascadeStyle = singularAttributeBinding.isCascadeable() + ? ( (Cascadeable) singularAttributeBinding ).getCascadeStyle() : CascadeStyles.NONE; final FetchMode fetchMode = singularAttributeBinding.isAssociation() - ? ( (AssociationAttributeBinding) singularAttributeBinding ).getFetchMode() + ? ( (Fetchable) singularAttributeBinding ).getFetchMode() : FetchMode.DEFAULT; + // TODO: set value generation strategy properly return new StandardProperty( singularAttributeBinding.getAttribute().getName(), type, lazyAvailable && singularAttributeBinding.isLazy(), - true, // insertable - true, // updatable + singularAttributeBinding.isIncludedInInsert(), // insertable + singularAttributeBinding.isIncludedInUpdate(), // updatable null, - singularAttributeBinding.isNullable(), - alwaysDirtyCheck || areAllValuesIncludedInUpdate( singularAttributeBinding ), + singularAttributeBinding.isNullable() || singularAttributeBinding.isOptional(), + alwaysDirtyCheck || singularAttributeBinding.isIncludedInUpdate(), singularAttributeBinding.isIncludedInOptimisticLocking(), cascadeStyle, fetchMode @@ -424,44 +578,36 @@ public final class PropertyFactory { } else { final AbstractPluralAttributeBinding pluralAttributeBinding = (AbstractPluralAttributeBinding) property; - final CascadeStyle cascadeStyle = pluralAttributeBinding.isAssociation() - ? pluralAttributeBinding.getCascadeStyle() - : CascadeStyles.NONE; + final CascadeStyle cascadeStyle; + if ( pluralAttributeBinding.isCascadeable() ) { + final Cascadeable elementBinding = + (Cascadeable) pluralAttributeBinding.getPluralAttributeElementBinding(); + cascadeStyle = elementBinding.getCascadeStyle(); + } + else { + cascadeStyle = CascadeStyles.NONE; + } final FetchMode fetchMode = pluralAttributeBinding.isAssociation() ? pluralAttributeBinding.getFetchMode() : FetchMode.DEFAULT; + // TODO: set value generation strategy properly return new StandardProperty( pluralAttributeBinding.getAttribute().getName(), type, lazyAvailable && pluralAttributeBinding.isLazy(), - // TODO: fix this when HHH-6356 is fixed; for now assume AbstractPluralAttributeBinding is updatable and insertable - true, // pluralAttributeBinding.isInsertable(), - true, //pluralAttributeBinding.isUpdatable(), + pluralAttributeBinding.getPluralAttributeKeyBinding().isInsertable(), + pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable(), null, - false, // nullable - not sure what that means for a collection - // TODO: fix this when HHH-6356 is fixed; for now assume AbstractPluralAttributeBinding is updatable and insertable - //alwaysDirtyCheck || pluralAttributeBinding.isUpdatable(), - true, + true, // plural attributes are nullable + alwaysDirtyCheck || pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable(), pluralAttributeBinding.isIncludedInOptimisticLocking(), cascadeStyle, fetchMode - ); + ); } } - private static boolean areAllValuesIncludedInUpdate(SingularAttributeBinding attributeBinding) { - if ( attributeBinding.hasDerivedValue() ) { - return false; - } - for ( SimpleValueBinding valueBinding : attributeBinding.getSimpleValueBindings() ) { - if ( ! valueBinding.isIncludeInUpdate() ) { - return false; - } - } - return true; - } - private static Constructor getConstructor(PersistentClass persistentClass) { if ( persistentClass == null || !persistentClass.hasPojoRepresentation() ) { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java index 14158a7b25..6d674d7caf 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java @@ -30,6 +30,8 @@ import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.tuple.Instantiator; @@ -51,6 +53,22 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { protected abstract Getter buildGetter(Component component, Property prop); protected abstract Setter buildSetter(Component component, Property prop); + protected abstract Instantiator buildInstantiator( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper + ); + protected abstract Getter buildGetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding + ); + protected abstract Setter buildSetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding + ); + + protected AbstractComponentTuplizer(Component component) { propertySpan = component.getPropertySpan(); getters = new Getter[propertySpan]; @@ -72,6 +90,33 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { instantiator = buildInstantiator( component ); } + // TODO: Get rid of the need for isIdentifierMapper arg. + // Instead the CompositeAttributeBinding should be wrapped (e.g., by a proxy) + // so it can provide the information needed to create getters and setters + // for an identifier mapper. + protected AbstractComponentTuplizer( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper + ) { + propertySpan = compositeAttributeBindingContainer.attributeBindingSpan(); + getters = new Getter[propertySpan]; + setters = new Setter[propertySpan]; + + boolean foundCustomAccessor = false; + + int i = 0; + for ( AttributeBinding attributeBinding : compositeAttributeBindingContainer.attributeBindings() ) { + getters[i] = buildGetter( compositeAttributeBindingContainer, isIdentifierMapper, attributeBinding ); + setters[i] = buildSetter( compositeAttributeBindingContainer, isIdentifierMapper, attributeBinding ); + if ( !attributeBinding.isBasicPropertyAccessor() ) { + foundCustomAccessor = true; + } + i++; + } + hasCustomAccessors = foundCustomAccessor; + instantiator = buildInstantiator( compositeAttributeBindingContainer, isIdentifierMapper ); + } + public Object getPropertyValue(Object component, int i) throws HibernateException { return getters[i].get( component ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java index 8b40ca7df9..2681c49b2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java @@ -122,7 +122,7 @@ public abstract class AbstractCompositionAttribute ) ); } - else if ( aType.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + else if ( aType.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { final String lhsTableName; final String[] lhsColumnNames; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java index aab4c71c08..0d9a4924c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java @@ -33,6 +33,8 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; import org.hibernate.tuple.PropertyFactory; import org.hibernate.tuple.StandardProperty; @@ -84,6 +86,38 @@ public class ComponentMetamodel implements Serializable { ) : componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); } + public ComponentMetamodel( + CompositeAttributeBindingContainer component, + boolean isIdentifierAttributeBinding, + boolean isIdentifierMapper) { + this.isKey = isIdentifierAttributeBinding; + this.role = component.getPathBase(); + propertySpan = component.attributeBindingSpan(); + properties = new StandardProperty[propertySpan]; + int i = 0; + for ( AttributeBinding attributeBinding : component.attributeBindings() ) { + properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, false ); + propertyIndexes.put( attributeBinding.getAttribute().getName(), i ); + i++; + } + + entityMode = component.seekEntityBinding().getHierarchyDetails().getEntityMode(); + + // todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel + final ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory(); + final Class tuplizerClass = component.getCustomTuplizerClass(); + if ( tuplizerClass == null ) { + componentTuplizer = componentTuplizerFactory.constructDefaultTuplizer( + entityMode, component, isIdentifierMapper + ); + } + else { + componentTuplizer = componentTuplizerFactory.constructTuplizer( + tuplizerClass, component, isIdentifierMapper + ); + } + } + public boolean isKey() { return isKey; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java index 9a117622a2..69123e693f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java @@ -34,8 +34,9 @@ import org.hibernate.tuple.Tuplizer; * a mapped components. *

* ComponentTuplizer implementations should have the following constructor signature: - * (org.hibernate.mapping.Component) - * + * ({@link org.hibernate.mapping.Component}) + * ({@link org.hibernate.metamodel.spi.binding.CompositeAttributeBinding}, boolean) + * * @author Gavin King * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java index bd92250177..6b66a18522 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java @@ -32,6 +32,7 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; /** * A registry allowing users to define the default {@link ComponentTuplizer} class to use per {@link EntityMode}. @@ -40,6 +41,10 @@ import org.hibernate.mapping.Component; */ public class ComponentTuplizerFactory implements Serializable { private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class }; + private static final Class[] COMPONENT_TUP_CTOR_SIG_NEW = new Class[] { + CompositeAttributeBindingContainer.class, + boolean.class + }; private Map> defaultImplClassByMode = buildBaseMapping(); @@ -53,7 +58,10 @@ public class ComponentTuplizerFactory implements Serializable { public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) { assert isComponentTuplizerImplementor( tuplizerClass ) : "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName(); - assert hasProperConstructor( tuplizerClass ) + // TODO: for now we need constructors for both PersistentClass and EntityBinding + assert hasProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG ) + : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; + assert hasProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG_NEW ) : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; defaultImplClassByMode.put( entityMode, tuplizerClass ); @@ -81,6 +89,31 @@ public class ComponentTuplizerFactory implements Serializable { } } + /** + * Construct an instance of the given tuplizer class. + * + * @param tuplizerClassName The name of the tuplizer class to instantiate + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException If class name cannot be resolved to a class reference, or if the + * {@link Constructor#newInstance} call fails. + */ + @SuppressWarnings({ "unchecked" }) + public ComponentTuplizer constructTuplizer( + String tuplizerClassName, + CompositeAttributeBindingContainer metadata, + boolean isIdentifierMapper) { + try { + Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); + return constructTuplizer( tuplizerClass, metadata, isIdentifierMapper ); + } + catch ( ClassNotFoundException e ) { + throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" ); + } + } + /** * Construct an instance of the given tuplizer class. * @@ -92,7 +125,7 @@ public class ComponentTuplizerFactory implements Serializable { * @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails. */ public ComponentTuplizer constructTuplizer(Class tuplizerClass, Component metadata) { - Constructor constructor = getProperConstructor( tuplizerClass ); + Constructor constructor = getProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG ); assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; try { return constructor.newInstance( metadata ); @@ -102,6 +135,30 @@ public class ComponentTuplizerFactory implements Serializable { } } + /** + * Construct an instance of the given tuplizer class. + * + * @param tuplizerClass The tuplizer class to instantiate + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails. + */ + public ComponentTuplizer constructTuplizer( + Class tuplizerClass, + CompositeAttributeBindingContainer metadata, + boolean isIdentifierMapper) { + Constructor constructor = getProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG_NEW ); + assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; + try { + return constructor.newInstance( metadata, isIdentifierMapper ); + } + catch ( Throwable t ) { + throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t ); + } + } + /** * Construct am instance of the default tuplizer for the given entity-mode. * @@ -122,19 +179,44 @@ public class ComponentTuplizerFactory implements Serializable { return constructTuplizer( tuplizerClass, metadata ); } + /** + * Construct am instance of the default tuplizer for the given entity-mode. + * + * @param entityMode The entity mode for which to build a default tuplizer. + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from + * {@link #constructTuplizer} too. + */ + public ComponentTuplizer constructDefaultTuplizer( + EntityMode entityMode, + CompositeAttributeBindingContainer metadata, + boolean isIdentifierMapper) { + Class tuplizerClass = defaultImplClassByMode.get( entityMode ); + if ( tuplizerClass == null ) { + throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" ); + } + + return constructTuplizer( tuplizerClass, metadata, isIdentifierMapper ); + } + private boolean isComponentTuplizerImplementor(Class tuplizerClass) { return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class ); } @SuppressWarnings({ "unchecked" }) - private boolean hasProperConstructor(Class tuplizerClass) { - return getProperConstructor( tuplizerClass ) != null; + private boolean hasProperConstructor(Class tuplizerClass, Class[] clazzConstructorSignature) { + return getProperConstructor( tuplizerClass, clazzConstructorSignature ) != null; } - private Constructor getProperConstructor(Class clazz) { + private Constructor getProperConstructor( + Class clazz, + Class[] clazzConstructorSignature) { Constructor constructor = null; try { - constructor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG ); + constructor = clazz.getDeclaredConstructor( clazzConstructorSignature ); try { constructor.setAccessible( true ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java index c26b346e02..4ea10ed28d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java @@ -27,6 +27,8 @@ import java.util.Map; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; @@ -54,16 +56,45 @@ public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer { super(component); } - private PropertyAccessor buildPropertyAccessor(Property property) { + public DynamicMapComponentTuplizer( + CompositeAttributeBindingContainer component, + boolean isIdentifierMapper) { + super( component, isIdentifierMapper ); + } + + private PropertyAccessor buildPropertyAccessor() { return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); } protected Getter buildGetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getGetter( null, prop.getName() ); + return buildPropertyAccessor().getGetter( null, prop.getName() ); } protected Setter buildSetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getSetter( null, prop.getName() ); + return buildPropertyAccessor().getSetter( null, prop.getName() ); + } + + @Override + protected Instantiator buildInstantiator( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper) { + return new DynamicMapInstantiator(); + } + + @Override + protected Getter buildGetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + return buildPropertyAccessor().getGetter( null, attributeBinding.getAttribute().getName() ); + } + + @Override + protected Setter buildSetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + return buildPropertyAccessor().getSetter( null, attributeBinding.getAttribute().getName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java index a9b0d5a9cf..53bca23d44 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java @@ -27,6 +27,7 @@ import java.io.Serializable; import java.lang.reflect.Method; import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.bytecode.spi.ReflectionOptimizer; @@ -35,6 +36,9 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; @@ -92,6 +96,52 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { } } + public PojoComponentTuplizer( + CompositeAttributeBindingContainer component, + boolean isIdentifierMapper) { + super( component, isIdentifierMapper ); + + final EntityIdentifier entityIdentifier = + component.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + + this.componentClass = + isIdentifierMapper ? + entityIdentifier.getIdClassClass() : + component.getClassReference(); + + String[] getterNames = new String[propertySpan]; + String[] setterNames = new String[propertySpan]; + Class[] propTypes = new Class[propertySpan]; + for ( int i = 0; i < propertySpan; i++ ) { + getterNames[i] = getters[i].getMethodName(); + setterNames[i] = setters[i].getMethodName(); + propTypes[i] = getters[i].getReturnType(); + } + + final String parentPropertyName = + component.getParentReference() == null ? null : component.getParentReference().getName(); + if ( parentPropertyName == null ) { + parentSetter = null; + parentGetter = null; + } + else { + PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( null ); + parentSetter = pa.getSetter( componentClass, parentPropertyName ); + parentGetter = pa.getGetter( componentClass, parentPropertyName ); + } + + if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { + optimizer = null; + } + else { + // TODO: here is why we need to make bytecode provider global :( + // TODO : again, fix this after HHH-1907 is complete + optimizer = Environment.getBytecodeProvider().getReflectionOptimizer( + componentClass, getterNames, setterNames, propTypes + ); + } + } + public Class getMappedClass() { return componentClass; } @@ -159,12 +209,97 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { return prop.getSetter( component.getComponentClass() ); } + protected Instantiator buildInstantiator( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper) { + if ( !compositeAttributeBindingContainer.isAggregated() && + ReflectHelper.isAbstractClass( compositeAttributeBindingContainer.getClassReference() ) ) { + return new ProxiedInstantiator( compositeAttributeBindingContainer ); + } + if ( optimizer == null ) { + return new PojoInstantiator( compositeAttributeBindingContainer, isIdentifierMapper, null ); + } + else { + return new PojoInstantiator( compositeAttributeBindingContainer, isIdentifierMapper, optimizer.getInstantiationOptimizer() ); + } + } + + @Override + protected Getter buildGetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + // TODO: when compositeAttributeBinding is wrapped for an identifier mapper + // there will be no need for PropertyFactory.getIdentifierMapperGetter() + // and PropertyFactory.getIdentifierMapperSetter + if ( isIdentifierMapper ) { + // HACK ALERT: when isIdentifierMapper is true, the entity identifier + // must be completely bound when this method is called. + final EntityIdentifier entityIdentifier = + compositeAttributeBindingContainer.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + return getGetter( + entityIdentifier.getIdClassClass(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getIdClassPropertyAccessorName() ) + ); + } + else { + return getGetter( + compositeAttributeBindingContainer.getClassReference(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( attributeBinding, EntityMode.POJO ) + ); + } + } + + @Override + protected Setter buildSetter( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + if ( isIdentifierMapper ) { + // HACK ALERT: when isIdentifierMapper is true, the entity identifier + // must be completely bound when this method is called. + final EntityIdentifier entityIdentifier = + compositeAttributeBindingContainer.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + return getSetter( + entityIdentifier.getIdClassClass(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getIdClassPropertyAccessorName() ) + ); + + } + else { + return getSetter( + compositeAttributeBindingContainer.getClassReference(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( attributeBinding, EntityMode.POJO ) + ); + } + } + + private Getter getGetter(Class clazz, String name, PropertyAccessor propertyAccessor) { + return propertyAccessor.getGetter( clazz, name ); + } + + private Setter getSetter(Class clazz, String name, PropertyAccessor propertyAccessor) { + return propertyAccessor.getSetter(clazz, name); + } + private static class ProxiedInstantiator implements Instantiator { private final Class proxiedClass; private final BasicProxyFactory factory; public ProxiedInstantiator(Component component) { - proxiedClass = component.getComponentClass(); + this( component.getComponentClass() ); + } + + public ProxiedInstantiator(CompositeAttributeBindingContainer compositeAttributeBindingContainer) { + this( compositeAttributeBindingContainer.getClassReference() ); + } + + private ProxiedInstantiator(Class proxiedClass) { + this.proxiedClass = proxiedClass; if ( proxiedClass.isInterface() ) { factory = Environment.getBytecodeProvider() .getProxyFactoryFactory() @@ -177,6 +312,7 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { } } + public Object instantiate(Serializable id) { throw new AssertionFailure( "ProxiedInstantiator can only be used to instantiate component" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index 55546ccd94..9ccbe6cc82 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -48,8 +48,9 @@ import org.hibernate.loader.PropertyPath; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.HibernateProxy; @@ -242,8 +243,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { this.entityMetamodel = entityMetamodel; if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); + idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); } else { idGetter = null; @@ -257,11 +258,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { boolean foundCustomAccessor = false; int i = 0; - for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) { - if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - continue; // ID binding processed above - } - + for ( AttributeBinding property : mappingInfo.getNonIdAttributeBindingClosure() ) { //TODO: redesign how PropertyAccessors are acquired... getters[ i ] = buildPropertyGetter( property ); setters[ i ] = buildPropertySetter( property ); @@ -284,19 +281,23 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { proxyFactory = null; } - - // TODO: Fix this when components are working (HHH-6173) - //Component mapper = mappingInfo.getEntityIdentifier().getIdentifierMapper(); - Component mapper = null; - if ( mapper == null ) { + final EntityIdentifier entityIdentifier = mappingInfo.getHierarchyDetails().getEntityIdentifier(); + if ( !entityIdentifier.isIdentifierMapper() ) { identifierMapperType = null; mappedIdentifierValueMarshaller = null; } else { - identifierMapperType = ( CompositeType ) mapper.getType(); + identifierMapperType = (CompositeType) entityMetamodel.getIdentifierProperty().getType(); + + // TODO: this only deals with normal IdClass; still need to deal with MapsId mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller( - ( ComponentType ) entityMetamodel.getIdentifierProperty().getType(), - ( ComponentType ) identifierMapperType + (ComponentType) identifierMapperType, + (ComponentType) mappingInfo + .getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java index 7e376d62b5..77f2f2084e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java @@ -33,8 +33,8 @@ import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; @@ -113,13 +113,12 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer { } private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) { - // TODO: fix when backrefs are working in new metamodel - //if ( mappedProperty.isBackRef() ) { - // return mappedProperty.getPropertyAccessor( null ); - //} - //else { + if ( mappedProperty.isBackRef() ) { + return null; + } + else { return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - //} + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java index 3e1092e387..04f3c11023 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java @@ -93,7 +93,7 @@ public class EntityBasedAssociationAttribute final Joinable joinable = type.getAssociatedJoinable( sessionFactory() ); - if ( type.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + if ( type.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { final String lhsTableName; final String[] lhsColumnNames; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index a0fc8724c2..640def38c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -50,11 +50,13 @@ import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.domain.SingularAttribute; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.IdentifierProperty; @@ -784,33 +786,33 @@ public class EntityMetamodel implements Serializable { identifierAttribute = PropertyFactory.buildIdentifierProperty( entityBinding, - sessionFactory.getIdentifierGenerator( rootName ) + sessionFactory.getIdentifierGenerator( rootName ), + sessionFactory ); versioned = entityBinding.isVersioned(); - boolean hasPojoRepresentation = false; - Class mappedClass = null; + boolean isPOJO = entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO; Class proxyInterfaceClass = null; - if ( entityBinding.getEntity().getClassReferenceUnresolved() != null ) { - hasPojoRepresentation = true; + Class mappedClass = null; + if ( isPOJO ) { mappedClass = entityBinding.getEntity().getClassReference(); - proxyInterfaceClass = entityBinding.getProxyInterfaceType().getValue(); + proxyInterfaceClass = entityBinding.getProxyInterfaceType() == null ? null : entityBinding.getProxyInterfaceType().getValue(); + instrumentationMetadata = Environment.getBytecodeProvider().getEntityInstrumentationMetadata( mappedClass ); + } + else { + instrumentationMetadata = new NonPojoInstrumentationMetadata( entityBinding.getEntity().getName() ); } - instrumentationMetadata = Environment.getBytecodeProvider().getEntityInstrumentationMetadata( mappedClass ); boolean hasLazy = false; // TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding - BasicAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - // entityBinding.getAttributeClosureSpan() includes the identifier binding; - // "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null - propertySpan = rootEntityIdentifier == null ? - entityBinding.getAttributeBindingClosureSpan() : - entityBinding.getAttributeBindingClosureSpan() - 1; + + final AttributeBinding [] attributeBindings = entityBinding.getNonIdAttributeBindingClosure(); + propertySpan = attributeBindings.length; properties = new NonIdentifierAttribute[propertySpan]; - List naturalIdNumbers = new ArrayList(); + List naturalIdNumbers = new ArrayList(); // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ propertyNames = new String[propertySpan]; propertyTypes = new Type[propertySpan]; @@ -824,7 +826,6 @@ public class EntityMetamodel implements Serializable { cascadeStyles = new CascadeStyle[propertySpan]; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // todo : handle value generations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this.hasPreInsertGeneratedValues = false; this.hasPreUpdateGeneratedValues = false; @@ -846,31 +847,40 @@ public class EntityMetamodel implements Serializable { boolean foundUpdateGeneratedValue = false; boolean foundUpdateableNaturalIdProperty = false; - for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == rootEntityIdentifier ) { - // skip the identifier attribute binding - continue; - } + for ( AttributeBinding attributeBinding : attributeBindings ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ) { + if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ) { tempVersionProperty = i; properties[i] = PropertyFactory.buildVersionProperty( persister, - entityBinding.getHierarchyDetails().getVersioningAttributeBinding(), + sessionFactory, + tempVersionProperty, + entityBinding, instrumentationMetadata.isInstrumented() ); } else { - properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, instrumentationMetadata.isInstrumented() ); + properties[i] = PropertyFactory.buildEntityBasedAttribute( + persister, + sessionFactory, + i, + attributeBinding, + instrumentationMetadata.isInstrumented() + ); } - // TODO: fix when natural IDs are added (HHH-6354) - //if ( attributeBinding.isNaturalIdentifier() ) { - // naturalIdNumbers.add( i ); - // if ( attributeBinding.isUpdateable() ) { - // foundUpdateableNaturalIdProperty = true; - // } - //} + if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { + SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast( + attributeBinding + ); + if ( singularAttributeBinding.getNaturalIdMutability() == SingularAttributeBinding.NaturalIdMutability.MUTABLE ) { + naturalIdNumbers.add( i ); + foundUpdateableNaturalIdProperty = true; + } + else if ( singularAttributeBinding.getNaturalIdMutability() == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE ) { + naturalIdNumbers.add( i ); + } + } if ( "id".equals( attributeBinding.getAttribute().getName() ) ) { foundNonIdentifierPropertyNamedId = true; @@ -922,7 +932,7 @@ public class EntityMetamodel implements Serializable { else { naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; - hasCacheableNaturalId = false; //See previous TODO and HHH-6354 + hasCacheableNaturalId = entityBinding.getHierarchyDetails().getNaturalIdCaching() != null; } hasCascades = foundCascade; @@ -935,18 +945,18 @@ public class EntityMetamodel implements Serializable { lazy = entityBinding.isLazy() && ( // TODO: this disables laziness even in non-pojo entity modes: - ! hasPojoRepresentation || + ! isPOJO || ! ReflectHelper.isFinalClass( proxyInterfaceClass ) ); mutable = entityBinding.isMutable(); if ( entityBinding.isAbstract() == null ) { // legacy behavior (with no abstract attribute specified) - isAbstract = hasPojoRepresentation && + isAbstract = isPOJO && ReflectHelper.isAbstractClass( mappedClass ); } else { - isAbstract = entityBinding.isAbstract().booleanValue(); - if ( !isAbstract && hasPojoRepresentation && + isAbstract = entityBinding.isAbstract(); + if ( !isAbstract && isPOJO && ReflectHelper.isAbstractClass( mappedClass ) ) { LOG.entityMappedAsNonAbstract(name); } @@ -979,8 +989,9 @@ public class EntityMetamodel implements Serializable { hasMutableProperties = foundMutable; for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) { + // TODO: is the following correct??? subclassEntityNames.add( subEntityBinding.getEntity().getName() ); - if ( subEntityBinding.getEntity().getClassReference() != null ) { + if ( isPOJO ) { entityNameByInheritenceClassMap.put( subEntityBinding.getEntity().getClassReference(), subEntityBinding.getEntity().getName() ); @@ -991,9 +1002,9 @@ public class EntityMetamodel implements Serializable { entityNameByInheritenceClassMap.put( mappedClass, name ); } - entityMode = hasPojoRepresentation ? EntityMode.POJO : EntityMode.MAP; + entityMode = isPOJO ? EntityMode.POJO : EntityMode.MAP; final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory(); - Class tuplizerClass = entityBinding.getCustomEntityTuplizerClass(); + Class tuplizerClass = entityBinding.getCustomTuplizerClass(); if ( tuplizerClass == null ) { entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, entityBinding ); @@ -1100,9 +1111,9 @@ public class EntityMetamodel implements Serializable { private void mapPropertyToIndex(Attribute attribute, int i) { propertyIndexes.put( attribute.getName(), i ); if ( attribute.isSingular() && - ( ( SingularAttribute ) attribute ).getSingularAttributeType().isComponent() ) { - org.hibernate.metamodel.domain.Component component = - ( org.hibernate.metamodel.domain.Component ) ( ( SingularAttribute ) attribute ).getSingularAttributeType(); + ( ( SingularAttribute ) attribute ).getSingularAttributeType().isAggregate() ) { + Aggregate component = + ( Aggregate ) ( ( SingularAttribute ) attribute ).getSingularAttributeType(); for ( Attribute subAttribute : component.attributes() ) { propertyIndexes.put( attribute.getName() + '.' + subAttribute.getName(), diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java index 229656949b..a20dc0e91d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java @@ -40,7 +40,7 @@ import org.hibernate.tuple.Tuplizer; *

* EntityTuplizer implementations should have the following constructor signatures: * (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.mapping.PersistentClass) - * (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.metamodel.binding.EntityBinding) + * (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.metamodel.spi.binding.EntityBinding) * * @author Gavin King * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java index 8be52bd0c8..7f45e6c2a2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java @@ -32,7 +32,7 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; /** * A registry allowing users to define the default {@link EntityTuplizer} class to use per {@link EntityMode}. diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java index 41945c3436..68421e2583 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java @@ -48,9 +48,12 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Subclass; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.Getter; +import org.hibernate.property.IndexPropertyAccessor; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; @@ -116,8 +119,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { public PojoEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { super( entityMetamodel, mappedEntity ); this.mappedClass = mappedEntity.getEntity().getClassReference(); - this.proxyInterface = mappedEntity.getProxyInterfaceType().getValue(); - this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass ); + this.proxyInterface = mappedEntity.getProxyInterfaceType() == null ? null : mappedEntity.getProxyInterfaceType().getValue(); this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass ); this.isInstrumented = entityMetamodel.isInstrumented(); for ( AttributeBinding property : mappedEntity.getAttributeBindingClosure() ) { @@ -259,10 +261,9 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { // determine the id getter and setter methods from the proxy interface (if any) // determine all interfaces needed by the resulting proxy - HashSet proxyInterfaces = new HashSet(); - proxyInterfaces.add( HibernateProxy.class ); + Set proxyInterfaces = new java.util.LinkedHashSet(); - Class mappedClass = entityBinding.getEntity().getClassReference(); + Class mappedClass = entityBinding.getClassReference(); Class proxyInterface = entityBinding.getProxyInterfaceType().getValue(); if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) { @@ -291,6 +292,8 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { } } + proxyInterfaces.add( HibernateProxy.class ); + for ( AttributeBinding property : entityBinding.attributeBindings() ) { Method method = getGetter( property ).getMethod(); if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { @@ -320,11 +323,11 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod, - entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded() + entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper() ? ( CompositeType ) entityBinding .getHierarchyDetails() .getEntityIdentifier() - .getValueBinding() + .getAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping() : null @@ -441,7 +444,21 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { } private PropertyAccessor getPropertyAccessor(AttributeBinding mappedProperty) throws MappingException { - // TODO: Fix this then backrefs are working in new metamodel + if ( mappedProperty.isBackRef() ) { + BackRefAttributeBinding backRefAttributeBinding = (BackRefAttributeBinding) mappedProperty; + if ( backRefAttributeBinding.isIndexBackRef() ) { + return new IndexPropertyAccessor( + backRefAttributeBinding.getCollectionRole(), + backRefAttributeBinding.getEntityName() + ); + } + else { + return new BackrefPropertyAccessor( + backRefAttributeBinding.getCollectionRole(), + backRefAttributeBinding.getEntityName() + ); + } + } return PropertyAccessorFactory.getPropertyAccessor( mappedProperty.getContainer().getClassReference(), mappedProperty.getPropertyAccessorName() diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java index 49b9cc8d28..9e712b7c6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java @@ -31,7 +31,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * @author Emmanuel Bernard diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index 4d5b0effdd..7f5694d1e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -40,7 +40,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.MutabilityPlan; @@ -359,7 +359,7 @@ public abstract class AbstractStandardBasicType Object owner, Map copyCache, ForeignKeyDirection foreignKeyDirection) { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT == foreignKeyDirection + return ForeignKeyDirection.FROM_PARENT == foreignKeyDirection ? getReplacement( (T) original, (T) target, session ) : target; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java index fdd7aba4e4..1618d16a25 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java @@ -32,7 +32,7 @@ import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Element; import org.dom4j.Node; @@ -173,7 +173,7 @@ public abstract class AbstractType implements Type { include = atype.getForeignKeyDirection()==foreignKeyDirection; } else { - include = ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT==foreignKeyDirection; + include = ForeignKeyDirection.FROM_PARENT==foreignKeyDirection; } return include ? replace(original, target, session, owner, copyCache) : target; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java index 582d65adc3..cdf0eaa331 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java @@ -45,7 +45,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Joinable; import org.hibernate.proxy.HibernateProxy; @@ -464,7 +464,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT @Override public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT; + return ForeignKeyDirection.FROM_PARENT; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java index 3a76e13f9b..6c5e160632 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java @@ -53,7 +53,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.entity.EntityPersister; @@ -366,7 +366,7 @@ public abstract class CollectionType extends AbstractType implements Association @Override public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT; + return ForeignKeyDirection.TO_PARENT; } /** diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index f706f3cc89..9bf572cf0d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -43,7 +43,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.tuple.StandardProperty; import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.component.ComponentTuplizer; diff --git a/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java index 146f4fe127..bc4cbc872a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java @@ -40,7 +40,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.LoggableUserType; diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index 552bd24a84..3cc6e69bc3 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -38,7 +38,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.usertype.EnhancedUserType; import org.hibernate.usertype.LoggableUserType; import org.hibernate.usertype.Sized; diff --git a/hibernate-core/src/main/java/org/hibernate/type/EnumType.java b/hibernate-core/src/main/java/org/hibernate/type/EnumType.java index b6b494b682..788f2826c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EnumType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EnumType.java @@ -38,6 +38,7 @@ import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.usertype.DynamicParameterizedType; import org.hibernate.usertype.EnhancedUserType; @@ -237,6 +238,9 @@ public class EnumType implements EnhancedUserType, DynamicParameterizedType,Logg } else { String enumClassName = (String) parameters.get( ENUM ); + if( StringHelper.isEmpty( enumClassName )){ + enumClassName = (String)parameters.get( DynamicParameterizedType.RETURNED_CLASS ); + } try { enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java b/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java index 594d07dee7..c00aedd109 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java @@ -23,16 +23,35 @@ */ package org.hibernate.type; -import java.io.Serializable; - +import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.internal.CascadePoint; /** * Represents directionality of the foreign key constraint + * * @author Gavin King */ -public abstract class ForeignKeyDirection implements Serializable { - protected ForeignKeyDirection() {} +public enum ForeignKeyDirection { + /** + * A foreign key from child to parent + */ + TO_PARENT { + @Override + public boolean cascadeNow(CascadePoint cascadePoint) { + return cascadePoint != CascadePoint.BEFORE_INSERT_AFTER_DELETE; + } + + }, + /** + * A foreign key from parent to child + */ + FROM_PARENT { + @Override + public boolean cascadeNow(CascadePoint cascadePoint) { + return cascadePoint != CascadePoint.AFTER_INSERT_BEFORE_DELETE; + } + }; + /** * Should we cascade at this cascade point? * @@ -44,40 +63,5 @@ public abstract class ForeignKeyDirection implements Serializable { */ public abstract boolean cascadeNow(CascadePoint cascadePoint); - /** - * A foreign key from child to parent - */ - public static final ForeignKeyDirection FOREIGN_KEY_TO_PARENT = new ForeignKeyDirection() { - @Override - public boolean cascadeNow(CascadePoint cascadePoint) { - return cascadePoint != CascadePoint.BEFORE_INSERT_AFTER_DELETE; - } - - @Override - public String toString() { - return "toParent"; - } - - Object readResolve() { - return FOREIGN_KEY_TO_PARENT; - } - }; - /** - * A foreign key from parent to child - */ - public static final ForeignKeyDirection FOREIGN_KEY_FROM_PARENT = new ForeignKeyDirection() { - @Override - public boolean cascadeNow(CascadePoint cascadePoint) { - return cascadePoint != CascadePoint.AFTER_INSERT_BEFORE_DELETE; - } - - @Override - public String toString() { - return "fromParent"; - } - - Object readResolve() { - return FOREIGN_KEY_FROM_PARENT; - } - }; } + diff --git a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java index 63c76af840..86ad050789 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java @@ -36,7 +36,7 @@ import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; /** @@ -176,7 +176,7 @@ public class ManyToOneType extends EntityType { } public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT; + return ForeignKeyDirection.FROM_PARENT; } public Object hydrate( diff --git a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java index da7d9e385e..4d17afc196 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java @@ -34,7 +34,7 @@ import org.hibernate.MappingException; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Node; diff --git a/hibernate-core/src/main/java/org/hibernate/type/NullableType.java b/hibernate-core/src/main/java/org/hibernate/type/NullableType.java index a8c4efcf7e..82a3370df6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/NullableType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/NullableType.java @@ -35,7 +35,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java index 960adf18d8..539a8541ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java @@ -34,7 +34,7 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; /** @@ -178,7 +178,7 @@ public class OneToOneType extends EntityType { } protected boolean isNullable() { - return foreignKeyType==ForeignKeyDirection.FOREIGN_KEY_TO_PARENT; + return foreignKeyType==ForeignKeyDirection.TO_PARENT; } public boolean useLHSPrimaryKey() { diff --git a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java index 70c86b3f6a..ccc0c86762 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java @@ -33,7 +33,7 @@ import org.hibernate.MappingException; import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * A one-to-one association that maps to specific formula(s) diff --git a/hibernate-core/src/main/java/org/hibernate/type/Type.java b/hibernate-core/src/main/java/org/hibernate/type/Type.java index e486934784..25df093f28 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/type/Type.java @@ -34,7 +34,7 @@ import org.hibernate.MappingException; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Node; diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java b/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java index 3f3e63080f..32ad6fa3c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java @@ -23,7 +23,7 @@ */ package org.hibernate.usertype; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * Extends dictated/default column size declarations from {@link org.hibernate.type.Type} to the {@link UserType} diff --git a/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd b/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd index ae67440487..21989e7032 100644 --- a/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd +++ b/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd @@ -1,1816 +1,1990 @@ - + + + An instance of this XML document may contain mappings for an arbitrary + number of classes. The class mappings may contain associations to classes + mapped in the same document or in another document. No class may be + mapped more than once. Each document may also contain definitions of an + arbitrary number of queries, and import declarations of arbitrary classes. + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + The document root. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Root entity mapping. Poorly named as entities do not have to be represented by + classes at all. Mapped entities may be represented via different methodologies + (POJO, Map, Dom4j). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + A composite key may be modelled by a java class with a property for each + key column. The class must implement java.io.Serializable and reimplement equals() + and hashCode(). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Versioned data requires a column holding a version number. This is exposed to the + application through a property of the Java class. + + + + + + + + + + + + + + + + + + A natural-id element allows declaration of the unique business key + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Collection declarations nested inside a class declaration indicate a foreign key + relationship from the collection table to the enclosing class. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares the type and column mapping for a collection index (array or + list index, or key of a map). + + + + + + + + + + + + + One to many association. This tag declares the entity-class + element type of a collection and specifies a one-to-many relational model + + + + + + + + + + + + + Declares a one-to-one association between two entities (Or from a component, + component element, etc. to an entity). + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares an association between two entities (Or from a component, component element, + etc. to an entity). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Many to many association. This tag declares the entity-class + element type of a collection and specifies a many-to-many relational model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + allows customized short-naming of IdentifierGenerator implementations. + ]]> + + + + + + + + IMPORT element definition; an explicit query language "import" + + + + + + + + + + + + + + + + + + + + Polymorphic data requires a column holding a class discriminator value. This + value is not directly exposed to the application. + + + + + + + + + + + + + + + + + - #2 : + #2 : CREATE OR REPLACE .... DROP .... - --> - - - - + ]]> + + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + dialect-scope element allows scoping auxiliary-objects to a particular + Hibernate dialect implementation. + + + + + + + + + + + allows defining a customized type mapping for a Hibernate type. May + contain parameters for parameterizable types. + ]]> + + + + + + + + + + + FILTER-DEF element; top-level filter definition. + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + An "any" association is a polymorphic association to any table with + the given identifier type. The first listed column is a VARCHAR column + holding the name of the class (for that row). + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + The column element is an alternative to column attributes and required for + mapping associations to classes with composite ids. + + + + + + The comment element allows definition of a database table or column comment. + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + A component is a user-defined class, persisted along with its containing entity + to the table of the entity class. JavaBeans style properties of the component are + mapped to columns of the table of the containing entity. A null component reference + is mapped to null values in all columns and vice versa. Components do not support + shared reference semantics. + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + A composite element allows a collection to hold instances of an arbitrary + class, without the requirement of joining to an entity table. Composite elements + have component semantics - no shared references and ad hoc null value semantics. + Composite elements may not hold nested collections. + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + A dynamic-component maps columns of the database entity to a java.util.Map + at the Java level + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Declares the element type of a collection of basic type + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + element defines a single path to which the fetch + refers, as well as the style of fetch to apply. The 'root' of the + path is different depending upon the context in which the + containing occurs; within a element, + the entity-name of the containing class mapping is assumed... + ]]> + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + + + FILTER element; used to apply a filter. + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + Generators generate unique identifiers. The class attribute specifies a Java + class implementing an id generation algorithm. + + + + + + + + + + + + + + + + + + + + + + + A join allows some properties of a class to be persisted to a second table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares the column name of a foreign key. + + + + + + + + + + + + + + + + + + A many-to-one association embedded in a composite identifier or map index + (always not-null, never cascade). + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - + - - - - + + + + A property embedded in a composite identifier or map index (always not-null). + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + The loader element allows specification of a named query to be used for fetching + an entity or collection + + + + - - - - - - - - - - - - - - - - + + + + A "many to any" defines a polymorphic association to any table + with the given identifier type. The first listed column is a VARCHAR column + holding the name of the class (for that row). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Composite index of a map ie. a map keyed on components. + + + + + + + + + + + + + + + + + + + Many to many association mapped to the key of a map. ie. a map keyed + on entities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + is used to assign meta-level attributes to a class + or property. Is currently used by codegenerator as a placeholder for + values that is not directly related to OR mappings. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The parent element maps a property of the component class as a pointer back to + the owning entity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + properties declares that the contained properties form an alternate key. The name + attribute allows an alternate key to be used as the target of a property-ref. + + + + + + + + + + + + + + + + + + + + + + + + + + + Property of an entity class or component, component-element, composite-id, etc. + JavaBeans style properties are mapped to table columns. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The sql-query element declares a named SQL query string + + + + + + + + + + + + + + + + + + + + + + + + + The query element declares a named Hibernate query string + + + + + + + + + + + + + + + + + + + + The query-param element is used only by tools that generate + finder methods for named queries + + + + + + + + + + FILTER-PARAM element; qualifies parameters found within a FILTER-DEF + condition. + + + + + + + + + + The resultset element declares a named resultset mapping definition for SQL queries + + + + + + + + + + + + + + + + + Defines a return component for a sql-query. Alias refers to the alias + used in the actual sql query; lock-mode specifies the locking to be applied + when the query is executed. The class, collection, and role attributes are mutually exclusive; + class refers to the class name of a "root entity" in the object result; collection refers + to a collection of a given class and is used to define custom sql to load that owned collection + and takes the form "ClassName.propertyName"; role refers to the property path for an eager fetch + and takes the form "owningAlias.propertyName" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TUPLIZER element; defines tuplizer to use for a component/entity for a given entity-mode + + + + + + + + + + + Declares the type of the containing property (overrides an eventually existing type + attribute of the property). May contain param elements to customize a ParametrizableType. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Define a class name type which can be used in the attribute value which requires a class name, + either qualified or not, time to do the validation. + + + + + + diff --git a/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb b/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb index 59b19b75b1..f73558fb48 100644 --- a/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb +++ b/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb @@ -1,8 +1,8 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + version="2.1"> @@ -15,4 +15,9 @@ + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb b/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb index 51811d9748..c2cf76cc44 100644 --- a/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb +++ b/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb @@ -1,10 +1,10 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" + jaxb:extensionBindingPrefixes="inheritance" + version="2.1"> @@ -18,107 +18,160 @@ - - org.hibernate.internal.jaxb.mapping.hbm.EntityElement - org.hibernate.internal.jaxb.mapping.hbm.JoinElementSource + + org.hibernate.jaxb.spi.hbm.EntityElement + org.hibernate.jaxb.spi.hbm.TableInformationSource + org.hibernate.jaxb.spi.hbm.JoinElementSource + + + org.hibernate.jaxb.spi.hbm.ReturnElement + + + org.hibernate.jaxb.spi.hbm.ReturnElement + + + org.hibernate.jaxb.spi.hbm.ReturnElement - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement - org.hibernate.internal.jaxb.mapping.hbm.JoinElementSource + org.hibernate.jaxb.spi.hbm.SubEntityElement + org.hibernate.jaxb.spi.hbm.JoinElementSource - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement + org.hibernate.jaxb.spi.hbm.SubEntityElement + org.hibernate.jaxb.spi.hbm.TableInformationSource - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement + org.hibernate.jaxb.spi.hbm.SubEntityElement + org.hibernate.jaxb.spi.hbm.TableInformationSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement + + org.hibernate.jaxb.spi.hbm.TableInformationSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement - - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement - - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement - - - org.hibernate.internal.jaxb.mapping.hbm.SingularAttributeSource + org.hibernate.jaxb.spi.hbm.SingularAttributeSource - - org.hibernate.internal.jaxb.mapping.hbm.SingularAttributeSource + + org.hibernate.jaxb.spi.hbm.SingularAttributeSource + + + org.hibernate.jaxb.spi.hbm.ComponentSourceElement + + + org.hibernate.jaxb.spi.hbm.ComponentSourceElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.jaxb.spi.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.IdBagPluralAttributeElementAdapter + org.hibernate.jaxb.spi.hbm.IdBagPluralAttributeElementAdapter - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.jaxb.spi.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.jaxb.spi.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.jaxb.spi.hbm.PluralAttributeElement + + + org.hibernate.metamodel.spi.source.MetaAttributeSource + + + org.hibernate.metamodel.spi.source.FilterParameterSource + + + org.hibernate.jaxb.spi.hbm.PluralAttributeElement - + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - @@ -131,36 +184,38 @@ - - - - - - - + - + - - - + - + + - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/orm-bindings.xjb b/hibernate-core/src/main/xjb/orm-bindings.xjb index 940eb3a86a..c9ed56908b 100644 --- a/hibernate-core/src/main/xjb/orm-bindings.xjb +++ b/hibernate-core/src/main/xjb/orm-bindings.xjb @@ -1,10 +1,12 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" + jaxb:extensionBindingPrefixes="inheritance" + version="2.1"> - + @@ -13,6 +15,96 @@ + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.SchemaAware + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.EntityElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.EntityElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.EntityElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.PropertyElement + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.Listener + + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.AttributesContainer + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker.AttributesContainer + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java b/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java index 26b86905a3..f522e6c16b 100644 --- a/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java @@ -27,15 +27,26 @@ import java.sql.Connection; import java.sql.Driver; import java.util.Collections; import java.util.Properties; +import java.util.Set; import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.connections.internal.DriverConnectionCreator; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport; import org.hibernate.engine.jdbc.internal.JdbcServicesImpl; import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.engine.jdbc.spi.TypeInfo; import org.hibernate.exception.JDBCConnectionException; +import org.hibernate.metamodel.spi.relational.Identifier; import org.hibernate.service.Service; +import org.hibernate.service.ServiceRegistry; import org.hibernate.service.internal.ProvidedService; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java index 763d5fcbc3..1bf6a7121d 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java @@ -32,13 +32,13 @@ import java.sql.SQLException; import java.util.Properties; import org.hibernate.Session; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.testing.env.TestingDatabaseInfo; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.SessionImpl; @@ -91,7 +91,7 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase { Dialect dialect = TestingDatabaseInfo.DIALECT; generator = new SequenceHiLoGenerator(); - generator.configure( StandardBasicTypes.LONG, properties, dialect ); + generator.configure( StandardBasicTypes.LONG, properties, dialect, new ClassLoaderServiceImpl() ); cfg = TestingDatabaseInfo.buildBaseConfiguration() .setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); diff --git a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java index 7239297ff7..7d06afbcda 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java @@ -32,13 +32,13 @@ import java.sql.SQLException; import java.util.Properties; import org.hibernate.Session; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.testing.env.TestingDatabaseInfo; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.SessionImpl; @@ -87,7 +87,7 @@ public class SequenceHiLoGeneratorTest extends BaseUnitTestCase { Dialect dialect = TestingDatabaseInfo.DIALECT; generator = new SequenceHiLoGenerator(); - generator.configure( StandardBasicTypes.LONG, properties, dialect ); + generator.configure( StandardBasicTypes.LONG, properties, dialect, new ClassLoaderServiceImpl() ); cfg = TestingDatabaseInfo.buildBaseConfiguration().setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); cfg.addAuxiliaryDatabaseObject( new SimpleAuxiliaryDatabaseObject( generator.sqlCreateStrings( dialect )[0], diff --git a/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java b/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java index b680f461f0..143ab995e4 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java @@ -25,6 +25,7 @@ package org.hibernate.id.enhanced; import org.junit.Test; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -274,7 +275,13 @@ public class OptimizerUnitTest extends BaseUnitTestCase { StandardOptimizerDescriptor descriptor, long initial, int increment) { - return OptimizerFactory.buildOptimizer( descriptor.getExternalName(), Long.class, increment, initial ); + return OptimizerFactory.buildOptimizer( + descriptor.getExternalName(), + Long.class, + increment, + initial, + new ClassLoaderServiceImpl() + ); } private static class SourceMock implements AccessCallback { diff --git a/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java b/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java index 1c2196b4a0..e77eb0770b 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java @@ -23,11 +23,14 @@ */ package org.hibernate.id.enhanced; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + import java.util.Properties; -import org.junit.Test; - import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; @@ -35,9 +38,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.StandardBasicTypes; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import org.junit.Test; /** * Tests that SequenceStyleGenerator configures itself as expected in various scenarios @@ -45,13 +46,14 @@ import static org.junit.Assert.fail; * @author Steve Ebersole */ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { + private final ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(); + private void assertClassAssignability(Class expected, Class actual) { if ( ! expected.isAssignableFrom( actual ) ) { fail( "Actual type [" + actual.getName() + "] is not assignable to expected type [" + expected.getName() + "]" ); } } - /** * Test all params defaulted with a dialect supporting sequences */ @@ -60,7 +62,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { Dialect dialect = new SequenceDialect(); Properties props = buildGeneratorPropertiesBase(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); @@ -92,7 +94,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { Dialect dialect = new TableDialect(); Properties props = buildGeneratorPropertiesBase(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); @@ -112,7 +114,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { // for dialects which do not support pooled sequences, we default to pooled+table Dialect dialect = new SequenceDialect(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -120,7 +122,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { // for dialects which do support pooled sequences, we default to pooled+sequence dialect = new PooledSequenceDialect(); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -137,7 +139,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" ); Dialect dialect = new TableDialect(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -152,7 +154,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { Properties props = buildGeneratorPropertiesBase(); props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -171,7 +173,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.NONE.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( 1, generator.getOptimizer().getIncrementSize() ); @@ -182,7 +184,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.HILO.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( HiLoOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( 20, generator.getOptimizer().getIncrementSize() ); @@ -193,7 +195,7 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.POOLED.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); // because the dialect reports to not support pooled seqyences, the expectation is that we will // use a table for the backing structure... assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); @@ -209,13 +211,13 @@ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { Properties props = buildGeneratorPropertiesBase(); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); props.setProperty( Environment.PREFER_POOLED_VALUES_LO, "true" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledLoOptimizer.class, generator.getOptimizer().getClass() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java b/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java index 01db4dae8b..1661187b20 100644 --- a/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java @@ -50,7 +50,7 @@ import org.hibernate.engine.jdbc.NClobImplementer; import org.hibernate.engine.jdbc.NonContextualLobCreator; import org.hibernate.engine.jdbc.WrappedBlob; import org.hibernate.engine.jdbc.WrappedClob; -import org.hibernate.engine.jdbc.internal.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -66,7 +66,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertTrue( lobCreator instanceof ContextualLobCreator ); testLobCreation( lobCreator ); @@ -79,7 +79,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); @@ -92,7 +92,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); @@ -107,7 +107,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas Properties props = new Properties(); props.setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" ); LobCreator lobCreator = - new LobCreatorBuilder( props, connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( props, connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java deleted file mode 100644 index 2598e426dd..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.sql.Types; -import java.util.Iterator; -import java.util.Set; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.domain.BasicType; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.type.LongType; -import org.hibernate.type.StringType; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * Basic tests of {@code hbm.xml} and annotation binding code - * - * @author Steve Ebersole - */ -public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { - - private StandardServiceRegistryImpl serviceRegistry; - - @Before - public void setUp() { - serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - } - - @After - public void tearDown() { - serviceRegistry.destroy(); - } - - protected ServiceRegistry basicServiceRegistry() { - return serviceRegistry; - } - - @Test - public void testSimpleEntityMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleEntityBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); - assertRoot( metadata, entityBinding ); - assertIdAndSimpleProperty( entityBinding ); - - assertNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); - } - - @Test - public void testSimpleVersionedEntityMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleVersionedEntityBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() ); - assertIdAndSimpleProperty( entityBinding ); - - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getAttribute() ); - } - - @Test - public void testEntityWithManyToOneMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleEntityBinding( sources ); - addSourcesForManyToOne( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - - EntityBinding simpleEntityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); - assertIdAndSimpleProperty( simpleEntityBinding ); - - Set referenceBindings = simpleEntityBinding.locateAttributeBinding( "id" ) - .getEntityReferencingAttributeBindings(); - assertEquals( "There should be only one reference binding", 1, referenceBindings.size() ); - - SingularAssociationAttributeBinding referenceBinding = referenceBindings.iterator().next(); - EntityBinding referencedEntityBinding = referenceBinding.getReferencedEntityBinding(); - // TODO - Is this assertion correct (HF)? - assertEquals( "Should be the same entity binding", referencedEntityBinding, simpleEntityBinding ); - - EntityBinding entityWithManyToOneBinding = metadata.getEntityBinding( ManyToOneEntity.class.getName() ); - Iterator it = entityWithManyToOneBinding.getEntityReferencingAttributeBindings() - .iterator(); - assertTrue( it.hasNext() ); - assertSame( entityWithManyToOneBinding.locateAttributeBinding( "simpleEntity" ), it.next() ); - assertFalse( it.hasNext() ); - } - - @Test - public void testSimpleEntityWithSimpleComponentMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForComponentBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntityWithSimpleComponent.class.getName() ); - assertRoot( metadata, entityBinding ); - assertIdAndSimpleProperty( entityBinding ); - - ComponentAttributeBinding componentAttributeBinding = (ComponentAttributeBinding) entityBinding.locateAttributeBinding( "simpleComponent" ); - assertNotNull( componentAttributeBinding ); - assertSame( componentAttributeBinding.getAttribute().getSingularAttributeType(), componentAttributeBinding.getAttributeContainer() ); - assertEquals( SimpleEntityWithSimpleComponent.class.getName() + ".simpleComponent", componentAttributeBinding.getPathBase() ); - assertSame( entityBinding, componentAttributeBinding.seekEntityBinding() ); - assertNotNull( componentAttributeBinding.getComponent() ); - } - - public abstract void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources); - - public abstract void addSourcesForSimpleEntityBinding(MetadataSources sources); - - public abstract void addSourcesForManyToOne(MetadataSources sources); - - public abstract void addSourcesForComponentBinding(MetadataSources sources); - - protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { - assertNotNull( entityBinding ); - assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); - assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - - AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); - assertNotNull( idAttributeBinding ); - assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - - assertTrue( idAttributeBinding.getAttribute().isSingular() ); - assertNotNull( idAttributeBinding.getAttribute() ); - SingularAttributeBinding singularIdAttributeBinding = (SingularAttributeBinding) idAttributeBinding; - assertFalse( singularIdAttributeBinding.isNullable() ); - SingularAttribute singularIdAttribute = ( SingularAttribute ) idAttributeBinding.getAttribute(); - BasicType basicIdAttributeType = ( BasicType ) singularIdAttribute.getSingularAttributeType(); - assertSame( Long.class, basicIdAttributeType.getClassReference() ); - - assertNotNull( singularIdAttributeBinding.getValue() ); - assertTrue( singularIdAttributeBinding.getValue() instanceof Column ); - Datatype idDataType = ( (Column) singularIdAttributeBinding.getValue() ).getDatatype(); - assertSame( Long.class, idDataType.getJavaType() ); - assertSame( Types.BIGINT, idDataType.getTypeCode() ); - assertSame( LongType.INSTANCE.getName(), idDataType.getTypeName() ); - - assertNotNull( entityBinding.locateAttributeBinding( "name" ) ); - assertNotNull( entityBinding.locateAttributeBinding( "name" ).getAttribute() ); - assertTrue( entityBinding.locateAttributeBinding( "name" ).getAttribute().isSingular() ); - - SingularAttributeBinding nameBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( "name" ); - assertTrue( nameBinding.isNullable() ); - assertSame( StringType.INSTANCE, nameBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - assertNotNull( nameBinding.getAttribute() ); - assertNotNull( nameBinding.getValue() ); - SingularAttribute singularNameAttribute = ( SingularAttribute ) nameBinding.getAttribute(); - BasicType basicNameAttributeType = ( BasicType ) singularNameAttribute.getSingularAttributeType(); - assertSame( String.class, basicNameAttributeType.getClassReference() ); - - assertNotNull( nameBinding.getValue() ); - SimpleValue nameValue = (SimpleValue) nameBinding.getValue(); - assertTrue( nameValue instanceof Column ); - Datatype nameDataType = nameValue.getDatatype(); - assertSame( String.class, nameDataType.getJavaType() ); - assertSame( Types.VARCHAR, nameDataType.getTypeCode() ); - assertSame( StringType.INSTANCE.getName(), nameDataType.getTypeName() ); - } - - protected void assertRoot(MetadataImplementor metadata, EntityBinding entityBinding) { - assertTrue( entityBinding.isRoot() ); - assertSame( entityBinding, metadata.getRootEntityBinding( entityBinding.getEntity().getName() ) ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml deleted file mode 100644 index 3eb4ca7633..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java deleted file mode 100644 index 95b316c2d1..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@GenericGenerator(name = "myGenerator", strategy = "sequence") -package org.hibernate.metamodel.binding; - -import org.hibernate.annotations.GenericGenerator; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java new file mode 100644 index 0000000000..64d0e949e9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java @@ -0,0 +1,227 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import java.util.Iterator; + +import org.junit.Test; + +import org.hibernate.EntityMode; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataBuilderImpl; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.source.annotations.AnnotationMetadataSourceProcessorImpl; +import org.hibernate.metamodel.internal.source.hbm.HbmMetadataSourceProcessorImpl; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.TableSource; +import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class AssertSourcesTest extends BaseUnitTestCase { + final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build() ; + + @Test + public void testUserEntitySources() { + MetadataSources hbm = new MetadataSources( serviceRegistry ); + hbm.addResource( getClass().getPackage().getName().replace( '.', '/' ) + "/User.hbm.xml" ); + MetadataSourceProcessor hbmProcessor = new HbmMetadataSourceProcessorImpl( buildMetadata( hbm ), hbm ); + testUserEntitySources( hbmProcessor ); + + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( User.class ); + MetadataSourceProcessor annProcessor = new AnnotationMetadataSourceProcessorImpl( + buildMetadata( ann ), + ann.buildJandexView() + ); + testUserEntitySources( annProcessor ); + } + + private MetadataImpl buildMetadata(MetadataSources sources) { + return new MetadataImpl( sources, new MetadataBuilderImpl.OptionsImpl( serviceRegistry ) ); + } + + private void testUserEntitySources(MetadataSourceProcessor processor) { + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchy hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + RootEntitySource entitySource = hierarchy.getRootEntitySource(); + assertFalse( entitySource.subclassEntitySources().iterator().hasNext() ); + + assertEquals( User.class.getName(), entitySource.getClassName() ); + assertEquals( User.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( User.class.getName() ), entitySource.getJpaEntityName() ); + + assertEquals( EntityMode.POJO, entitySource.getEntityMode() ); + assertNull( entitySource.getCaching() ); + assertNull( entitySource.getDiscriminatorSource() ); + assertNull( entitySource.getDiscriminatorMatchValue() ); + + assertTrue( entitySource.getJpaCallbackClasses() == null || entitySource.getJpaCallbackClasses().isEmpty() ); + + TableSpecificationSource primaryTableSpecificationSource = entitySource.getPrimaryTable(); + assertTrue( TableSource.class.isInstance( primaryTableSpecificationSource ) ); + TableSource primaryTable = (TableSource) primaryTableSpecificationSource; + // todo : should sources be responsible for figuring out logical names? + // these are the things that need to match in terms of lookup keys + assertNull( primaryTable.getExplicitCatalogName() ); + assertNull( primaryTable.getExplicitSchemaName() ); + assertNull( primaryTable.getExplicitTableName() ); + + assertFalse( entitySource.getSecondaryTables().iterator().hasNext() ); + assertTrue( + ArrayHelper.isEmpty( entitySource.getSynchronizedTableNames() ) + ); + + IdentifierSource identifierSource = entitySource.getIdentifierSource(); + assertNotNull( identifierSource ); + assertEquals( EntityIdentifierNature.SIMPLE, identifierSource.getNature() ); + SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; + SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource(); + assertEquals( "id", identifierAttributeSource.getName() ); + assertTrue( identifierAttributeSource.isSingular() ); + assertFalse( identifierAttributeSource.isVirtualAttribute() ); + assertFalse( identifierAttributeSource.isLazy() ); + assertEquals( SingularAttributeSource.Nature.BASIC, identifierAttributeSource.getNature() ); + assertEquals( PropertyGeneration.INSERT, identifierAttributeSource.getGeneration() ); +// assertNull( identifierAttributeSource.getPropertyAccessorName() ); + + // todo : here is an interesting question in terms of who is responsible for semantic interpretation + // really an attribute for identifier should never be included in updates + // and it should only be included in inserts only in certain cases + // and should never be nullable + // ^^ all because this is the PK. That is the semantic interpretation of those values based on that context. + // + // So do sources simply return explicit user values? Or do they consider such semantic analysis? + assertTrue( identifierAttributeSource.areValuesIncludedInInsertByDefault() ); + assertFalse( identifierAttributeSource.areValuesIncludedInUpdateByDefault() ); + assertFalse( identifierAttributeSource.areValuesNullableByDefault() ); + + // todo : return collections? or iterables? + // todo : empty collections? or null? + assertEquals( 0, identifierAttributeSource.relationalValueSources().size() ); +// RelationalValueSource relationalValueSource = identifierAttributeSource.relationalValueSources().get( 0 ); +// assertNull( relationalValueSource.getContainingTableName() ); +// assertEquals( RelationalValueSource.Nature.COLUMN, relationalValueSource.getNature() ); +// ColumnSource columnSource = (ColumnSource) relationalValueSource; +// assertNull( columnSource.getName() ); +// assertNull( columnSource.getReadFragment() ); +// assertNull( columnSource.getWriteFragment() ); +// assertNull( columnSource.getDefaultValue() ); +// assertNull( columnSource.getSqlType() ); +// assertNull( columnSource.getCheckCondition() ); +// assertNull( columnSource.getComment() ); +// assertNull( columnSource.getJdbcDataType() ); +// assertNull( columnSource.getSize() ); +// // todo : technically, pk has to be unique, but this another semantic case +// assertFalse( columnSource.isUnique() ); +// // todo : see comments above +// assertFalse( columnSource.isIncludedInInsert() ); +// assertFalse( columnSource.isIncludedInUpdate() ); +// assertFalse( columnSource.isNullable() ); + + assertEquals( 3, entitySource.attributeSources().size() ); + + + } + + @Test + public void testOrderEntitySources() { + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.OrderPk.class ); + MetadataSourceProcessor annProcessor = new AnnotationMetadataSourceProcessorImpl( + buildMetadata( ann ), + ann.buildJandexView() + ); + testOrderEntitySources( annProcessor ); + } + + private void testOrderEntitySources(MetadataSourceProcessor processor) { + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchy hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + RootEntitySource entitySource = hierarchy.getRootEntitySource(); + assertFalse( entitySource.subclassEntitySources().iterator().hasNext() ); + + assertEquals( Order.class.getName(), entitySource.getClassName() ); + assertEquals( Order.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( Order.class.getName() ), entitySource.getJpaEntityName() ); + } + + @Test + public void testOrderNonAggregatedEntitySources() { + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.OrderPk.class ); + MetadataSourceProcessor annProcessor = new AnnotationMetadataSourceProcessorImpl( + buildMetadata( ann ), + ann.buildJandexView() + ); + testOrderNonAggregatedEntitySources( annProcessor ); + } + + private void testOrderNonAggregatedEntitySources(MetadataSourceProcessor processor) { + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchy hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + RootEntitySource entitySource = hierarchy.getRootEntitySource(); + assertFalse( entitySource.subclassEntitySources().iterator().hasNext() ); + + assertEquals( Order.class.getName(), entitySource.getClassName() ); + assertEquals( Order.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( Order.class.getName() ), entitySource.getJpaEntityName() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java index f06395ca3d..167f0ea7f7 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java similarity index 87% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java index 828719c709..4d34bfc8c0 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java @@ -21,24 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; +package org.hibernate.metamodel.internal.source; import java.util.Iterator; -import org.hibernate.HibernateException; +import org.junit.Test; + import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.Metadata; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.binding.FetchProfile; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.SessionFactoryBuilderImpl; +import org.hibernate.metamodel.spi.binding.FetchProfile; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; /** * @author Hardy Ferentschik @@ -59,17 +61,10 @@ public class MetadataImplTest extends BaseUnitTestCase { sources.buildMetadata(); } - @Test(expected = HibernateException.class) - public void testAddingNonExistingPackageName() { - MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "not.a.package" ); - sources.buildMetadata(); - } - @Test public void testAddingPackageName() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "org.hibernate.metamodel.source.internal" ); + sources.addPackage( "org.hibernate.metamodel.internal.source" ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); assertFetchProfile( metadata ); @@ -78,7 +73,7 @@ public class MetadataImplTest extends BaseUnitTestCase { @Test public void testAddingPackageNameWithTrailingDot() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "org.hibernate.metamodel.source.internal." ); + sources.addPackage( "org.hibernate.metamodel.internal.source." ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); assertFetchProfile( metadata ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java new file mode 100644 index 0000000000..ed2225fc2c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * Defines an entity with an embedded id. + * + * @author Steve Ebersole + */ +@Entity +@Table( name = "T_ORDER" ) +public class Order { + private OrderPk id; + + @EmbeddedId + public OrderPk getId() { + return id; + } + + @Embeddable + public static class OrderPk { + private String customerIdentifier; + private int orderNumber; + + OrderPk() { + } + + public OrderPk(String customerIdentifier, int orderNumber) { + this.customerIdentifier = customerIdentifier; + this.orderNumber = orderNumber; + } + + public String getCustomerIdentifier() { + return customerIdentifier; + } + + private void setCustomerIdentifier(String customerIdentifier) { + this.customerIdentifier = customerIdentifier; + } + + public int getOrderNumber() { + return orderNumber; + } + + private void setOrderNumber(int orderNumber) { + this.orderNumber = orderNumber; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java new file mode 100644 index 0000000000..9210c5b305 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +/** + * @author Steve Ebersole + */ +@Entity +@IdClass( Order.OrderPk.class ) +public class OrderWithNonEmbeddedId { + private String customerIdentifier; + private int orderNumber; + + public OrderWithNonEmbeddedId() { + } + + public OrderWithNonEmbeddedId(String customerIdentifier, int orderNumber) { + this.customerIdentifier = customerIdentifier; + this.orderNumber = orderNumber; + } + + @Id + public String getCustomerIdentifier() { + return customerIdentifier; + } + + public void setCustomerIdentifier(String customerIdentifier) { + this.customerIdentifier = customerIdentifier; + } + + @Id + public int getOrderNumber() { + return orderNumber; + } + + public void setOrderNumber(int orderNumber) { + this.orderNumber = orderNumber; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java index 43e87b6fb5..da88c0b386 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; import java.io.Serializable; import java.util.Iterator; @@ -38,8 +38,9 @@ import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.SessionFactoryBuilderImpl; import org.hibernate.proxy.EntityNotFoundDelegate; - import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.Type; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java index c6f1c5c763..2c9b9c5f95 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java new file mode 100644 index 0000000000..26fa3aab63 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NaturalId; + +/** + * @author Steve Ebersole + */ +@Entity +public class User { + private Long id; + private Name name; + private String userName; + private Date lastLogin; + private int version; + + @Id + @GeneratedValue( generator = "increment" ) + @GenericGenerator( name = "increment", strategy = "increment" ) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + + @NaturalId + @Column( name = "UNAME" ) + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Temporal( TemporalType.TIMESTAMP ) + public Date getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Date lastLogin) { + this.lastLogin = lastLogin; + } + + @Version + @Column( name = "LAST_UPDATED" ) + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + @Embeddable + public static class Name { + private String firstName; + private String middleName; + private String lastName; + + public Name() { + } + + public Name(String firstName, String middleName, String lastName) { + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + } + + @Column( name = "FNAME" ) + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @Column( name="LNAME" ) + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Column( name = "MNAME" ) + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java similarity index 72% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java index bfbe32b9f3..981f4dc3ea 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java @@ -21,17 +21,21 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Access; import javax.persistence.AccessType; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Id; import org.junit.Test; import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; @@ -69,10 +73,13 @@ public class AccessBindingTest extends BaseAnnotationBindingTestCase { @Resources(annotatedClasses = { PropertyAccess.class }) public void testDefaultPropertyAccess() { EntityBinding binding = getEntityBinding( PropertyAccess.class ); - assertEquals( "Wrong access type", "property", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "id" ).getPropertyAccessorName() + ); } - @Entity class NoAccess { private int id; @@ -113,6 +120,18 @@ public class AccessBindingTest extends BaseAnnotationBindingTestCase { ); } + @Test + @Resources(annotatedClasses = { MixedAccess.class }) + public void test() { + EntityBinding binding = getEntityBinding( MixedAccess.class ); + assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "name" ).getPropertyAccessorName() + ); + } + @Entity class Base { @Id @@ -148,6 +167,32 @@ public class AccessBindingTest extends BaseAnnotationBindingTestCase { ); } + + @Entity + class EntityWithEmbeddedId { + EmbeddableId id; + + @EmbeddedId + public EmbeddableId getId() { + return id; + } + } + + @Embeddable + public class EmbeddableId { + String ssn; + } + + @Test + @Resources(annotatedClasses = { EntityWithEmbeddedId.class, EmbeddableId.class }) + public void testEmbeddedIdWithPropertyAccess() { + EntityBinding binding = getEntityBinding( EntityWithEmbeddedId.class ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "id" ).getPropertyAccessorName() + ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java index b94774e9be..77aae2e309 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -29,7 +29,9 @@ import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.BatchSize; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java index 4b6bf54199..c489373d55 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Cacheable; import javax.persistence.Entity; @@ -33,8 +33,10 @@ import org.junit.Test; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java index 935fa511b2..5129bfc5b3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -34,8 +34,10 @@ import org.hibernate.annotations.SQLDeleteAll; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java new file mode 100644 index 0000000000..a9aaff88f7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java @@ -0,0 +1,241 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.List; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; + +import org.junit.Test; + +import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.metamodel.spi.binding.BagBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +/** + * Tests for different types of @ElementCollection mappings. + * + * @author Hardy Ferentschik + */ + +public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase { + @Entity + class TestEntity { + @Id + private int id; + + @ElementCollection + @JoinTable + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + public void testElementCollectionWithJoinTableThrowsException() { + try { + sources.addAnnotatedClass( TestEntity.class ); + sources.buildMetadata(); + fail( "Invalid use of @JoinTable with @ElementCollection" ); + } + catch ( MappingException e ) { + assertEquals( "Unexpected error origin", TestEntity.class.getName(), e.getOrigin().getName() ); + assertEquals( "Unexpected type", SourceType.ANNOTATION, e.getOrigin().getType() ); + assertTrue( "Wrong error message", e.getMessage().startsWith( "HHH000460" ) ); + } + } + + @Entity + class TestEntity2 { + @Id + private int id; + + @ElementCollection + @JoinTable + @CollectionTable + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + public void testCollectionTableAndJoinTableThrowsException() { + try { + sources.addAnnotatedClass( TestEntity2.class ); + sources.buildMetadata(); + fail( "Invalid use of @JoinTable AND @CollectionTable" ); + } + catch ( MappingException e ) { + assertEquals( "Unexpected error origin", TestEntity2.class.getName(), e.getOrigin().getName() ); + assertEquals( "Unexpected type", SourceType.ANNOTATION, e.getOrigin().getType() ); + assertTrue( "Wrong error message", e.getMessage().startsWith( "HHH000458" ) ); + } + } + + @Entity + class TestEntity3 { + @Id + private int id; + + @ElementCollection + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity3.class) + public void testDefaultJoinTableName() { + EntityBinding entityBinding = getEntityBinding( TestEntity3.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertEquals( + "Wrong default collection table name", + "ElementCollectionBindingTest$TestEntity3_strings", + tableSpec.getLogicalName().getText() + ); + } + + @Entity + class TestEntity4 { + @Id + private int id; + + @ElementCollection + @CollectionTable(name = "STRING_COLLECTION") + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity4.class) + public void testExplicitJoinTableName() { + EntityBinding entityBinding = getEntityBinding( TestEntity4.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertEquals( + "Wrong default collection table name", + "STRING_COLLECTION", + tableSpec.getLogicalName().getText() + ); + } + + + @Entity + class TestEntity5 { + @Id + private int id; + + @ElementCollection + @CollectionTable(name = "STRING_COLLECTION", joinColumns = @JoinColumn(name = "FOO")) + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity5.class) + public void testJoinColumnAsPartOfCollectionTable() { + EntityBinding entityBinding = getEntityBinding( TestEntity5.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + Column column = tableSpec.locateColumn( "FOO" ); + assertNotNull( "The join column should be named FOO", column ); + } + + @Entity + class TestEntity6 { + @Id + private int id; + + @ElementCollection + @JoinColumn(name = "FOO") + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity6.class) + public void testElementCollectionWithJoinColumn() { + EntityBinding entityBinding = getEntityBinding( TestEntity6.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + Column column = tableSpec.locateColumn( "FOO" ); + assertNotNull( "The join column should be named FOO", column ); + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java similarity index 67% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java index 6a0099d3c0..45654dc375 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; @@ -35,9 +35,11 @@ import org.junit.Test; import org.hibernate.annotations.Parent; import org.hibernate.annotations.Target; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.ComponentAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -72,21 +74,20 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String componentName = "phone"; assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( componentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding compositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( componentName ); - // todo - is this really correct? Does the path start w/ the class name assertEquals( "Wrong path", - "org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.phone", - componentBinding.getPathBase() + "phone", + compositeBinding.getPathBase() ); - assertNotNull( componentBinding.locateAttributeBinding( "countryCode" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "areaCode" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "number" ) ); + assertNotNull( compositeBinding.locateAttributeBinding( "countryCode" ) ); + assertNotNull( compositeBinding.locateAttributeBinding( "areaCode" ) ); + assertNotNull( compositeBinding.locateAttributeBinding( "number" ) ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -113,15 +114,17 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String componentName = "embedded"; assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( componentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding compositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( componentName ); - assertNotNull( componentBinding.locateAttributeBinding( "name" ) ); - BasicAttributeBinding nameAttribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "name" ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); - assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() ); + assertNotNull( compositeBinding.locateAttributeBinding( "name" ) ); + BasicAttributeBinding nameAttribute = (BasicAttributeBinding) compositeBinding.locateAttributeBinding( "name" ); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getText() ); assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); } @@ -166,39 +169,42 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String addressComponentName = "address"; assertNotNull( binding.locateAttributeBinding( addressComponentName ) ); - assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding attributeComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding attributeCompositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( addressComponentName ); - assertNotNull( attributeComponentBinding.locateAttributeBinding( "street" ) ); - assertNotNull( attributeComponentBinding.locateAttributeBinding( "city" ) ); - assertNotNull( attributeComponentBinding.locateAttributeBinding( "state" ) ); + assertNotNull( attributeCompositeBinding.locateAttributeBinding( "street" ) ); + assertNotNull( attributeCompositeBinding.locateAttributeBinding( "city" ) ); + assertNotNull( attributeCompositeBinding.locateAttributeBinding( "state" ) ); - BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeComponentBinding.locateAttributeBinding( + BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeCompositeBinding.locateAttributeBinding( "state" ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) stateAttribute.getValue(); + assertEquals( 1, stateAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) stateAttribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_STATE", - column.getColumnName().getName() + column.getColumnName().getText() ); final String zipComponentName = "zipcode"; - assertNotNull( attributeComponentBinding.locateAttributeBinding( zipComponentName ) ); - assertTrue( attributeComponentBinding.locateAttributeBinding( zipComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding zipComponentBinding = (ComponentAttributeBinding) attributeComponentBinding.locateAttributeBinding( + assertNotNull( attributeCompositeBinding.locateAttributeBinding( zipComponentName ) ); + assertTrue( attributeCompositeBinding.locateAttributeBinding( zipComponentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding zipCompositeBinding = (CompositeAttributeBinding) attributeCompositeBinding.locateAttributeBinding( zipComponentName ); - BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipComponentBinding.locateAttributeBinding( "zip" ); - column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); + BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipCompositeBinding.locateAttributeBinding( "zip" ); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_ZIP", - column.getColumnName().getName() + column.getColumnName().getText() ); } @@ -257,32 +263,35 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String aComponentName = "a"; assertNotNull( binding.locateAttributeBinding( aComponentName ) ); - assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding aComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding aCompositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( aComponentName ); final String bComponentName = "b"; - assertNotNull( aComponentBinding.locateAttributeBinding( bComponentName ) ); - assertTrue( aComponentBinding.locateAttributeBinding( bComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding bComponentBinding = (ComponentAttributeBinding) aComponentBinding.locateAttributeBinding( + assertNotNull( aCompositeBinding.locateAttributeBinding( bComponentName ) ); + assertTrue( aCompositeBinding.locateAttributeBinding( bComponentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding bCompositeBinding = (CompositeAttributeBinding) aCompositeBinding.locateAttributeBinding( bComponentName ); - BasicAttributeBinding attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "foo" ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); + BasicAttributeBinding attribute = (BasicAttributeBinding) bCompositeBinding.locateAttributeBinding( "foo" ); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "BAR", - column.getColumnName().getName() + column.getColumnName().getText() ); - attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "fubar" ); - column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); + attribute = (BasicAttributeBinding) bCompositeBinding.locateAttributeBinding( "fubar" ); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "C_WINS", - column.getColumnName().getName() + column.getColumnName().getText() ); } @@ -293,6 +302,15 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { private String test; @Parent private MainEntity parent; + + // require getter/setter for parent because of HHH-1614 + public MainEntity getParent() { + return parent; + } + + public void setParent(MainEntity parent) { + this.parent = parent; + } } @Entity @@ -311,25 +329,33 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String componentName = "embedded"; assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( componentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding compositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( componentName ); - assertEquals( "Wrong parent reference name", "parent", componentBinding.getParentReference().getName() ); + assertEquals( "Wrong parent reference name", "parent", compositeBinding.getParentReference().getName() ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public interface Car { int getHorsePower(); + void setHorsePower(int horsePower); } @Embeddable public class CarImpl implements Car { + private int horsePower; + @Override public int getHorsePower() { - return 0; + return horsePower; + } + + @Override + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; } } @@ -357,12 +383,14 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { final String componentName = "car"; assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( + assertTrue( binding.locateAttributeBinding( componentName ) instanceof CompositeAttributeBinding ); + CompositeAttributeBinding compositeBinding = (CompositeAttributeBinding) binding.locateAttributeBinding( componentName ); - BasicAttributeBinding attribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "horsePower" ); + BasicAttributeBinding attribute = (BasicAttributeBinding) compositeBinding.locateAttributeBinding( + "horsePower" + ); assertTrue( attribute.getAttribute().isTypeResolved() ); assertEquals( "Wrong resolved type", diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java index 7ec16508b5..af3370ea30 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Access; import javax.persistence.AccessType; @@ -32,39 +32,42 @@ import javax.persistence.Entity; import org.junit.Test; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityIdentifier; -import org.hibernate.testing.FailureExpected; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; /** * @author Strong Liu */ -@FailureExpected(jiraKey = "HHH-6447", message = "Work in progress") public class EmbeddedIdTest extends BaseAnnotationBindingTestCase { - @Test -// @Resources(annotatedClasses = { User.class, Address.class }) - public void testEmbeddable() { - EntityBinding binding = getEntityBinding( User.class ); - EntityIdentifier identifier = binding.getHierarchyDetails().getEntityIdentifier(); - assertTrue( identifier.isEmbedded() ); - } + @Test + @Resources(annotatedClasses = { User.class, Address.class }) + public void testEmbeddable() { + EntityBinding binding = getEntityBinding( User.class ); + EntityIdentifier identifier = binding.getHierarchyDetails().getEntityIdentifier(); + assertTrue( !identifier.isNonAggregatedComposite() ); + assertEquals( identifier.getNature(), EntityIdentifierNature.AGGREGATED_COMPOSITE ); + } - @Entity - @Access( AccessType.FIELD ) - class User { - private String name; - @EmbeddedId - private Address address; - } + @Entity + @Access(AccessType.FIELD) + class User { + private String name; + @EmbeddedId + private Address address; + } - @Embeddable - class Address { - String street; - String city; - String postCode; - } + @Embeddable + class Address { + String street; + String city; + String postCode; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java index 9049e08c60..9805b9a0d2 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.sql.Types; import java.util.Date; @@ -35,9 +35,12 @@ import javax.persistence.TemporalType; import org.junit.Test; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.hibernate.usertype.DynamicParameterizedType; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -80,7 +83,7 @@ public class EnumeratedBindingTest extends BaseAnnotationBindingTestCase { assertFalse( descriptor.getTypeParameters().isEmpty() ); assertEquals( CustomerType.class.getName(), - descriptor.getTypeParameters().get( org.hibernate.type.EnumType.ENUM ) + descriptor.getTypeParameters().get( DynamicParameterizedType.RETURNED_CLASS ) ); assertEquals( String.valueOf( Types.INTEGER ), @@ -96,7 +99,7 @@ public class EnumeratedBindingTest extends BaseAnnotationBindingTestCase { assertFalse( descriptor.getTypeParameters().isEmpty() ); assertEquals( OrderType.class.getName(), - descriptor.getTypeParameters().get( org.hibernate.type.EnumType.ENUM ) + descriptor.getTypeParameters().get( DynamicParameterizedType.RETURNED_CLASS ) ); assertEquals( String.valueOf( Types.VARCHAR ), diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java new file mode 100644 index 0000000000..579a4ac3ff --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import junit.framework.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +/** + * @author Strong Liu + */ +public class GenericTest extends BaseAnnotationBindingTestCase { + @Entity + @Inheritance + public abstract class Event { + private long id; + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } + + @Entity + public class LoginEvent extends Event { + + } + + @Entity + @Inheritance + public abstract class Notification { + private long id; + private X event; + + @ManyToOne(optional = false, targetEntity = Event.class) + @JoinColumn + public X getEvent() { + return event; + } + + public void setEvent(X event) { + this.event = event; + } + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } + + @Entity + public class LoginNotification extends Notification { + + } + + @Test + @Ignore("not finished yet") + @Resources(annotatedClasses = { LoginNotification.class, Notification.class, LoginEvent.class, Event.class }) + public void testGenericProperty() { + EntityBinding entityBinding = getEntityBinding( LoginNotification.class ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "event" ); +// Assert.assertNotNull( attributeBinding ); + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java index c5f0afbbf0..77d5a9b6be 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -22,19 +22,15 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import org.junit.Test; + import org.hibernate.annotations.GenericGenerator; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.dialect.H2Dialect; @@ -45,11 +41,18 @@ import org.hibernate.id.MultipleHiLoPerTableGenerator; import org.hibernate.id.SequenceHiLoGenerator; import org.hibernate.id.UUIDHexGenerator; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityIdentifier; -import org.hibernate.metamodel.source.MappingException; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.source.MappingException; import org.hibernate.testing.RequiresDialect; -import org.junit.Test; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; /** * @author Hardy Ferentschik @@ -70,7 +73,7 @@ public class IdentifierGeneratorTest extends BaseAnnotationBindingTestCase { IdentifierGenerator generator =identifier.getIdentifierGenerator(); assertNotNull( generator ); assertEquals( "Wrong generator", Assigned.class, generator.getClass() ); - assertFalse( identifier.isEmbedded() ); + assertFalse( identifier.isNonAggregatedComposite() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java similarity index 85% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java index 6ba182dd8d..bbe7fa17bd 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.HashSet; import java.util.Iterator; @@ -37,11 +37,14 @@ import org.junit.Test; import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.DiscriminatorOptions; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -122,30 +125,33 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertFalse( noInheritanceEntityBinding.isPolymorphic() ); assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() ); assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertEquals( 0, noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().length ); + assertEquals( 0, noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().length ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); } assertEquals( 1, directAttributeBindings.size() ); assertSame( - noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), + noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), directAttributeBindings.iterator().next() ); assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() ); Iterator iterator = noInheritanceEntityBinding.attributeBindings().iterator(); assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); - assertFalse( iterator.hasNext() ); - iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator(); - assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); - assertFalse( iterator.hasNext() ); - iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator(); - assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() ); assertFalse( iterator.hasNext() ); + + AttributeBinding[] attributeBindings = noInheritanceEntityBinding.getAttributeBindingClosure(); + assertTrue( attributeBindings.length > 0 ); + int index =0; + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] ); + assertFalse( index < attributeBindings.length ); + attributeBindings = noInheritanceEntityBinding.getEntitiesAttributeBindingClosure(); + index = 0; + assertTrue( attributeBindings.length > 0 ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] ); + assertFalse( index < attributeBindings.length ); } @Test @@ -156,14 +162,14 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { OtherSubclassOfSingleTableInheritance.class, SubclassOfSubclassOfSingleTableInheritance.class }) - public void testRootPolymporhism() { + public void testRootPolymporphism() { EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class ); EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class ); EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class ); EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class ); assertTrue( rootEntityBinding.isRoot() ); - assertNull( rootEntityBinding.getDiscriminatorMatchValue() ); + assertEquals( StringHelper.unqualify( rootEntityBinding.getEntity().getName() ), rootEntityBinding.getDiscriminatorMatchValue() ); assertNull( rootEntityBinding.getSuperEntityBinding() ); assertSame( rootEntityBinding, getRootEntityBinding( RootOfSingleTableInheritance.class ) ); assertTrue( rootEntityBinding.isPolymorphic() ); @@ -196,7 +202,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertEquals( 1, attributeBindingClosure.size() ); assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : rootEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : rootEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 4, subAttributeBindings.size() ); @@ -223,23 +229,24 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { Iterator directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator(); boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next(); assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure().iterator(); - assertTrue( subEntityBindingIterator.hasNext() ); + EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure(); + assertTrue( subEntityBindingIterator.length > 0 ); + int i = 0; if ( isSubclassEntityBindingFirst ) { - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); - assertTrue( subEntityBindingIterator.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertTrue( subEntityBindingIterator.hasNext() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); + assertTrue( i directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator(); boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next(); assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure().iterator(); - assertTrue( subEntityBindingIterator.hasNext() ); + EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure(); + int i =0; + assertTrue( subEntityBindingIterator.length > 0 ); if ( isSubclassEntityBindingFirst ) { - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] ); } else { - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); } - assertFalse( subEntityBindingIterator.hasNext() ); + assertFalse( i < subEntityBindingIterator.length ); } @Test @@ -295,8 +303,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( otherSubclassEntityBinding.isPolymorphic() ); assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() ); assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 ); + assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -312,7 +320,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 2, subAttributeBindings.size() ); @@ -341,14 +349,16 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( subclassEntityBinding.isPolymorphic() ); assertTrue( subclassEntityBinding.hasSubEntityBindings() ); assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator(); - assertTrue( itSubEntityBindings.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() ); - assertFalse( itSubEntityBindings.hasNext() ); - itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator(); - assertTrue( itSubEntityBindings.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() ); - assertFalse( itSubEntityBindings.hasNext() ); + EntityBinding[] itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure(); + int i = 0; + assertTrue( i < itSubEntityBindings.length ); + assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] ); + assertFalse( i < itSubEntityBindings.length ); + itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure(); + i = 0; + assertTrue( i < itSubEntityBindings.length ); + assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] ); + assertFalse( i < itSubEntityBindings.length ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -364,7 +374,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 3, subAttributeBindings.size() ); @@ -394,8 +404,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() ); assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() ); assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 ); + assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -412,7 +422,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) ); assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 3, subAttributeBindings.size() ); @@ -446,23 +456,23 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { assertEquals( "base", rootEntityBinding.getDiscriminatorMatchValue() ); } - @Test - @Resources(annotatedClasses = { Fruit.class, Apple.class }) - public void testDiscriminatorFormula() { - EntityBinding rootEntityBinding = getEntityBinding( Fruit.class ); - assertTrue( rootEntityBinding.isRoot() ); - EntityBinding entityBinding = getEntityBinding( Apple.class ); - assertFalse( entityBinding.isRoot() ); + @Test + @Resources(annotatedClasses = { Fruit.class, Apple.class }) + public void testDiscriminatorFormula() { + EntityBinding rootEntityBinding = getEntityBinding( Fruit.class ); + assertTrue( rootEntityBinding.isRoot() ); + EntityBinding entityBinding = getEntityBinding( Apple.class ); + assertFalse( entityBinding.isRoot() ); EntityDiscriminator discriminator = rootEntityBinding.getHierarchyDetails().getEntityDiscriminator(); - SimpleValue simpleValue = discriminator.getBoundValue(); - assertTrue( simpleValue instanceof DerivedValue); - DerivedValue derivedValue = (DerivedValue)simpleValue; - assertEquals( "case when zik_type is null then 0 else zik_type end", derivedValue.getExpression() ); + Value simpleValue = discriminator.getRelationalValue(); + assertTrue( simpleValue instanceof DerivedValue); + DerivedValue derivedValue = (DerivedValue)simpleValue; + assertEquals( "case when zik_type is null then 0 else zik_type end", derivedValue.getExpression() ); assertTrue( "Wrong default value", discriminator.isForced() ); assertFalse( "Wrong default value", discriminator.isInserted() ); - } + } - @Entity + @Entity class SingleEntity { @Id @GeneratedValue @@ -507,19 +517,19 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { class Jump extends Base { } - @Entity - @DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER) - @DiscriminatorFormula("case when zik_type is null then 0 else zik_type end") - @DiscriminatorOptions(force = true, insert = false) - class Fruit { - @Id - private int id; - } + @Entity + @DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER) + @DiscriminatorFormula("case when zik_type is null then 0 else zik_type end") + @DiscriminatorOptions(force = true, insert = false) + class Fruit { + @Id + private int id; + } - @Entity - class Apple extends Fruit { + @Entity + class Apple extends Fruit { - } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java index 6069d63048..b618da32f6 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.io.Serializable; import java.sql.Blob; @@ -33,9 +33,11 @@ import javax.persistence.Lob; import org.junit.Test; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import org.hibernate.type.BlobType; import org.hibernate.type.CharacterArrayClobType; import org.hibernate.type.ClobType; @@ -45,6 +47,7 @@ import org.hibernate.type.PrimitiveCharacterArrayClobType; import org.hibernate.type.SerializableToBlobType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.WrappedMaterializedBlobType; +import org.hibernate.usertype.DynamicParameterizedType; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java index a35651e39f..bfe82e53b5 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; @@ -31,15 +31,15 @@ import javax.persistence.MappedSuperclass; import org.junit.Test; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.domain.NonEntity; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.testing.FailureExpected; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertNull; /** * Tests for {@link javax.persistence.MappedSuperclass} {@link javax.persistence.AttributeOverrides} @@ -47,37 +47,51 @@ import static junit.framework.Assert.assertTrue; * * @author Hardy Ferentschik */ -@FailureExpected(jiraKey = "HHH-6447", message = "Work in progress") public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { @Test -// @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) + @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) public void testSimpleAttributeOverrideInMappedSuperclass() { EntityBinding binding = getEntityBinding( MyEntity.class ); - SingularAttributeBinding nameBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "name" ); + SingularAttributeBinding nameBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "name" ); assertNotNull( "the name attribute should be bound to MyEntity", nameBinding ); - Column column = (Column) nameBinding.getValue(); + assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) nameBinding.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Wrong column name", "MY_NAME", column.getColumnName().toString() ); } @Test -// @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) + @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) public void testLastAttributeOverrideWins() { EntityBinding binding = getEntityBinding( MyEntity.class ); - SingularAttributeBinding fooBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "foo" ); + SingularAttributeBinding fooBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "foo" ); assertNotNull( "the foo attribute should be bound to MyEntity", fooBinding ); - Column column = (Column) fooBinding.getValue(); + assertEquals( 1, fooBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) fooBinding.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Wrong column name", "MY_FOO", column.getColumnName().toString() ); } @Test -// @Resources(annotatedClasses = { SubclassOfNoEntity.class, NoEntity.class }) + @Resources(annotatedClasses = { SubclassOfNoEntity.class, NoEntity.class }) public void testNonEntityBaseClass() { EntityBinding binding = getEntityBinding( SubclassOfNoEntity.class ); assertEquals( "Wrong entity name", SubclassOfNoEntity.class.getName(), binding.getEntity().getName() ); - assertEquals( "Wrong entity name", NoEntity.class.getName(), binding.getEntity().getSuperType().getName() ); - assertTrue( binding.getEntity().getSuperType() instanceof NonEntity ); + assertNull( "Supertype should not be mapped", binding.getEntity().getSuperType() ); + } + + @Test + @Resources(annotatedClasses = { Foo.class, SuperFoo.class }) + public void testOverrideOfIdAttribute() { + EntityBinding binding = getEntityBinding( Foo.class ); + + SingularAttributeBinding idAttributeBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "id" ); + assertNotNull( "the id attribute should be bound to Foo", idAttributeBinding ); + + assertEquals( 1, idAttributeBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) idAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Wrong column name", "FOO_ID", column.getColumnName().toString() ); + assertEquals( "Wrong column name", 1, column.getSize().getLength() ); } @MappedSuperclass @@ -94,7 +108,7 @@ public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { } @Entity - @AttributeOverrides( { + @AttributeOverrides({ @AttributeOverride(name = "name", column = @javax.persistence.Column(name = "MY_NAME")), @AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "MY_FOO")) }) @@ -113,6 +127,18 @@ public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { @Id private int id; } + + + @MappedSuperclass + class SuperFoo { + @Id + private int id; + } + + @Entity + @AttributeOverride(name = "id", column = @javax.persistence.Column(name = "FOO_ID", length = 1)) + class Foo extends SuperFoo { + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java similarity index 83% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java index 81b0a3b8b5..662b19f759 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java @@ -22,8 +22,9 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; +import java.util.List; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Id; @@ -34,7 +35,8 @@ import org.junit.Test; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MappingException; +import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -59,17 +61,16 @@ public class MapsIdTest extends BaseAnnotationBindingTestCase { @Entity public class Dependent { - @Id // should be @EmbeddedId, but embedded id are not working atm - DependentId id; + @Id + DependentId id; @MapsId("empid") @OneToMany - Employee emp; // maps the empid attribute of embedded id @ManyToOne Employee emp; + List emp; // maps the empid attribute of embedded id @ManyToOne Employee emp; } @Test - @Resources(annotatedClasses = DependentId.class) public void testMapsIsOnOneToManyThrowsException() { try { sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); @@ -81,12 +82,13 @@ public class MapsIdTest extends BaseAnnotationBindingTestCase { } catch ( MappingException e ) { assertTrue( - e.getMessage() - .startsWith( "@MapsId can only be specified on a many-to-one or one-to-one associations" ) + e.getMessage().startsWith( + "@MapsId can only be specified on a many-to-one or one-to-one associations" + ) ); assertEquals( "Wrong error origin", - "org.hibernate.metamodel.source.annotations.entity.MapsIdTest$Dependent", + MapsIdTest.Dependent.class.getName(), e.getOrigin().getName() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java new file mode 100644 index 0000000000..475a3e75fd --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java @@ -0,0 +1,192 @@ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.List; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.junit.Test; + +import org.hibernate.annotations.NaturalId; +import org.hibernate.annotations.NaturalIdCache; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class NaturalIdBindingTests extends BaseAnnotationBindingTestCase { + @Entity + public class SimpleEntityWithNaturalId { + @Id + long id; + @NaturalId + String name; + @NaturalId(mutable = true) + int age; + } + + @Test + @Resources(annotatedClasses = NaturalIdBindingTests.SimpleEntityWithNaturalId.class) + public void testSimpleNaturalIdAttributeBinding() { + EntityBinding entityBinding = getEntityBinding( SimpleEntityWithNaturalId.class ); + assertNull( entityBinding.getHierarchyDetails().getNaturalIdCaching() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "name" + ); + assertEquals( + SingularAttributeBinding.NaturalIdMutability.IMMUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + + assertFalse( + "immutable (by default) natural id should not be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + Column column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + + //------------------------------------------------------------------------------------------------------- + attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "age" + ); + assertEquals( + SingularAttributeBinding.NaturalIdMutability.MUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + + relationalValueBinding = relationalValueBindings.get( 0 ); + + assertTrue( + "mutable natural id should be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + // ----------------------------------------------------------------------------------------------------- + + assertTrue( SchemaUtil.hasUniqueKeys( entityBinding.getPrimaryTable(), "age", "name" ) ); + } + + @Entity + public class EntityWithEmbedded { + @Id + long id; + @NaturalId + @Embedded + Component component; + + } + + @Embeddable + public class Component { + String name; + String age; + } + + @Test + @Resources(annotatedClasses = { EntityWithEmbedded.class, Component.class }) + public void testEmbeddedNaturalIdAttributeBinding() { + EntityBinding entityBinding = getEntityBinding( EntityWithEmbedded.class ); + assertNull( entityBinding.getHierarchyDetails().getNaturalIdCaching() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "component" + ); + assertEquals( + SingularAttributeBinding.NaturalIdMutability.IMMUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + for ( RelationalValueBinding valueBinding : relationalValueBindings ) { + assertFalse( + "immutable (by default) natural id should not be included in the update list", + valueBinding.isIncludeInUpdate() + ); + Column column = Column.class.cast( valueBinding.getValue() ); +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + } + + assertTrue( SchemaUtil.hasUniqueKeys( entityBinding.getPrimaryTable(), "age", "name" ) ); + } + + @Entity + @NaturalIdCache + public class EntityWithAssociation { + @Id + long id; + + @NaturalId + String name; + + @ManyToOne + @NaturalId + SimpleEntity simpleEntity; + } + + @Entity + public class SimpleEntity { + @Id + long id; + String simpleName; + } + + @Test + @Resources(annotatedClasses = { + EntityWithAssociation.class, + SimpleEntity.class + }) + public void testAssociationNaturalIdBinding() { + EntityBinding entityBinding = getEntityBinding( EntityWithAssociation.class ); + assertNotNull( entityBinding.getHierarchyDetails().getNaturalIdCaching() ); + assertNotNull( entityBinding.getHierarchyDetails().getNaturalIdCaching().getRegion() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding)entityBinding.locateAttributeBinding( "simpleEntity" ); + assertEquals( SingularAttributeBinding.NaturalIdMutability.IMMUTABLE, attributeBinding.getNaturalIdMutability() ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + + assertFalse( + "immutable natural id should not be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + Column column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + // ----------------------------------------------------------------------------------------------------- + + assertTrue( SchemaUtil.hasUniqueKeys( entityBinding.getPrimaryTable(), "name", "simpleEntity_id" ) ); + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java new file mode 100644 index 0000000000..ffc889dd1f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import org.junit.Test; + +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.test.annotations.loader.Player; +import org.hibernate.test.annotations.loader.Team; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class OneToManyBindingTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { Team.class, Player.class }) + public void testPluralAttributeBindingTest() { + EntityBinding playerBinding = getEntityBinding( Player.class ); + assertNotNull( playerBinding ); + + AttributeBinding attributeBinding = playerBinding.locateAttributeBinding( "team" ); + assertTrue( attributeBinding.isAssociation() ); + + HibernateTypeDescriptor typeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + EntityBinding teamBinding = getEntityBinding( Team.class ); + assertNotNull( teamBinding ); + attributeBinding = teamBinding.locateAttributeBinding( "players" ); + assertTrue( attributeBinding.isAssociation() ); + typeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + PluralAttributeBinding pluralAttributeBinding = PluralAttributeBinding.class.cast( attributeBinding ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java index b27dea5399..c2bb9db8fe 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -29,7 +29,9 @@ import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.Proxy; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -72,7 +74,7 @@ public class ProxyBindingTest extends BaseAnnotationBindingTestCase { assertTrue( "Wrong laziness", binding.isLazy() ); assertEquals( "Wrong proxy interface", - "org.hibernate.metamodel.source.annotations.entity.ProxyBindingTest$ProxyInterfaceEntity", + ProxyBindingTest.ProxyInterfaceEntity.class.getName(), binding.getProxyInterfaceType().getValue().getName() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java similarity index 79% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java index d139735248..9e54529802 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -30,8 +30,10 @@ import javax.persistence.Table; import org.junit.Test; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.Identifier; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static org.junit.Assert.assertEquals; @@ -39,7 +41,7 @@ import static org.junit.Assert.assertEquals; * @author Strong Liu */ public class QuotedIdentifierTest extends BaseAnnotationBindingTestCase { - private final String ormPath = "org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml"; + private final String ormPath = "org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml"; @Test @Resources(annotatedClasses = { Item.class, Item2.class, Item3.class, Item4.class }, ormXmlPath = ormPath) @@ -61,8 +63,8 @@ public class QuotedIdentifierTest extends BaseAnnotationBindingTestCase { //todo check if the column names are quoted private void assertIdentifierEquals(String expected, EntityBinding realValue) { - org.hibernate.metamodel.relational.Table table = (org.hibernate.metamodel.relational.Table) realValue.getPrimaryTable(); - assertEquals( Identifier.toIdentifier( expected ), table.getTableName() ); + org.hibernate.metamodel.spi.relational.Table table = (org.hibernate.metamodel.spi.relational.Table) realValue.getPrimaryTable(); + assertEquals( Identifier.toIdentifier( expected ), table.getPhysicalName() ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java index 7874ce1968..988203075f 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -29,7 +29,9 @@ import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.RowId; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java similarity index 54% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java index 2ba3cd1168..73b2e16022 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.Iterator; import javax.persistence.Column; @@ -32,12 +32,17 @@ import javax.persistence.SecondaryTable; import org.junit.Test; import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -47,6 +52,7 @@ import static junit.framework.Assert.fail; public class SecondaryTableTest extends BaseAnnotationBindingTestCase { @Entity @SecondaryTable(name = "SECOND_TABLE") + @SuppressWarnings( {"UnusedDeclaration"}) class EntityWithSecondaryTable { @Id private long id; @@ -60,13 +66,30 @@ public class SecondaryTableTest extends BaseAnnotationBindingTestCase { public void testSecondaryTableExists() { EntityBinding binding = getEntityBinding( EntityWithSecondaryTable.class ); Table table = (Table) binding.locateTable( "SECOND_TABLE" ); - assertEquals( "The secondary table should exist", "SECOND_TABLE", table.getTableName().getName() ); + assertEquals( "The secondary table should exist", "SECOND_TABLE", table.getPhysicalName().getText() ); - Iterator valueIterator = table.values().iterator(); - assertTrue( valueIterator.hasNext() ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) valueIterator.next(); - assertEquals( "Wrong column name", "name", column.getColumnName().getName() ); - assertFalse( valueIterator.hasNext() ); + assertEquals( 2, table.values().size() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) table.values().get( 0 ); + // TODO: the first column should be the secondary table's primary key??? + //assertSame( "First column is not the primary key", table.getPrimaryKey().getColumns().get( 0 ), column ); + // the second column should be the column for the attribute + column = (org.hibernate.metamodel.spi.relational.Column) table.values().get( 1 ); + assertEquals( "Wrong column name", "name", column.getColumnName().getText() ); + + Iterator fkIterator = table.getForeignKeys().iterator(); + assertTrue( fkIterator.hasNext() ); + ForeignKey foreignKey = fkIterator.next(); + assertEquals( "Wrong number of foreign key columns", 1, foreignKey.getTargetColumns().size() ); + assertSame( "Wrong column is the foreign key column", table.values().get( 0 ), foreignKey.getSourceColumns().get( 0 ) ); + assertEquals( "Wrong foreign key target column", binding.getPrimaryTable().getPrimaryKey().getColumns(), foreignKey.getTargetColumns() ); + assertFalse( fkIterator.hasNext() ); + + BasicAttributeBinding nameAttrBinding = (BasicAttributeBinding) binding.locateAttributeBinding( "name" ); + assertEquals( 1, nameAttrBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = nameAttrBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + assertSame( table, valueBinding.getTable() ); + assertSame( column, valueBinding.getValue() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java similarity index 75% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java index 04bf0ec8a9..0aca288a59 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java @@ -21,16 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; -import java.util.Set; import javax.persistence.Entity; import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.Synchronize; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -45,17 +46,26 @@ public class SynchronizeBindingTest extends BaseAnnotationBindingTestCase { @Resources(annotatedClasses = TestEntityWithSynchronizeAnnotation.class) public void testSynchronizeAnnotation() { EntityBinding binding = getEntityBinding( TestEntityWithSynchronizeAnnotation.class ); - Set synchronizedTableNames = binding.getSynchronizedTableNames(); - assertEquals( "Wrong number of synced tables", 2, synchronizedTableNames.size() ); - assertTrue( "Table name missing", synchronizedTableNames.contains( "Foo" ) ); - assertTrue( "Table name missing", synchronizedTableNames.contains( "Bar" ) ); + String [] synchronizedTableNames = binding.getSynchronizedTableNames(); + assertEquals( "Wrong number of synced tables", 2, synchronizedTableNames.length ); + assertTrue( "Table name missing", contains( synchronizedTableNames, "Foo" ) ); + assertTrue( "Table name missing", contains( synchronizedTableNames, "Bar" ) ); + } + + private boolean contains(String[] arrays, String key) { + for ( String s : arrays ) { + if ( key.equals( s ) ) { + return true; + } + } + return false; } @Test @Resources(annotatedClasses = TestEntity.class) public void testNoSynchronizeAnnotation() { EntityBinding binding = getEntityBinding( TestEntity.class ); - assertTrue( "There should be no cache binding", binding.getSynchronizedTableNames().size() == 0 ); + assertTrue( "There should be no cache binding", binding.getSynchronizedTableNames().length == 0 ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java similarity index 80% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java index eb31eb09b9..75b0845a7b 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -31,8 +31,10 @@ import javax.persistence.Table; import org.junit.Test; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; @@ -59,7 +61,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "TableNameTest$A", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( B.class ); @@ -67,7 +69,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "TableNameTest$A", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } @@ -92,7 +94,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "FOO", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( JoinedB.class ); @@ -100,7 +102,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "TableNameTest$JoinedB", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } @@ -125,7 +127,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "TableNameTest$TablePerClassA", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( TablePerClassB.class ); @@ -133,7 +135,7 @@ public class TableNameTest extends BaseAnnotationBindingTestCase { assertEquals( "wrong table name", "TableNameTest$TablePerClassB", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java index b85b6c9d32..67621812e8 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.Date; import javax.persistence.Entity; @@ -31,35 +31,24 @@ import javax.persistence.TemporalType; import org.junit.Test; -import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import org.hibernate.type.TimestampType; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; + /** * @author Strong Liu */ public class TemporalBindingTest extends BaseAnnotationBindingTestCase { - @Entity - class Item1 { - @Id - long id; - Date date; - } - - @Test(expected = AnnotationException.class) - @Resources(annotatedClasses = TemporalBindingTest.Item1.class) - public void testNoTemporalAnnotationOnTemporalTypeAttribute() { - getEntityBinding( Item1.class ); - - } - - @Entity + + @Entity class Item2 { @Id long id; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java new file mode 100644 index 0000000000..57ba6a8f23 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.entity; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import java.util.List; +import java.util.Set; + +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.OrderColumn; +import javax.persistence.Table; +import javax.persistence.TableGenerator; +import javax.persistence.UniqueConstraint; + +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +/** + * test for {@link javax.persistence.UniqueConstraint} + * + * @author Strong Liu + * @author Brett Meyer + */ +public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { TableWithUniqueConstraint.class, SecondTable.class }) + public void testTableUniqueConstraints() { + EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class ); + testTableUniqueConstraints( binding.getPrimaryTable(), "u1", 2 ); + testTableUniqueConstraints( ( (MultipleHiLoPerTableGenerator) binding.getHierarchyDetails() + .getEntityIdentifier().getIdentifierGenerator() ).getTable(), "u2", 1 ); + testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "secondTables", meta ) + .getPluralAttributeKeyBinding().getCollectionTable(), "u3", 2 ); + testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "elements", meta ) + .getPluralAttributeKeyBinding().getCollectionTable(), "u4", 1 ); + } + + private void testTableUniqueConstraints(TableSpecification table, String ukName, int ukNumColumns) { + Iterable uniqueKeyIterable = table.getUniqueKeys(); + assertNotNull( uniqueKeyIterable ); + int i = 0; + for ( UniqueKey key : uniqueKeyIterable ) { + i++; + assertEquals( ukName, key.getName() ); + assertTrue( table == key.getTable() ); + assertNotNull( key.getColumns() ); + assertEquals( "There should be two columns in the unique constraint", ukNumColumns, key.getColumns().size() ); + assertEquals( "There should be two columns in the unique constraint", ukNumColumns, key.getColumnSpan() ); + } + assertEquals( "There should only be one unique constraint", 1, i ); + } + + @Entity + @Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) }) + class TableWithUniqueConstraint { + @Id + @GeneratedValue(strategy = GenerationType.TABLE, generator = "fooGenerator") + @TableGenerator(name = "fooGenerator", table = "foo_generator_table", valueColumnName = "fooGeneratorValue", uniqueConstraints = @UniqueConstraint(columnNames = "fooGeneratorValue", name = "u2")) + int id; + + String name; + + int age; + + @ManyToMany + @JoinTable(name = "JoinTable", joinColumns = @JoinColumn(name = "secondTable"), inverseJoinColumns = @JoinColumn(name = "tableWithUniqueConstraint"), uniqueConstraints = @UniqueConstraint(columnNames = { + "secondTable", "tableWithUniqueConstraint" }, name = "u3")) + Set secondTables; + + @ElementCollection + @CollectionTable(name = "CollectionTable", joinColumns = @JoinColumn(name = "element"), uniqueConstraints = @UniqueConstraint(columnNames = "element", name = "u4")) + @OrderColumn(name = "element_index") + public List elements; + // TODO: int[] is not completely supported using the new metamodel yet, so I changed int[] to List + } + + @Entity + class SecondTable { + @Id + @GeneratedValue + int id; + + String name; + + int age; + + @ManyToMany(mappedBy = "secondTables") + Set tableWithUniqueConstraint; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java new file mode 100644 index 0000000000..f3e070b9e7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Version; + +import org.junit.Test; + +import org.hibernate.annotations.Source; +import org.hibernate.annotations.SourceType; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.hibernate.type.DbTimestampType; +import org.hibernate.type.LongType; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class VersionBindingTests extends BaseAnnotationBindingTestCase { + @Entity + class Item1 { + @Id + long id; + long version; + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item1.class) + public void testNoVersionAnnotation() { + assertFalse( getEntityBinding( Item1.class ).isVersioned() ); + } + + @Entity + class Item2 { + @Id + private long id; + @Version + private Long version; + + //we need add getters / setters due to HHH-6561 + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item2.class) + public void testVersionTypeAttribute() { + EntityBinding binding = getEntityBinding( Item2.class ); + assertTrue( binding.isVersioned() ); + HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding() + .getHibernateTypeDescriptor(); +// assertEquals( "Long", descriptor.getExplicitTypeName() ); + assertEquals( Long.class.getName(), descriptor.getJavaTypeName() ); + assertNotNull( descriptor.getResolvedTypeMapping() ); + assertEquals( LongType.class, descriptor.getResolvedTypeMapping().getClass() ); + assertNotNull( descriptor.getTypeParameters() ); + assertTrue( descriptor.getTypeParameters().isEmpty() ); + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item2.class) + public void testVersionUnsavedValue() { + EntityBinding binding = getEntityBinding( Item2.class ); + assertTrue( binding.isVersioned() ); + assertEquals( "undefined", binding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + @Entity + class Item3 { + @Id + Long id; + @Version + @Source(SourceType.DB) + Date version; + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item3.class) + public void testVersionAttributeWithSource() { + EntityBinding binding = getEntityBinding( Item3.class ); + assertTrue( binding.isVersioned() ); + HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding() + .getHibernateTypeDescriptor(); + assertEquals( "dbtimestamp", descriptor.getExplicitTypeName() ); + assertEquals( Date.class.getName(), descriptor.getJavaTypeName() ); + assertNotNull( descriptor.getResolvedTypeMapping() ); + assertEquals( DbTimestampType.class, descriptor.getResolvedTypeMapping().getClass() ); + assertNotNull( descriptor.getTypeParameters() ); + assertTrue( descriptor.getTypeParameters().isEmpty() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java similarity index 70% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java index 6b3702e754..385c3e7ef4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java @@ -1,4 +1,4 @@ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -6,7 +6,9 @@ import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.Where; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java similarity index 72% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java index a686f1b03e..085f60f8b2 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java @@ -21,11 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.global; +package org.hibernate.metamodel.internal.source.annotations.global; import java.util.Iterator; import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -35,12 +36,12 @@ import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchProfile; import org.hibernate.annotations.FetchProfiles; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.internal.MetadataImpl; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContextImpl; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.testing.junit4.BaseUnitTestCase; import static junit.framework.Assert.fail; @@ -75,27 +76,27 @@ public class FetchProfileBinderTest extends BaseUnitTestCase { }) class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); + IndexView index = JandexHelper.indexForClass( service, Foo.class ); - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + FetchProfileProcessor.bind( new AnnotationBindingContextImpl( meta, index ) ); - Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); + Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); assertTrue( mappedFetchProfiles.hasNext() ); - org.hibernate.metamodel.binding.FetchProfile profile = mappedFetchProfiles.next(); + org.hibernate.metamodel.spi.binding.FetchProfile profile = mappedFetchProfiles.next(); assertEquals( "Wrong fetch profile name", "foo", profile.getName() ); - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); assertEquals( "Wrong association name", "bar", fetch.getAssociation() ); assertEquals( "Wrong association type", Foo.class.getName(), fetch.getEntity() ); } @Test public void testFetchProfiles() { - Index index = JandexHelper.indexForClass( service, FooBar.class ); - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + IndexView index = JandexHelper.indexForClass( service, FooBar.class ); + FetchProfileProcessor.bind( new AnnotationBindingContextImpl( meta, index ) ); - Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); + Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); assertTrue( mappedFetchProfiles.hasNext() ); - org.hibernate.metamodel.binding.FetchProfile profile = mappedFetchProfiles.next(); + org.hibernate.metamodel.spi.binding.FetchProfile profile = mappedFetchProfiles.next(); assertProfiles( profile ); assertTrue( mappedFetchProfiles.hasNext() ); @@ -103,14 +104,14 @@ public class FetchProfileBinderTest extends BaseUnitTestCase { assertProfiles( profile ); } - private void assertProfiles(org.hibernate.metamodel.binding.FetchProfile profile) { + private void assertProfiles(org.hibernate.metamodel.spi.binding.FetchProfile profile) { if ( profile.getName().equals( "foobar" ) ) { - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); assertEquals( "Wrong association name", "foobar", fetch.getAssociation() ); assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); } else if ( profile.getName().equals( "fubar" ) ) { - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); assertEquals( "Wrong association name", "fubar", fetch.getAssociation() ); assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); } @@ -126,9 +127,9 @@ public class FetchProfileBinderTest extends BaseUnitTestCase { }) class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); + IndexView index = JandexHelper.indexForClass( service, Foo.class ); - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + FetchProfileProcessor.bind( new AnnotationBindingContextImpl( meta, index ) ); } @FetchProfiles( { diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java similarity index 82% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java index dc27113eb1..605588ac39 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java @@ -21,37 +21,34 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.global; - -import javax.persistence.NamedNativeQuery; - -import org.jboss.jandex.Index; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; -import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; +package org.hibernate.metamodel.internal.source.annotations.global; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; +import javax.persistence.NamedNativeQuery; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContextImpl; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.jboss.jandex.IndexView; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + /** * @author Hardy Ferentschik */ public class QueryBinderTest extends BaseUnitTestCase { - private StandardServiceRegistryImpl serviceRegistry; private ClassLoaderService service; private MetadataImpl meta; @@ -68,13 +65,13 @@ public class QueryBinderTest extends BaseUnitTestCase { serviceRegistry.destroy(); } - @Test(expected = NotYetImplementedException.class) + @Test public void testNoResultClass() { @NamedNativeQuery(name = "fubar", query = "SELECT * FROM FOO") class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); - QueryBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + IndexView index = JandexHelper.indexForClass( service, Foo.class ); + QueryProcessor.bind( new AnnotationBindingContextImpl( meta, index ) ); } @Test @@ -82,8 +79,8 @@ public class QueryBinderTest extends BaseUnitTestCase { @NamedNativeQuery(name = "fubar", query = "SELECT * FROM FOO", resultClass = Foo.class) class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); - QueryBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + IndexView index = JandexHelper.indexForClass( service, Foo.class ); + QueryProcessor.bind( new AnnotationBindingContextImpl( meta, index ) ); NamedSQLQueryDefinition namedQuery = meta.getNamedNativeQuery( "fubar" ); assertNotNull( namedQuery ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java similarity index 71% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java index fd57f6d3fe..9f4eb2fa70 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java @@ -21,25 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import java.util.Set; import javax.persistence.AccessType; +import com.fasterxml.classmate.ResolvedType; import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.junit.After; import org.junit.Before; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.EntityHierarchyBuilder; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableHierarchy; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.internal.MetadataImpl; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContextImpl; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableHierarchy; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.EntityHierarchy; import org.hibernate.testing.junit4.BaseUnitTestCase; /** @@ -59,7 +60,7 @@ public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase { } public Set createEntityHierarchies(Class... clazz) { - Index index = JandexHelper.indexForClass( + IndexView index = JandexHelper.indexForClass( meta.getServiceRegistry().getService( ClassLoaderService.class ), clazz ); @@ -67,13 +68,15 @@ public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase { return EntityHierarchyBuilder.createEntityHierarchies( context ); } - public EmbeddableHierarchy createEmbeddableHierarchy(AccessType accessType, Class... configuredClasses) { - Index index = JandexHelper.indexForClass( + public EmbeddableHierarchy createEmbeddableHierarchy(AccessType accessType,SingularAttributeBinding.NaturalIdMutability naturalIdMutability, Class... configuredClasses) { + IndexView index = JandexHelper.indexForClass( meta.getServiceRegistry().getService( ClassLoaderService.class ), configuredClasses ); AnnotationBindingContext context = new AnnotationBindingContextImpl( meta, index ); - return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "", accessType, context ); + ResolvedType resolvedType = context.getTypeResolver().resolve( configuredClasses[0] ); + return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "",resolvedType, accessType, + naturalIdMutability,null, context ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EmbeddableHierarchyTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EmbeddableHierarchyTest.java index deae20dbd7..efac81d248 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EmbeddableHierarchyTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import java.util.Iterator; import javax.persistence.AccessType; @@ -36,8 +36,9 @@ import org.junit.Ignore; import org.junit.Test; import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableHierarchy; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass; +import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableHierarchy; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -65,7 +66,7 @@ public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase { } EmbeddableHierarchy hierarchy = createEmbeddableHierarchy( - AccessType.FIELD, + AccessType.FIELD, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID, C.class, A.class, B.class @@ -86,7 +87,8 @@ public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase { class NonAnnotatedEmbeddable { } - createEmbeddableHierarchy( AccessType.FIELD, NonAnnotatedEmbeddable.class ); + createEmbeddableHierarchy( AccessType.FIELD, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID, NonAnnotatedEmbeddable.class ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyTest.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyTest.java index 202a0acbdd..ba543d807e 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchyTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import java.util.Iterator; import java.util.Set; @@ -35,10 +35,10 @@ import javax.persistence.MappedSuperclass; import org.junit.Test; import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.EntityHierarchy; +import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SubclassEntitySource; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java index 4d29116a91..61d6d59caf 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -250,4 +250,4 @@ public class GenericTypeDiscoveryTest extends BaseAnnotationIndexTestCase { this.state = state; } } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java similarity index 63% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java index 10edc54a44..950618ad67 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java @@ -21,17 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; -import java.net.MalformedURLException; -import java.net.URL; +import java.util.Collection; import java.util.List; import java.util.Map; -import javax.persistence.AttributeConverter; import javax.persistence.AttributeOverride; import javax.persistence.Basic; import javax.persistence.Column; -import javax.persistence.Converter; import javax.persistence.Entity; import javax.persistence.LockModeType; import javax.persistence.NamedQuery; @@ -40,18 +37,15 @@ import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.hibernate.AssertionFailure; -import org.hibernate.HibernateException; import org.hibernate.annotations.NamedNativeQuery; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -89,11 +83,11 @@ public class JandexHelperTest extends BaseUnitTestCase { private String bar; private String fubar; } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); ClassInfo classInfo = index.getClassByName( DotName.createSimple( Foo.class.getName() ) ); Map> memberAnnotations = JandexHelper.getMemberAnnotations( - classInfo, "bar" + classInfo, "bar", serviceRegistry ); assertTrue( "property bar should defines @Column annotation", @@ -104,7 +98,7 @@ public class JandexHelperTest extends BaseUnitTestCase { memberAnnotations.containsKey( DotName.createSimple( Basic.class.getName() ) ) ); - memberAnnotations = JandexHelper.getMemberAnnotations( classInfo, "fubar" ); + memberAnnotations = JandexHelper.getMemberAnnotations( classInfo, "fubar", serviceRegistry ); assertTrue( "there should be no annotations in fubar", memberAnnotations.isEmpty() ); } @@ -114,20 +108,21 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); // try to retrieve the name - String name = JandexHelper.getValue( annotationInstance, "name", String.class ); + String name = JandexHelper.getValue( annotationInstance, "name", String.class, classLoaderService ); assertEquals( "Wrong nested annotation", "foo", name ); // try to retrieve the nested column annotation instance AnnotationInstance columnAnnotationInstance = JandexHelper.getValue( annotationInstance, "column", - AnnotationInstance.class + AnnotationInstance.class, + classLoaderService ); assertNotNull( columnAnnotationInstance ); assertEquals( @@ -143,12 +138,13 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - JandexHelper.getValue( annotationInstance, "name", Float.class ); + JandexHelper.getValue( annotationInstance, "name", Float.class, + classLoaderService); } @Test @@ -157,12 +153,13 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class ); + LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class, + classLoaderService ); assertEquals( "Wrong lock mode", LockModeType.NONE, lockMode ); } @@ -172,12 +169,13 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class ); + LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class, + classLoaderService ); assertEquals( "Wrong lock mode", LockModeType.OPTIMISTIC, lockMode ); } @@ -188,12 +186,13 @@ public class JandexHelperTest extends BaseUnitTestCase { private String foo; } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.INDEX ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( HibernateDotNames.INDEX ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - String[] columnNames = JandexHelper.getValue( annotationInstance, "columnNames", String[].class ); + String[] columnNames = JandexHelper.getValue( annotationInstance, "columnNames", String[].class, + classLoaderService ); Assert.assertTrue( columnNames.length == 3 ); } @@ -203,12 +202,12 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - JandexHelper.getValue( annotationInstance, "resultClass", Class.class ); + JandexHelper.getValue( annotationInstance, "resultClass", Class.class, classLoaderService ); } @Test @@ -217,12 +216,12 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); - String fqcn = JandexHelper.getValue( annotationInstance, "resultClass", String.class ); + String fqcn = JandexHelper.getValue( annotationInstance, "resultClass", String.class, classLoaderService ); assertEquals( "Wrong class names", Foo.class.getName(), fqcn ); } @@ -232,13 +231,13 @@ public class JandexHelperTest extends BaseUnitTestCase { class Foo { } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ENTITY ); + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ENTITY ); assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); try { - JandexHelper.getValue( annotationInstance, "foo", String.class ); + JandexHelper.getValue( annotationInstance, "foo", String.class, classLoaderService ); fail(); } catch ( AssertionFailure e ) { @@ -249,36 +248,6 @@ public class JandexHelperTest extends BaseUnitTestCase { } } - - @Test - public void testPrimitiveAnnotationAttributeTypes() { - @Converter( autoApply = true ) - class MyConverter implements AttributeConverter { - - @Override - public String convertToDatabaseColumn(URL attribute) { - return attribute.toExternalForm(); - } - - @Override - public URL convertToEntityAttribute(String dbData) { - try { - return new URL( dbData ); - } - catch (MalformedURLException e) { - throw new HibernateException( "Could not convert string [" + dbData + "] to url", e ); - } - } - } - - Index index = JandexHelper.indexForClass( classLoaderService, MyConverter.class ); - List annotationInstances = index.getAnnotations( JPADotNames.CONVERTER ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - boolean value = JandexHelper.getValue( annotationInstance, "autoApply", boolean.class ); - Assert.assertTrue( value ); - } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java index 2d2753440d..ebc6a9b7c0 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import javax.persistence.Id; @@ -64,4 +64,4 @@ public class TypeDiscoveryTest extends BaseAnnotationIndexTestCase { @Type(type = "my.custom.Type", parameters = { @Parameter(name = "foo", value = "bar") }) private String customString; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java index 76f829b9d7..e4b950ac05 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java similarity index 78% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java index e31cea2ea4..962c2e2561 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java @@ -21,17 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; -import static junit.framework.Assert.assertNotNull; +import org.junit.Test; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.internal.MetadataImpl; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.source.MappingException; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.junit.Test; + +import static junit.framework.Assert.assertNotNull; /** * @author Hardy Ferentschik @@ -40,7 +41,7 @@ public class OrmXmlParserTests extends BaseUnitTestCase { @Test public void testSimpleOrmVersion2() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-father.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml" ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); EntityBinding binding = metadata.getEntityBinding( Father.class.getName() ); @@ -50,17 +51,16 @@ public class OrmXmlParserTests extends BaseUnitTestCase { @Test public void testSimpleOrmVersion1() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-star.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml" ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding binding = metadata.getEntityBinding( Star.class.getName() ); assertNotNull( binding ); } - @Test(expected = MappingException.class) + @Test(expected = org.hibernate.metamodel.spi.source.InvalidMappingException.class) public void testInvalidOrmXmlThrowsException() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml" ); sources.buildMetadata(); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java index 5131a0a319..b6af84a864 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java index 4b9f23a999..236cf8fa06 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.io.IOException; import java.io.InputStream; @@ -38,9 +38,13 @@ import org.jboss.jandex.Indexer; import org.hibernate.AnnotationException; import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.service.ServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.jaxb.internal.JaxbMappingProcessor; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; +import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.jaxb.spi.orm.JaxbEntityMappings; +import org.hibernate.service.ServiceRegistry; import org.hibernate.testing.ServiceRegistryBuilder; import static org.junit.Assert.assertEquals; @@ -52,7 +56,7 @@ import static org.junit.Assert.fail; public abstract class AbstractMockerTest { private static final String ORM1_MAPPING_XSD = "org/hibernate/jpa/orm_1_0.xsd"; private static final String ORM2_MAPPING_XSD = "org/hibernate/jpa/orm_2_0.xsd"; - + private static final String ORM2_1_MAPPING_XSD = "org/hibernate/jpa/orm_2_1.xsd"; private IndexBuilder indexBuilder; private Index index; private ServiceRegistry serviceRegistry; @@ -70,23 +74,14 @@ public abstract class AbstractMockerTest { ClassLoaderService classLoaderService = getServiceRegistry().getService( ClassLoaderService.class ); List xmlEntityMappingsList = new ArrayList(); for ( String fileName : mappingFiles ) { - JaxbEntityMappings entityMappings; - try { - entityMappings = XmlHelper.unmarshallXml( - packagePrefix + fileName, ORM2_MAPPING_XSD, JaxbEntityMappings.class, classLoaderService - ).getRoot(); - } - catch ( JAXBException orm2Exception ) { - // if we cannot parse against orm_2_0.xsd we try orm_1_0.xsd for backwards compatibility - try { - entityMappings = XmlHelper.unmarshallXml( - packagePrefix + fileName, ORM1_MAPPING_XSD, JaxbEntityMappings.class, classLoaderService - ).getRoot(); - } - catch ( JAXBException orm1Exception ) { - throw new AnnotationException( "Unable to parse xml configuration.", orm1Exception ); - } - } + JaxbMappingProcessor processor = new JaxbMappingProcessor( getServiceRegistry() ); + JaxbRoot jaxbRoot = processor.unmarshal( + classLoaderService.locateResourceStream( packagePrefix + fileName ), + new Origin( SourceType.FILE, packagePrefix + fileName ) + ); + JaxbEntityMappings entityMappings = (JaxbEntityMappings)jaxbRoot.getRoot(); + + xmlEntityMappingsList.add( entityMappings ); } return new EntityMappingsMocker( xmlEntityMappingsList, getIndex(), getServiceRegistry() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java index 0a2868d18d..169e6e2bdc 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java index f53b4f2314..e58c852025 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; @@ -29,11 +29,11 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbGeneratedValue; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.metamodel.source.annotations.JPADotNames; +import org.hibernate.jaxb.spi.orm.JaxbAttributes; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.jaxb.spi.orm.JaxbGeneratedValue; +import org.hibernate.jaxb.spi.orm.JaxbId; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java index ccfebfa64e..2cdfb39865 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.Date; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java index 2a5e913c73..7b3d111778 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java @@ -1,4 +1,4 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.HashMap; import java.util.HashSet; @@ -18,8 +18,8 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.metamodel.source.annotations.JPADotNames; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -54,8 +54,7 @@ public class DefaultConfigurationHelperTest extends AbstractMockerTest { assertNull( entity.getTable().getCatalog() ); assertTrue( entity.isMetadataComplete() ); assertEquals( "org.test.Entity", entity.getClazz() ); - DefaultConfigurationHelper.INSTANCE - .applyDefaults( new SchemaAware.TableSchemaAware( entity.getTable() ), defaults ); + DefaultConfigurationHelper.INSTANCE.applyDefaults( entity.getTable(), defaults ); assertEquals( "schema", entity.getTable().getSchema() ); assertNull( entity.getTable().getCatalog() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java index 392e5430ff..fc50ac24a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java @@ -21,15 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; import static org.junit.Assert.assertEquals; @@ -56,7 +56,5 @@ public class EntityListenerTest extends AbstractMockerTest { assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_PRE_PERSIST ); assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_POST_PERSIST ); - - } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java similarity index 72% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java index 52d1189241..1ccdb21128 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java @@ -1,4 +1,4 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java index fa5be30fc4..70c811018c 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; /** * @author Strong Liu diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java index dc1852b0b6..ad56f70aa1 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; /** * @author Strong Liu diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java index 2f796486de..cf776ddc2b 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.List; @@ -32,8 +32,8 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.metamodel.source.annotations.JPADotNames; +import org.hibernate.jaxb.spi.orm.JaxbEntity; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java index 0086b8975e..6f8437b7a6 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import javax.persistence.AccessType; @@ -29,7 +29,7 @@ import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.internal.source.annotations.xml.PseudoJpaDotNames; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java index cf74904525..fbf335b67e 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import javax.persistence.Embeddable; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java index e7cc270ade..008168a87f 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.io.InputStream; import java.net.URL; @@ -36,10 +36,10 @@ import javax.xml.validation.SchemaFactory; import org.jboss.logging.Logger; import org.xml.sax.SAXException; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jaxb.spi.JaxbRoot; +import org.hibernate.jaxb.spi.Origin; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java index cf82afd1f1..9387e9a3ce 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java @@ -24,7 +24,7 @@ @FetchProfile(name = "package-configured-profile", fetchOverrides = { @FetchProfile.FetchOverride(entity = Foo.class, association = "bar", mode = FetchMode.JOIN) }) -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchProfile; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java deleted file mode 100644 index bccbc2ecc7..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; - -import org.junit.Test; - -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.relational.UniqueKey; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -/** - * test for {@link javax.persistence.UniqueConstraint} - * - * @author Strong Liu - */ -public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase { - @Test - @Resources(annotatedClasses = TableWithUniqueConstraint.class) - public void testTableUniqueConstraints() { - EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class ); - TableSpecification table = binding.getPrimaryTable(); - Iterable uniqueKeyIterable = table.getUniqueKeys(); - assertNotNull( uniqueKeyIterable ); - int i = 0; - for ( UniqueKey key : uniqueKeyIterable ) { - i++; - assertEquals( "u1", key.getName() ); - assertTrue( table == key.getTable() ); - assertNotNull( key.getColumns() ); - int j = 0; - for ( Column column : key.getColumns() ) { - j++; - } - assertEquals( "There should be two columns in the unique constraint", 2, j ); - } - assertEquals( "There should only be one unique constraint", 1, i ); - } - - @Entity - @Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) }) - class TableWithUniqueConstraint { - @Id - int id; - String name; - int age; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java new file mode 100644 index 0000000000..4080567f0b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java @@ -0,0 +1,310 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.sql.Types; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.FetchMode; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.BasicType; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.type.LongType; +import org.hibernate.type.StringType; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Basic tests of {@code hbm.xml} and annotation binding code + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testSimpleEntityMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleEntityBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); + assertRoot( metadata, entityBinding ); + assertIdAndSimpleProperty( entityBinding ); + + assertNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ); + } + + @Test + public void testSimpleVersionedEntityMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleVersionedEntityBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() ); + assertIdAndSimpleProperty( entityBinding ); + + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding().getAttribute() ); + + final BasicAttributeBinding versionAttributeBinding = + entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(); + assertEquals( "does not have 1 relational binding", 1, versionAttributeBinding.getRelationalValueBindings().size() ); + assertEquals( "version is nullable", false, versionAttributeBinding.getRelationalValueBindings().get( 0 ).isNullable() ); + } + + protected void testEntityWithManyToOneMapping(String defaultManyToOneColumnReferencingId) { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleEntityBinding( sources ); + addSourcesForManyToOne( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + + final String simpleEntityClassName = SimpleEntity.class.getName(); + EntityBinding simpleEntityBinding = metadata.getEntityBinding( simpleEntityClassName ); + assertIdAndSimpleProperty( simpleEntityBinding ); + + EntityBinding entityWithManyToOneBinding = metadata.getEntityBinding( EntityWithManyToOnes.class.getName() ); + AttributeBinding attributeBinding = entityWithManyToOneBinding.locateAttributeBinding( "simpleEntity" ); + checkManyToOneAttributeBinding( + metadata, + entityWithManyToOneBinding, + attributeBinding, + SingularAttributeBinding.class.cast( + simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() + ), + defaultManyToOneColumnReferencingId, + false + ); + + checkManyToOneAttributeBinding( + metadata, + entityWithManyToOneBinding, + entityWithManyToOneBinding.locateAttributeBinding( "simpleEntityFromPropertyRef" ), + SingularAttributeBinding.class.cast( simpleEntityBinding.locateAttributeBinding( "name" ) ), + "simplename", + true + ); + } + + private void checkManyToOneAttributeBinding( + MetadataImplementor metadata, + EntityBinding entityWithManyToOneBinding, + AttributeBinding attributeBinding, + SingularAttributeBinding referencedAttributeBinding, + String manyToOneColumnName, + boolean expectedNullable) { + final EntityBinding referencedEntityBinding = referencedAttributeBinding.getContainer().seekEntityBinding(); + final String referencedEntityName = referencedEntityBinding.getEntity().getName(); + assertTrue( SingularAttributeBinding.class.isInstance( referencedAttributeBinding ) ); + assertEquals( 1, SingularAttributeBinding.class.cast( referencedAttributeBinding ).getRelationalValueBindings().size() ); + final Value referencedValue = + SingularAttributeBinding.class.cast( referencedAttributeBinding ) + .getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( Column.class.isInstance( referencedValue ) ); + final JdbcDataType referencedJdbcDataType = Column.class.cast( referencedValue ).getJdbcDataType(); + + // binding model + assertTrue( attributeBinding.isAssociation() ); + assertTrue( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ); + ManyToOneAttributeBinding manyToOneAttributeBinding = (ManyToOneAttributeBinding) attributeBinding; + assertEquals( referencedEntityName, manyToOneAttributeBinding.getReferencedEntityName() ); + assertSame( referencedEntityBinding, manyToOneAttributeBinding.getReferencedEntityBinding() ); + assertSame( CascadeStyles.NONE, manyToOneAttributeBinding.getCascadeStyle() ); + assertTrue( manyToOneAttributeBinding.isLazy() ); + assertSame( FetchMode.SELECT, manyToOneAttributeBinding.getFetchMode() ); + assertSame( FetchTiming.DELAYED, manyToOneAttributeBinding.getFetchTiming() ); + assertSame( entityWithManyToOneBinding, manyToOneAttributeBinding.getContainer() ); + Assert.assertEquals( "property", manyToOneAttributeBinding.getPropertyAccessorName() ); + assertTrue( manyToOneAttributeBinding.isIncludedInOptimisticLocking() ); + assertFalse( manyToOneAttributeBinding.isAlternateUniqueKey() ); + assertEquals( expectedNullable, manyToOneAttributeBinding.isNullable() ); + HibernateTypeDescriptor hibernateTypeDescriptor = manyToOneAttributeBinding.getHibernateTypeDescriptor(); + Assert.assertNull( hibernateTypeDescriptor.getExplicitTypeName() ); + Assert.assertEquals( referencedEntityName, hibernateTypeDescriptor.getJavaTypeName() ); + assertTrue( hibernateTypeDescriptor.isToOne() ); + assertTrue( hibernateTypeDescriptor.getTypeParameters().isEmpty() ); + + // domain model + Attribute simpleEntityAttribute= entityWithManyToOneBinding.getEntity().locateAttribute( "simpleEntity" ); + assertEquals( "simpleEntity", simpleEntityAttribute.getName() ); + Assert.assertSame( entityWithManyToOneBinding.getEntity(), simpleEntityAttribute.getAttributeContainer() ) ; + Assert.assertTrue( simpleEntityAttribute.isSingular() ); + SingularAttribute simpleEntitySingularAttribute = ( SingularAttribute ) simpleEntityAttribute; + assertTrue( simpleEntitySingularAttribute.isTypeResolved() ); + assertSame( + metadata.getEntityBinding( referencedEntityName ).getEntity(), + simpleEntitySingularAttribute.getSingularAttributeType() + ); + Entity simpleEntityAttributeType = (Entity) simpleEntitySingularAttribute.getSingularAttributeType(); + assertEquals( referencedEntityName, simpleEntityAttributeType.getName() ); + Assert.assertEquals( referencedEntityName, simpleEntityAttributeType.getClassName()); + Assert.assertTrue( simpleEntityAttributeType.isAssociation() ); + assertFalse( simpleEntityAttributeType.isAggregate() ); + + // relational + List relationalValueBindings = manyToOneAttributeBinding.getRelationalValueBindings(); + Assert.assertEquals( 1, relationalValueBindings.size() ); + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + assertFalse( relationalValueBinding.isDerived() ); + assertTrue( relationalValueBinding.isIncludeInInsert() ); + assertTrue( relationalValueBinding.isIncludeInUpdate() ); + assertEquals( expectedNullable, relationalValueBinding.isNullable() ); + assertTrue( relationalValueBinding.getValue() instanceof Column ); + Column column = ( Column ) relationalValueBinding.getValue(); + Assert.assertEquals( Identifier.toIdentifier( manyToOneColumnName ), column.getColumnName() ); + JdbcDataType jdbcDataType = column.getJdbcDataType(); + assertEquals( referencedJdbcDataType.getTypeCode(), jdbcDataType.getTypeCode() ); + assertEquals( referencedJdbcDataType.getJavaType(), jdbcDataType.getJavaType() ); + assertEquals( referencedJdbcDataType.getTypeName(), jdbcDataType.getTypeName() ); + + // locate the foreignKey + boolean sourceColumnFound = false; + for ( ForeignKey fk : relationalValueBinding.getTable().getForeignKeys() ) { + for ( Column sourceColumn : fk.getSourceColumns() ) { + if ( sourceColumn == column ) { + assertFalse( "source column not found in more than one foreign key", sourceColumnFound ); + sourceColumnFound = true; + assertEquals( 1, fk.getTargetColumns().size() ); + assertSame( + referencedAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(), + fk.getTargetColumns().get( 0 ) + ); + } + } + } + assertTrue( "foreign key with specified source column found", sourceColumnFound ); + } + + @Test + public void testSimpleEntityWithSimpleComponentMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForComponentBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntityWithSimpleComponent.class.getName() ); + assertRoot( metadata, entityBinding ); + assertIdAndSimpleProperty( entityBinding ); + + CompositeAttributeBinding compositeAttributeBinding = + (CompositeAttributeBinding) entityBinding.locateAttributeBinding( "simpleComponent" ); + assertNotNull( compositeAttributeBinding ); + assertSame( compositeAttributeBinding.getAttribute().getSingularAttributeType(), compositeAttributeBinding.getAttributeContainer() ); + assertEquals( "simpleComponent", compositeAttributeBinding.getPathBase() ); + assertSame( entityBinding, compositeAttributeBinding.seekEntityBinding() ); + assertTrue( compositeAttributeBinding.getAttribute().getSingularAttributeType() instanceof Aggregate ); + } + + public abstract void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources); + + public abstract void addSourcesForSimpleEntityBinding(MetadataSources sources); + + public abstract void addSourcesForManyToOne(MetadataSources sources); + + public abstract void addSourcesForComponentBinding(MetadataSources sources); + + protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { + assertNotNull( entityBinding ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + + AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); + assertNotNull( idAttributeBinding ); + assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + + assertTrue( idAttributeBinding.getAttribute().isSingular() ); + assertNotNull( idAttributeBinding.getAttribute() ); + SingularAttributeBinding singularIdAttributeBinding = (SingularAttributeBinding) idAttributeBinding; + assertFalse( singularIdAttributeBinding.isNullable() ); + SingularAttribute singularIdAttribute = ( SingularAttribute ) idAttributeBinding.getAttribute(); + BasicType basicIdAttributeType = ( BasicType ) singularIdAttribute.getSingularAttributeType(); + assertSame( Long.class, basicIdAttributeType.getClassReference() ); + + assertTrue( singularIdAttributeBinding.getRelationalValueBindings().size() == 1 ); + Value value = singularIdAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( value instanceof Column ); + JdbcDataType idDataType = value.getJdbcDataType(); + assertSame( Long.class, idDataType.getJavaType() ); + assertSame( Types.BIGINT, idDataType.getTypeCode() ); + assertSame( LongType.INSTANCE.getName(), idDataType.getTypeName() ); + + assertNotNull( entityBinding.locateAttributeBinding( "name" ) ); + assertNotNull( entityBinding.locateAttributeBinding( "name" ).getAttribute() ); + assertTrue( entityBinding.locateAttributeBinding( "name" ).getAttribute().isSingular() ); + + SingularAttributeBinding nameBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( "name" ); + assertTrue( nameBinding.isNullable() ); + assertSame( StringType.INSTANCE, nameBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + assertNotNull( nameBinding.getAttribute() ); + assertNotNull( nameBinding.getRelationalValueBindings().size() ); + SingularAttribute singularNameAttribute = nameBinding.getAttribute(); + BasicType basicNameAttributeType = (BasicType) singularNameAttribute.getSingularAttributeType(); + assertSame( String.class, basicNameAttributeType.getClassReference() ); + Assert.assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Value nameValue = nameBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( nameValue instanceof Column ); + JdbcDataType nameDataType = nameValue.getJdbcDataType(); + assertSame( String.class, nameDataType.getJavaType() ); + assertSame( Types.VARCHAR, nameDataType.getTypeCode() ); + assertSame( StringType.INSTANCE.getName(), nameDataType.getTypeName() ); + } + + protected void assertRoot(MetadataImplementor metadata, EntityBinding entityBinding) { + assertTrue( entityBinding.isRoot() ); + assertSame( entityBinding, metadata.getRootEntityBinding( entityBinding.getEntity().getName() ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java new file mode 100644 index 0000000000..0c58284491 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java @@ -0,0 +1,209 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.sql.Timestamp; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; + +/** + * "Unsaved" value tests of {@code hbm.xml} and annotation binding code + * + * @author Gail Badner + */ +public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + protected ServiceRegistry basicServiceRegistry() { + return serviceRegistry; + } + + @Test + public void testAssignedSimpleIdDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForAssignedIdDefaultUnsavedValue( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testIncrementSimpleIdDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSequenceIdDefaultUnsavedValue( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + // Generator is explicitly "increment", so unsaved ID value should be null + assertEquals( null, entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testDefaultUnsavedVersion() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForDefaultUnsavedVersion( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithVersion.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testDefaultUnsavedTimestamp() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForDefaultUnsavedTimestamp( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithTimestamp.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + public abstract void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources); + + public abstract void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources); + + public abstract void addSourcesForDefaultUnsavedVersion(MetadataSources sources); + + public abstract void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources); + + @Entity + public static class EntityWithAssignedId { + @Id + private Long id; + + public EntityWithAssignedId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithSequenceId { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + + public EntityWithSequenceId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithVersion { + @Id + private Long id; + + @Version + private Integer version; + + public EntityWithVersion() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + } + + @Entity + public static class EntityWithTimestamp { + @Id + private Long id; + + @Version + @Temporal( value = TemporalType.TIMESTAMP ) + private Timestamp timestamp; + + public EntityWithTimestamp() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + public void setTimestamp(Timestamp timestamp) { + this.timestamp = timestamp; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java index 50d9a9068e..eef0449cc4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; + +import org.junit.Test; import org.hibernate.metamodel.MetadataSources; @@ -31,6 +33,7 @@ import org.hibernate.metamodel.MetadataSources; * @author Hardy Ferentschik */ public class BasicAnnotationBindingTests extends AbstractBasicBindingTests { + @Override public void addSourcesForSimpleEntityBinding(MetadataSources sources) { sources.addAnnotatedClass( SimpleEntity.class ); @@ -43,7 +46,7 @@ public class BasicAnnotationBindingTests extends AbstractBasicBindingTests { @Override public void addSourcesForManyToOne(MetadataSources sources) { - sources.addAnnotatedClass( ManyToOneEntity.class ); + sources.addAnnotatedClass( EntityWithManyToOnes.class ); } @Override @@ -51,4 +54,9 @@ public class BasicAnnotationBindingTests extends AbstractBasicBindingTests { sources.addAnnotatedClass( SimpleEntityWithSimpleComponent.class ); sources.addAnnotatedClass( SimpleEntityWithSimpleComponent.SimpleComponent.class ); } + + @Test + public void testEntityWithManyToOneMapping() { + super.testEntityWithManyToOneMapping( "simpleEntity_id"); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java similarity index 73% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java index 7f2b63ae8c..1440769cf0 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.junit.Test; @@ -33,24 +33,29 @@ import org.hibernate.metamodel.MetadataSources; * @author Steve Ebersole */ public class BasicHbmBindingTests extends AbstractBasicBindingTests { + + @Override public void addSourcesForSimpleEntityBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleEntity.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml" ); } + @Override public void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml" ); } + @Override public void addSourcesForManyToOne(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml" ); } + @Override public void addSourcesForComponentBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml" ); } @Test - public void testSimpleEntityWithSimpleComponentMapping() { - super.testSimpleEntityWithSimpleComponentMapping(); + public void testEntityWithManyToOneMapping() { + super.testEntityWithManyToOneMapping( "simpleEntity" ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java similarity index 70% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java index 709d769e20..99debcceba 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java @@ -21,30 +21,32 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.Id; +import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; /** * @author Gail Badner */ @Entity -public class ManyToOneEntity { - @Id +public class EntityWithManyToOnes { private Long id; private String theName; - @ManyToOne SimpleEntity simpleEntity; + SimpleEntity simpleEntityFromPropertyRef; - public ManyToOneEntity() { + public EntityWithManyToOnes() { } - public ManyToOneEntity(String name) { + public EntityWithManyToOnes(String name) { this.theName = name; } + @Id public Long getId() { return id; } @@ -61,6 +63,8 @@ public class ManyToOneEntity { this.theName = name; } + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) public SimpleEntity getSimpleEntity() { return simpleEntity; } @@ -69,13 +73,24 @@ public class ManyToOneEntity { this.simpleEntity = simpleEntity; } + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "simplename", referencedColumnName = "name") + public SimpleEntity getSimpleEntityFromPropertyRef() { + return simpleEntityFromPropertyRef; + } + + public void setSimpleEntityFromPropertyRef(SimpleEntity simpleEntityFromPropertyRef) { + this.simpleEntityFromPropertyRef = simpleEntityFromPropertyRef; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append( "EntityWithManyToOne" ); + sb.append( "EntityWithManyToOnes" ); sb.append( "{id=" ).append( id ); sb.append( ", theName='" ).append( theName ).append( '\'' ); sb.append( ", simpleEntity=" ).append( simpleEntity ); + sb.append( ", simpleEntityFromPropertyRef=" ).append( simpleEntityFromPropertyRef ); sb.append( '}' ); return sb.toString(); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java similarity index 61% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java index af2001320b..fc75b9dac4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,31 +21,31 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; -import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.ManyToMany; /** * @author Gail Badner - * @author Steve Ebersole */ @Entity -public class EntityWithBasicCollections { +public class EntityWithUnidirectionalManyToMany { private Long id; private String name; - private Collection theBag = new ArrayList(); - private Set theSet = new HashSet(); + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private Collection thePropertyRefBag = new ArrayList(); - public EntityWithBasicCollections() { + public EntityWithUnidirectionalManyToMany() { } - public EntityWithBasicCollections(String name) { + public EntityWithUnidirectionalManyToMany(String name) { this.name = name; } @@ -66,21 +66,30 @@ public class EntityWithBasicCollections { this.name = name; } - @ElementCollection - public Collection getTheBag() { + @ManyToMany + public Collection getTheBag() { return theBag; } - public void setTheBag(Collection theBag) { + public void setTheBag(Collection theBag) { this.theBag = theBag; } - @ElementCollection - public Set getTheSet() { + @ManyToMany + public Set getTheSet() { return theSet; } - public void setTheSet(Set theSet) { + public void setTheSet(Set theSet) { this.theSet = theSet; } + + @ManyToMany + public Collection getThePropertyRefSet() { + return thePropertyRefBag; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefBag = thePropertyRefSet; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java new file mode 100644 index 0000000000..518ca094cd --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class JoinedSubclassBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testJoinedSubclassBindingGeneratesForeignKey() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + sources.addAnnotatedClass( Sub.class ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + + EntityBinding entityBinding = metadata.getEntityBinding( Sub.class.getName() ); + assertTrue( entityBinding.getPrimaryTable().getForeignKeys().iterator().hasNext() ); + } + + @Entity + @Inheritance( strategy = InheritanceType.JOINED ) + public static class Base { + @Id + private Long id; + } + + @Entity + public static class Sub extends Base { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java index 227dc31cf4..8f987096f6 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java index 29c6c31491..ba08f5b844 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java index 1fb5ec9854..211eb48839 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Embeddable; import javax.persistence.Embedded; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java similarity index 62% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java index bf7c6d177c..7ccb0436b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java @@ -21,22 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.sql.Types; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.junit.Test; import org.hibernate.EntityMode; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.relational.Table; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Size; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.junit.Assert.assertSame; @@ -47,31 +52,53 @@ import static org.junit.Assert.assertSame; * @author Steve Ebersole */ public class SimpleValueBindingTests extends BaseUnitTestCase { - public static final Datatype BIGINT = new Datatype( Types.BIGINT, "BIGINT", Long.class ); - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); + public static final JdbcDataType BIGINT = new JdbcDataType( Types.BIGINT, "BIGINT", Long.class ); + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); @Test public void testBasicMiddleOutBuilding() { - Table table = new Table( new Schema( null, null ), "the_table" ); + final Identifier tableName = Identifier.toIdentifier( "the_table" ); + Table table = new Table( new Schema( null, null ), tableName, tableName ); + Column idColumn = table.locateOrCreateColumn( "id" ); + idColumn.setJdbcDataType( BIGINT ); + idColumn.setSize( Size.precision( 18, 0 ) ); + table.getPrimaryKey().addColumn( idColumn ); + table.getPrimaryKey().setName( "my_table_pk" ); + Entity entity = new Entity( "TheEntity", "NoSuchClass", makeJavaType( "NoSuchClass" ), null ); EntityBinding entityBinding = new EntityBinding( InheritanceType.NO_INHERITANCE, EntityMode.POJO ); entityBinding.setEntity( entity ); entityBinding.setPrimaryTable( table ); + List valueBindings = new ArrayList(); + valueBindings.add( + new RelationalValueBinding( + table, + idColumn, + true, + true + ) + ); SingularAttribute idAttribute = entity.createSingularAttribute( "id" ); - BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( idAttribute ); + BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( + idAttribute, + valueBindings, + "property", + true, + false, + SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID, + null, + PropertyGeneration.NEVER + ); attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); assertSame( idAttribute, attributeBinding.getAttribute() ); - entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( attributeBinding ); - - Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( BIGINT ); - idColumn.setSize( Size.precision( 18, 0 ) ); - table.getPrimaryKey().addColumn( idColumn ); - table.getPrimaryKey().setName( "my_table_pk" ); - //attributeBinding.setValue( idColumn ); + entityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier( + attributeBinding, + new IdentifierGeneratorDefinition( "assigned", "assigned", Collections.emptyMap() ), + "null" + ); } ValueHolder> makeJavaType(final String name) { diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java index 2c7eacd515..4458bbb85c 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java index 2deb0afe3f..42ede4038e 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,27 +21,29 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.hibernate.metamodel.MetadataSourceProcessingOrder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.internal.MetadataImpl; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; /** - * @author Steve Ebersole + * @author Gail Badner */ -public class BasicCollectionBindingTests extends BaseUnitTestCase { +public class UnidirectionalManyToManyBindingTests extends BaseUnitTestCase { private StandardServiceRegistryImpl serviceRegistry; @Before @@ -60,31 +62,27 @@ public class BasicCollectionBindingTests extends BaseUnitTestCase { // } @Test + @TestForIssue( jiraKey = "HHH-7436" ) public void testHbm() { doTest( MetadataSourceProcessingOrder.HBM_FIRST ); } private void doTest(MetadataSourceProcessingOrder processingOrder) { MetadataSources sources = new MetadataSources( serviceRegistry ); -// sources.addAnnotatedClass( EntityWithBasicCollections.class ); - sources.addResource( "org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml" ); MetadataImpl metadata = (MetadataImpl) sources.getMetadataBuilder().with( processingOrder ).build(); - final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithBasicCollections.class.getName() ); + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithUnidirectionalManyToMany.class.getName() ); + final EntityBinding simpleEntityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); assertNotNull( entityBinding ); - PluralAttributeBinding bagBinding = metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theBag" ); - assertNotNull( bagBinding ); - assertSame( bagBinding, entityBinding.locateAttributeBinding( "theBag" ) ); - assertNotNull( bagBinding.getCollectionTable() ); - assertEquals( CollectionElementNature.BASIC, bagBinding.getCollectionElement().getCollectionElementNature() ); - assertEquals( String.class.getName(), ( (BasicCollectionElement) bagBinding.getCollectionElement() ).getHibernateTypeDescriptor().getJavaTypeName() ); - - PluralAttributeBinding setBinding = metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theSet" ); - assertNotNull( setBinding ); - assertSame( setBinding, entityBinding.locateAttributeBinding( "theSet" ) ); - assertNotNull( setBinding.getCollectionTable() ); - assertEquals( CollectionElementNature.BASIC, setBinding.getCollectionElement().getCollectionElementNature() ); - assertEquals( String.class.getName(), ( (BasicCollectionElement) setBinding.getCollectionElement() ).getHibernateTypeDescriptor().getJavaTypeName() ); + assertEquals( + Identifier.toIdentifier( "SimpleEntity" ), + simpleEntityBinding.getPrimaryTable().getLogicalName() + ); + assertEquals( 1, simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() ); + Column simpleEntityIdColumn = simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ); + assertEquals( Identifier.toIdentifier( "id" ) , simpleEntityIdColumn.getColumnName() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java new file mode 100644 index 0000000000..4f90171e45 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.MetadataSources; + +/** + * "Unsaved" value tests annotation binding code + * + * @author Gail Badner + */ +public class UnsavedValueAnnotationsTests extends AbstractUnsavedValueTests { + + public void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } + + public void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithSequenceId.class ); + } + + public void addSourcesForDefaultUnsavedVersion(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithVersion.class ); + } + + public void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithTimestamp.class ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java new file mode 100644 index 0000000000..7936275918 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; + +import static org.junit.Assert.assertEquals; + +/** + * "Unsaved" value tests of {@code hbm.xml} binding code + * + * @author Gail Badner + */ +public class UnsavedValueHbmTests extends AbstractUnsavedValueTests { + + @Test + public void testAssignedSimpleIdNonDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + // unsaved-value was mapped as "any"; that should be used, regardless of ID generator. + assertEquals( "any", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testIncrementSimpleIdNonDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + // unsaved-value was mapped as "null"; that should be used, regardless of ID generator. + assertEquals( "null", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testNonDefaultUnsavedVersion() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithVersion.class.getName() ); + // version unsaved-value was mapped as "negative". + assertEquals( "negative", entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + @Test + public void testNonDefaultUnsavedTimestamp() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithTimestamp.class.getName() ); + // version unsaved-value was mapped as "null". + assertEquals( "null", entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + + public void addSourcesForDefaultSimpleIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForDefaultUnsavedVersion(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources) { + addDefaultSources( sources ); + } + + private void addDefaultSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml" ); + } + + private void addNonDefaultSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java new file mode 100644 index 0000000000..e2f852d318 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java @@ -0,0 +1,234 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.type.BagType; +import org.hibernate.type.CollectionType; +import org.hibernate.type.SetType; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + private MetadataImpl metadata; + + @Before + public void setUp() { + serviceRegistry = ( StandardServiceRegistryImpl ) new StandardServiceRegistryBuilder().build(); + MetadataSources metadataSources = new MetadataSources( serviceRegistry ); + addSources( metadataSources ); + metadata = ( MetadataImpl ) metadataSources.getMetadataBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + public abstract void addSources(MetadataSources sources); + + @Test + public void testBasicCollections() { + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithBasicCollections.class.getName() ); + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); + assertNotNull( entityBinding ); + + // TODO: this will fail until HHH-7121 is fixed + //assertTrue( entityBinding.getPrimaryTable().locateColumn( "`name`" ).isUnique() ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theBag" ), + BagType.class, + Collection.class, + String.class, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "EntityWithBasicCollections_theBag" ), + Identifier.toIdentifier( "owner_id" ), + FetchTiming.IMMEDIATE, + true + ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theSet" ), + SetType.class, + Set.class, + String.class, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "EntityWithBasicCollections_theSet" ), + Identifier.toIdentifier( "pid" ), + FetchTiming.EXTRA_LAZY, + true + ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + ".thePropertyRefSet" ), + SetType.class, + Set.class, + Integer.class, + ( SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ), + Identifier.toIdentifier( "EntityWithBasicCollections_thePropertyRefSet" ), + Identifier.toIdentifier( "pid" ), + FetchTiming.DELAYED, + false + ); + } + + private void assertBasicCollectionBinding( + EntityBinding collectionOwnerBinding, + PluralAttributeBinding collectionBinding, + Class expectedCollectionTypeClass, + Class expectedCollectionJavaClass, + Class expectedElementJavaClass, + SingularAttributeBinding expectedKeyTargetAttributeBinding, + Identifier expectedCollectionTableName, + Identifier expectedKeySourceColumnName, + FetchTiming expectedFetchTiming, + boolean expectedElementNullable) { + assertNotNull( collectionBinding ); + assertSame( + collectionBinding, + collectionOwnerBinding.locateAttributeBinding( collectionBinding.getAttribute().getName() ) + ); + assertSame( collectionOwnerBinding, collectionBinding.getContainer().seekEntityBinding() ); + + TableSpecification collectionTable = collectionBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertNotNull( collectionTable ); + assertEquals( expectedCollectionTableName, collectionTable.getLogicalName() ); + PluralAttributeKeyBinding keyBinding = collectionBinding.getPluralAttributeKeyBinding(); + assertSame( collectionBinding, keyBinding.getPluralAttributeBinding() ); + HibernateTypeDescriptor collectionHibernateTypeDescriptor = collectionBinding.getHibernateTypeDescriptor(); + assertNull( collectionHibernateTypeDescriptor.getExplicitTypeName() ); + assertEquals( expectedCollectionJavaClass.getName(), collectionHibernateTypeDescriptor.getJavaTypeName() ); + assertTrue( collectionHibernateTypeDescriptor.getTypeParameters().isEmpty() ); + assertTrue( expectedCollectionTypeClass.isInstance( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ) ); + assertFalse( collectionHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() ); + final String role = collectionBinding.getAttribute().getRole(); + assertEquals( + role, + collectionOwnerBinding.getEntity().getName() + "." + collectionBinding.getAttribute().getName() + ); + assertEquals( + role, + expectedCollectionTypeClass.cast( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() + ); + + assertEquals( expectedFetchTiming, collectionBinding.getFetchTiming() ); + assertEquals( expectedFetchTiming != FetchTiming.IMMEDIATE, collectionBinding.isLazy() ); + + List keyRelationalValueBindings = keyBinding.getRelationalValueBindings(); + assertNotNull( keyRelationalValueBindings ); + for( RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + assertSame( collectionTable, keyRelationalValueBinding.getTable() ); + } + assertEquals( 1, keyRelationalValueBindings.size() ); + assertEquals( 1, expectedKeyTargetAttributeBinding.getRelationalValueBindings().size() ); + Value expectedFKTargetValue = expectedKeyTargetAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertFalse( keyRelationalValueBindings.get( 0 ).isDerived() ); + assertEquals( expectedKeySourceColumnName, ( (Column) keyRelationalValueBindings.get( 0 ).getValue() ).getColumnName() ); + assertEquals( expectedFKTargetValue.getJdbcDataType(), keyRelationalValueBindings.get( 0 ).getValue().getJdbcDataType() ); + + assertFalse( keyBinding.isCascadeDeleteEnabled() ); + checkEquals( + expectedKeyTargetAttributeBinding.getHibernateTypeDescriptor(), + keyBinding.getHibernateTypeDescriptor() + ); + assertFalse( keyBinding.isInverse() ); + Assert.assertEquals( + PluralAttributeElementBinding.Nature.BASIC, + collectionBinding.getPluralAttributeElementBinding().getNature() + ); + assertEquals( + expectedElementJavaClass.getName(), + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeName() + ); + assertEquals( + expectedElementJavaClass, + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getResolvedTypeMapping().getReturnedClass() + + ); + assertEquals( 1, collectionBinding.getPluralAttributeElementBinding().getRelationalValueBindings().size() ); + RelationalValueBinding elementRelationalValueBinding = collectionBinding.getPluralAttributeElementBinding().getRelationalValueBindings().get( 0 ); + assertEquals( expectedElementNullable, elementRelationalValueBinding.isNullable() ); + if ( collectionBinding.getAttribute().getNature() == PluralAttribute.Nature.BAG ) { + assertEquals( 0, collectionTable.getPrimaryKey().getColumnSpan() ); + } + else if ( collectionBinding.getAttribute().getNature() == PluralAttribute.Nature.SET ) { + if ( expectedElementNullable ) { + assertEquals( 0, collectionTable.getPrimaryKey().getColumnSpan() ); + } + else { + assertEquals( 2, collectionTable.getPrimaryKey().getColumnSpan() ); + assertSame( keyRelationalValueBindings.get( 0 ).getValue(), collectionTable.getPrimaryKey().getColumns().get( 0 ) ); + assertSame( elementRelationalValueBinding.getValue(), collectionTable.getPrimaryKey().getColumns().get( 1 ) ); + } + } + } + + private void checkEquals(HibernateTypeDescriptor expected, HibernateTypeDescriptor actual) { + assertEquals( expected.getExplicitTypeName(), actual.getExplicitTypeName() ); + assertEquals( expected.getJavaTypeName(), actual.getJavaTypeName() ); + assertEquals( expected.getTypeParameters(), actual.getTypeParameters() ); + assertEquals( expected.getResolvedTypeMapping(), actual.getResolvedTypeMapping() ); + assertEquals( expected.isToOne(), actual.isToOne() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java similarity index 70% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java index a2b38037fd..30566b601c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java @@ -21,20 +21,22 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding.basiccollections; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; /** - * @author Steve Ebersole - * @author Gail Badner + * @author Hardy Ferentschik */ -public class OneToManyCollectionElement extends AbstractCollectionElement { - - OneToManyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); +public class AnnotationBasicCollectionBindingTests extends AbstractBasicCollectionBindingTests { + public void addSources(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithBasicCollections.class ); } - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.ONE_TO_MANY; + @Test + public void testBasicCollections() { + super.testBasicCollections(); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java new file mode 100644 index 0000000000..f384152429 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; + +/** + * @author Gail Badner + * @author Steve Ebersole + */ +@Entity +public class EntityWithBasicCollections { + private Long id; + private String name; + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private Set thePropertyRefSet = new HashSet(); + private List theList = new ArrayList(); + private Map theMap = new HashMap(); + + public EntityWithBasicCollections() { + } + + public EntityWithBasicCollections(String name) { + this.name = name; + } + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Column(unique = true) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @ElementCollection(fetch = FetchType.EAGER) + @JoinColumn(name = "owner_id") + public Collection getTheBag() { + return theBag; + } + + public void setTheBag(Collection theBag) { + this.theBag = theBag; + } + + @ElementCollection + @LazyCollection(value = LazyCollectionOption.EXTRA) + @JoinColumn(name = "pid") + public Set getTheSet() { + return theSet; + } + + public void setTheSet(Set theSet) { + this.theSet = theSet; + } + + @ElementCollection + @JoinColumn(name = "pid", referencedColumnName = "name") + @Column(name="property_ref_set_stuff", nullable = false) + public Set getThePropertyRefSet() { + return thePropertyRefSet; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefSet = thePropertyRefSet; + } + + @ElementCollection + public List getTheList() { + return theList; + } + + public void setTheList(List theList) { + this.theList = theList; + } + + @ElementCollection + public Map getTheMap() { + return theMap; + } + + public void setTheMap(Map theMap) { + this.theMap = theMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java similarity index 74% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java index 8fa01ef480..2dd51780b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java @@ -21,17 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.spi.binding.basiccollections; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; +import org.hibernate.metamodel.MetadataSources; /** * @author Hardy Ferentschik */ -public class SubclassEntitySourceImpl extends EntitySourceImpl implements SubclassEntitySource { - public SubclassEntitySourceImpl(EntityClass entityClass) { - super( entityClass ); +public class HbmBasicCollectionBindingTests extends AbstractBasicCollectionBindingTests { + public void addSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml" ); } } - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java new file mode 100644 index 0000000000..262be21639 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java @@ -0,0 +1,252 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.type.BagType; +import org.hibernate.type.CollectionType; +import org.hibernate.type.ListType; +import org.hibernate.type.MapType; +import org.hibernate.type.SetType; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * @author Gail Badner + */ +public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + private MetadataImpl metadata; + + @Before + public void setUp() { + serviceRegistry = ( StandardServiceRegistryImpl ) new StandardServiceRegistryBuilder().build(); + MetadataSources metadataSources = new MetadataSources( serviceRegistry ); + addSources( metadataSources ); + metadata = ( MetadataImpl ) metadataSources.getMetadataBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + public abstract void addSources(MetadataSources sources); + + @Test + public void testOneToMany() { + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithUnidirectionalOneToMany.class.getName() ); + final EntityBinding simpleEntityBinding = metadata.getEntityBinding( ReferencedEntity.class.getName() ); + assertNotNull( entityBinding ); + + assertEquals( + Identifier.toIdentifier( "ReferencedEntity" ), + simpleEntityBinding.getPrimaryTable().getLogicalName() + ); + assertEquals( 1, simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() ); + Column simpleEntityIdColumn = simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ); + assertEquals( Identifier.toIdentifier( "id" ), simpleEntityIdColumn.getColumnName() ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + ".theBag" ), + BagType.class, + Collection.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theBagOwner" ), + FetchTiming.DELAYED, + true + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + ".theSet" ), + SetType.class, + Set.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theSetOwner" ), + FetchTiming.IMMEDIATE, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + ".theList" ), + ListType.class, + List.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theListOwner" ), + FetchTiming.IMMEDIATE, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + ".theMap" ), + MapType.class, + Map.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theMapOwner" ), + FetchTiming.DELAYED, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + ".thePropertyRefSet" ), + BagType.class, + Collection.class, + simpleEntityBinding, + ( SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ), + Identifier.toIdentifier( "ownerName" ), + FetchTiming.EXTRA_LAZY, + false + ); + } + + private void checkResult( + EntityBinding collectionOwnerBinding, + PluralAttributeBinding collectionBinding, + Class expectedCollectionTypeClass, + Class expectedCollectionJavaType, + EntityBinding expectedElementEntityBinding, + SingularAttributeBinding expectedKeyTargetAttributeBinding, + Identifier expectedKeySourceColumnName, + FetchTiming expectedFetchTiming, + boolean expectedNullableCollectionKey) { + Assert.assertEquals( + PluralAttributeElementBinding.Nature.ONE_TO_MANY, + collectionBinding.getPluralAttributeElementBinding().getNature() + ); + assertSame( + collectionBinding, + collectionOwnerBinding.locateAttributeBinding( collectionBinding.getAttribute().getName() ) + ); + assertEquals( expectedFetchTiming, collectionBinding.getFetchTiming() ); + assertEquals( expectedFetchTiming != FetchTiming.IMMEDIATE, collectionBinding.isLazy() ); + + final String role = collectionBinding.getAttribute().getRole(); + assertEquals( + role, + collectionOwnerBinding.getEntity().getName() + "." + collectionBinding.getAttribute().getName() + ); + + final PluralAttributeKeyBinding keyBinding = collectionBinding.getPluralAttributeKeyBinding(); + assertSame( expectedElementEntityBinding.getPrimaryTable(), keyBinding.getCollectionTable() ); + assertSame( collectionBinding, keyBinding.getPluralAttributeBinding() ); + assertFalse( keyBinding.isInverse() ); + + final HibernateTypeDescriptor collectionHibernateTypeDescriptor = collectionBinding.getHibernateTypeDescriptor(); + assertNull( collectionHibernateTypeDescriptor.getExplicitTypeName() ); + assertEquals( expectedCollectionJavaType.getName(), collectionHibernateTypeDescriptor.getJavaTypeName() ); + assertTrue( collectionHibernateTypeDescriptor.getTypeParameters().isEmpty() ); + assertTrue( expectedCollectionTypeClass.isInstance( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ) ); + assertFalse( collectionHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() ); + assertEquals( + role, + expectedCollectionTypeClass.cast( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() + ); + + List keyRelationalValueBinding = keyBinding.getRelationalValueBindings(); + assertNotNull( keyRelationalValueBinding ); + assertFalse( keyBinding.isCascadeDeleteEnabled() ); + + assertSame( expectedElementEntityBinding.getPrimaryTable(), keyBinding.getCollectionTable() ); + assertEquals( 1, keyRelationalValueBinding.size() ); + + SingularAttributeBinding keySourceAttributeBinding = + ( SingularAttributeBinding ) expectedElementEntityBinding.locateAttributeBinding( + "_" + role + "BackRef" + ); + assertEquals( "expected "+keyBinding.getPluralAttributeBinding() +" has a " + expectedNullableCollectionKey +" collection key",expectedNullableCollectionKey, keyBinding.isNullable() ); + if ( keyBinding.isNullable() ) { + assertNull( keySourceAttributeBinding ); + } + else { + assertEquals( 1, keySourceAttributeBinding.getRelationalValueBindings().size() ); + Value keySourceValue = keySourceAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( keySourceValue instanceof Column ); + Column keySourceColumn = ( Column ) keySourceValue; + assertEquals( expectedKeySourceColumnName, keySourceColumn.getColumnName() ); + } + + assertEquals( 1, expectedKeyTargetAttributeBinding.getRelationalValueBindings().size() ); + assertEquals( + expectedKeyTargetAttributeBinding.getRelationalValueBindings().get( 0 ).getValue().getJdbcDataType(), + keyRelationalValueBinding.get( 0 ).getValue().getJdbcDataType() + ); + + checkEquals( + expectedKeyTargetAttributeBinding.getHibernateTypeDescriptor(), + keyBinding.getHibernateTypeDescriptor() + ); + + assertEquals( + expectedElementEntityBinding.getEntity().getName(), + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeName() + ); + } + + private void checkEquals(HibernateTypeDescriptor expected, HibernateTypeDescriptor actual) { + assertEquals( expected.getExplicitTypeName(), actual.getExplicitTypeName() ); + assertEquals( expected.getJavaTypeName(), actual.getJavaTypeName() ); + assertEquals( expected.getTypeParameters(), actual.getTypeParameters() ); + assertEquals( expected.getResolvedTypeMapping(), actual.getResolvedTypeMapping() ); + assertEquals( expected.isToOne(), actual.isToOne() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java similarity index 72% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java index 164e756af7..173c2694c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java @@ -21,20 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.spi.binding.onetomany; + +import org.hibernate.metamodel.MetadataSources; /** - * An emum for the type of id configuration for an entity. - * * @author Hardy Ferentschik */ -public enum IdType { - // single @Id annotation - SIMPLE, - // multiple @Id annotations - COMPOSED, - // @EmbeddedId annotation - EMBEDDED, - // does not contain any identifier mappings - NONE +public class AnnotationUnidirectionalOneToManyBindingTests extends AbstractUnidirectionalOneToManyBindingTests { + @Override + public void addSources(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithUnidirectionalOneToMany.class ); + sources.addAnnotatedClass( ReferencedEntity.class ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java new file mode 100644 index 0000000000..0ebfdc1016 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java @@ -0,0 +1,105 @@ +package org.hibernate.metamodel.spi.binding.onetomany; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; + +import org.hibernate.annotations.IndexColumn; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +/** + * @author Gail Badner + */ +@Entity +public class EntityWithUnidirectionalOneToMany { + private Long id; + private String name; + + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private List theList = new ArrayList(); + private Map theMap = new HashMap(); + private Collection thePropertyRefBag = new ArrayList(); + + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @OneToMany + @JoinColumn + public Collection getTheBag() { + return theBag; + } + + public void setTheBag(Collection theBag) { + this.theBag = theBag; + } + + @OneToMany(fetch = FetchType.EAGER) + @JoinColumn(name = "theSetOwner", nullable = false) + public Set getTheSet() { + return theSet; + } + + public void setTheSet(Set theSet) { + this.theSet = theSet; + } + + @OneToMany(fetch = FetchType.EAGER) + @JoinColumn(name = "theListOwner", nullable = false) + @IndexColumn( name = "list_index") + public List getTheList() { + return theList; + } + + public void setTheList(List theList) { + this.theList = theList; + } + + @OneToMany + @JoinColumn(name = "theMapOwner", nullable = false) + public Map getTheMap() { + return theMap; + } + + public void setTheMap(Map theMap) { + this.theMap = theMap; + } + + @OneToMany + @JoinColumn(name = "ownerName", nullable = false, referencedColumnName = "name") + @LazyCollection( LazyCollectionOption.EXTRA ) + public Collection getThePropertyRefSet() { + return thePropertyRefBag; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefBag = thePropertyRefSet; + } + +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java new file mode 100644 index 0000000000..f723da3fec --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import org.hibernate.metamodel.MetadataSources; + +/** + * @author Hardy Ferentschik + */ +public class HbmUnidirectionalOneToManyBindingTests extends AbstractUnidirectionalOneToManyBindingTests { + @Override + public void addSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java new file mode 100644 index 0000000000..9b57369e4a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Hardy Ferentschik + */ +@Entity +public class ReferencedEntity { + @Id + private Long id; + private String name; + + public ReferencedEntity() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java new file mode 100644 index 0000000000..bfc294ca73 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java @@ -0,0 +1,4 @@ +@GenericGenerator(name = "myGenerator", strategy = "sequence") +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.annotations.GenericGenerator; \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java new file mode 100644 index 0000000000..f1f2548f93 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java @@ -0,0 +1,187 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; + +/** + * Identity column tests of {@code hbm.xml} and annotation binding code + * + * @author Gail Badner + */ +public abstract class AbstractGeneratedIdColumnTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + protected ServiceRegistry basicServiceRegistry() { + return serviceRegistry; + } + + @Test + public void testNativeId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForNativeId( sources ); + // use old identifier generators so that strategy=GenerationType.AUTO maps to "native" ID generator + sources.getMetadataBuilder().withNewIdentifierGeneratorsEnabled( false ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithNativeId.class.getName() ); + assertEquals( + serviceRegistry.getService( JdbcServices.class ).getDialect().supportsIdentityColumns(), + entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() + ); + } + + @Test + public void testSequenceId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSequenceId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + assertEquals( false, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + @Test + public void testIdentityId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForIdentityId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithIdentityId.class.getName() ); + assertEquals( true, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + @Test + public void testAssignedId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForAssignedId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + assertEquals( false, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + public abstract void addSourcesForNativeId(MetadataSources sources); + + public abstract void addSourcesForSequenceId(MetadataSources sources); + + public abstract void addSourcesForIdentityId(MetadataSources sources); + + public abstract void addSourcesForAssignedId(MetadataSources sources); + + @Entity + public static class EntityWithNativeId { + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + public EntityWithNativeId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithSequenceId { + @Id + @GeneratedValue(strategy=GenerationType.SEQUENCE) + private Long id; + + public EntityWithSequenceId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithIdentityId { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + public EntityWithIdentityId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithAssignedId { + @Id + private Long id; + + public EntityWithAssignedId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java new file mode 100644 index 0000000000..af36f0273e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java @@ -0,0 +1,278 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.hibernate.dialect.Dialect; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * + * NOTE: the table number is automatically statically incremented every time + * a table is created. Because of this, it is impossible to predict how + * large the table number can get when running the suite of unit tests. + * Since we don't know how large the table number is, we don't know how + * many characters to allot in the resulting alias for the table number. + * + * To workaround this unknown, Dialect instances are created + * to control whether the test will need to truncate the column + * name when creating the alias. + * + * @author Gail Badner + */ +public class ColumnAliasTest extends BaseUnitTestCase { + + private Schema schema; + private Table table0; + private Table table1; + + @Before + public void setUp() { + schema = new Schema( null, null ); + table0 = new Table( + schema, + Identifier.toIdentifier( "table0" ), + Identifier.toIdentifier( "table0" ) + ); + table1 = new Table( + schema, + Identifier.toIdentifier( "table1" ), + Identifier.toIdentifier( "table1" ) + ); + } + + @After + public void tearDown() { + schema = null; + table0 = null; + table1 = null; + } + + @Test + public void testNoCharactersInNameNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "1" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`1`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + public void testNameStartsWithNonCharacterNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "1abc" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "1abc`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "_abc" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`_abc`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testNameStartsWithNonCharacterTruncation() { + Column column = table0.createColumn( "1" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + // create dialect with maximum alias length that will force truncation. + Dialect dialect = createDialect( expectedSuffix.length() + "column".length() - 1 ); + String nameTruncated = "column".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "column".length() ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix , alias ); + } + + @Test + public void testNameIncludingNonCharacter() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + + Column column = table0.createColumn( "a1" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + column = table0.createColumn( "`a1`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "a1b" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`a1b`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "ab1" ); + assertEquals( "ab" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`ab1`" ); + assertEquals( "ab" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "a1b2" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`a1b2`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testUseNameAsIs() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "abc" ); + assertEquals( "abc" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testUseNameAsIsWithMaxLength() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + String name = "abcdef"; + Column column = table0.createColumn( name ); + assertEquals( name + getExpectedSuffix( column, table0 ) , column.getAlias( dialect, table0 ) ); + } + + @Test + public void testQuotedNameAllCharactersNoTrucation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + + String name = "`abc`"; + Column column = table0.createColumn( name ); + assertEquals( column.getColumnName().getText() + getExpectedSuffix( column, table0 ), column.getAlias( + dialect, + table0 + ) ); + assertEquals( column.getColumnName().getText() + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + } + + @Test + public void testRowIdNameNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "RowId" ); + assertEquals( "RowId" + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`rowid`" ); + assertEquals( "rowid" + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + } + + @Test + public void testRowIdNameTruncation() { + Column column = table0.createColumn( "RowId" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + Dialect dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + String nameTruncated = "RowId".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "RowId".length() ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + nameTruncated = "RowId".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "column".length() ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix , alias ); + } + + @Test + public void testTruncatedName() { + Column column = table0.createColumn( "abcdefghijk" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + // Force max alias length to be less than the column name to that + // the name is not used as is (and the expected suffix will be used). + Dialect dialect = createDialect( column.getColumnName().getText().length() - 1 ); + + String nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() - 1 ); + nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + } + + @Test + public void testTruncatedQuotedName() { + Column column = table0.createColumn( "`abcdefghijk`" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + Dialect dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + String nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + } + + private Dialect createDialect(final int maxAliasLength) { + return new Dialect() { + public int getMaxAliasLength() { + return maxAliasLength; + } + }; + } + + private String getExpectedSuffix(Column column, TableSpecification table) { + return String.valueOf( column.getPosition() ) + "_" + String.valueOf( table.getTableNumber() ) + "_" ; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java new file mode 100644 index 0000000000..e429eaad26 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.testing.FailureExpected; + +/** + * Identity column tests of annotations binding code + * + * @author Gail Badner + */ +public class GeneratedIdColumnAnnotationsTests extends AbstractGeneratedIdColumnTests { + + @Test + @FailureExpected( jiraKey = "HHH-7400" ) + public void testNativeId() { + super.testNativeId(); + } + + @Override + public void addSourcesForNativeId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } + + @Override + public void addSourcesForSequenceId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithSequenceId.class ); + } + + @Override + public void addSourcesForIdentityId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithIdentityId.class ); + } + + @Override + public void addSourcesForAssignedId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java new file mode 100644 index 0000000000..bc40092d6f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.metamodel.MetadataSources; + +/** + * Identity column tests of {@code hbm.xml} binding code + * + * @author Gail Badner + */ +public class GeneratedIdColumnHbmTests extends AbstractGeneratedIdColumnTests { + private static String FILENAME = "org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml"; + + @Override + public void addSourcesForNativeId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForSequenceId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForIdentityId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForAssignedId(MetadataSources sources) { + sources.addResource( FILENAME ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java similarity index 74% rename from hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java index d974b8d942..145d7e4f7b 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java @@ -21,13 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.junit.Test; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.H2Dialect; -import org.hibernate.testing.env.TestingDatabaseInfo; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.junit.Assert.assertEquals; @@ -40,14 +39,14 @@ public class ObjectNameTests extends BaseUnitTestCase { @Test public void testMissingName() { try { - new ObjectName( (String)null, null, null ); + new ObjectName( null, (String)null, null ); fail(); } catch ( IllegalIdentifierException ignore ) { } try { - new ObjectName( "schema", "catalog", null ); + new ObjectName( "catalog", "schema", null ); fail(); } catch ( IllegalIdentifierException ignore ) { @@ -56,16 +55,16 @@ public class ObjectNameTests extends BaseUnitTestCase { @Test public void testIdentifierBuilding() { - Dialect dialect = TestingDatabaseInfo.DIALECT; - ObjectName on = new ObjectName( "schema", "catalog", "name" ); - assertEquals( "schema.catalog.name", on.toText() ); - on = new ObjectName( "schema", null, "name" ); + Dialect dialect = new H2Dialect(); + ObjectName on = new ObjectName( "catalog", "schema", "name" ); + assertEquals( "catalog.schema.name", on.toText() ); + on = new ObjectName( null, "schema", "name" ); assertEquals( "schema.name", on.toText() ); assertEquals( "schema.name", on.toText( dialect ) ); - on = new ObjectName( "`schema`", "`catalog`", "`name`" ); - assertEquals( "`schema`.`catalog`.`name`", on.toText() ); - assertEquals( "\"schema\".\"catalog\".\"name\"", on.toText( dialect ) ); - on = new ObjectName( "`schema`", null, "`name`" ); + on = new ObjectName( "`catalog`", "`schema`", "`name`" ); + assertEquals( "`catalog`.`schema`.`name`", on.toText() ); + assertEquals( "\"catalog\".\"schema\".\"name\"", on.toText( dialect ) ); + on = new ObjectName( null, "`schema`", "`name`" ); assertEquals( "`schema`.`name`", on.toText() ); assertEquals( "\"schema\".\"name\"", on.toText( dialect ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java similarity index 52% rename from hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java index 69fdc683b4..e9af2c9c3c 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.sql.Types; @@ -29,34 +29,34 @@ import org.junit.Test; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.H2Dialect; -import org.hibernate.testing.env.TestingDatabaseInfo; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; /** * @author Steve Ebersole */ public class TableManipulationTests extends BaseUnitTestCase { - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); - public static final Datatype INTEGER = new Datatype( Types.INTEGER, "INTEGER", Long.class ); + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); + public static final JdbcDataType INTEGER = new JdbcDataType( Types.INTEGER, "INTEGER", Long.class ); @Test public void testTableCreation() { Schema schema = new Schema( null, null ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); + Table table = schema.createTable( Identifier.toIdentifier( "my_table" ), Identifier.toIdentifier( "my_table" ) ); assertNull( table.getSchema().getName().getSchema() ); assertNull( table.getSchema().getName().getCatalog() ); - assertEquals( "my_table", table.getTableName().toString() ); + assertEquals( "my_table", table.getPhysicalName().toString() ); assertEquals( "my_table", table.getExportIdentifier() ); assertNull( table.getPrimaryKey().getName() ); assertFalse( table.values().iterator().hasNext() ); Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( INTEGER ); + idColumn.setJdbcDataType( INTEGER ); idColumn.setSize( Size.precision( 18, 0 ) ); table.getPrimaryKey().addColumn( idColumn ); table.getPrimaryKey().setName( "my_table_pk" ); @@ -64,22 +64,22 @@ public class TableManipulationTests extends BaseUnitTestCase { assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() ); Column col_1 = table.locateOrCreateColumn( "col_1" ); - col_1.setDatatype( VARCHAR ); + col_1.setJdbcDataType( VARCHAR ); col_1.setSize( Size.length( 512 ) ); for ( Value value : table.values() ) { assertTrue( Column.class.isInstance( value ) ); Column column = ( Column ) value; - if ( column.getColumnName().getName().equals( "id" ) ) { - assertEquals( INTEGER, column.getDatatype() ); + if ( column.getColumnName().getText().equals( "id" ) ) { + assertEquals( INTEGER, column.getJdbcDataType() ); assertEquals( 18, column.getSize().getPrecision() ); assertEquals( 0, column.getSize().getScale() ); assertEquals( -1, column.getSize().getLength() ); assertNull( column.getSize().getLobMultiplier() ); } else { - assertEquals( "col_1", column.getColumnName().getName() ); - assertEquals( VARCHAR, column.getDatatype() ); + assertEquals( "col_1", column.getColumnName().getText() ); + assertEquals( VARCHAR, column.getJdbcDataType() ); assertEquals( -1, column.getSize().getPrecision() ); assertEquals( -1, column.getSize().getScale() ); assertEquals( 512, column.getSize().getLength() ); @@ -88,65 +88,91 @@ public class TableManipulationTests extends BaseUnitTestCase { } } - @Test - public void testTableSpecificationCounter() { - Schema schema = new Schema( null, null ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); - InLineView inLineView = schema.createInLineView( "my_inlineview", "subselect" ); - InLineView otherInLineView = schema.createInLineView( "my_other_inlineview", "other subselect" ); - Table otherTable = schema.createTable( Identifier.toIdentifier( "my_other_table" ) ); - - int firstTableNumber = table.getTableNumber(); - assertEquals( firstTableNumber, table.getTableNumber() ); - assertEquals( firstTableNumber + 1, inLineView.getTableNumber() ); - assertEquals( firstTableNumber + 2, otherInLineView.getTableNumber() ); - assertEquals( firstTableNumber + 3, otherTable.getTableNumber() ); - } - @Test public void testBasicForeignKeyDefinition() { Schema schema = new Schema( null, null ); - Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ) ); + Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ), Identifier.toIdentifier( "BOOK" ) ); Column bookId = book.locateOrCreateColumn( "id" ); - bookId.setDatatype( INTEGER ); + bookId.setJdbcDataType( INTEGER ); bookId.setSize( Size.precision( 18, 0 ) ); book.getPrimaryKey().addColumn( bookId ); book.getPrimaryKey().setName( "BOOK_PK" ); - Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ) ); + Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ), Identifier.toIdentifier( "PAGE" ) ); Column pageId = page.locateOrCreateColumn( "id" ); - pageId.setDatatype( INTEGER ); + pageId.setJdbcDataType( INTEGER ); pageId.setSize( Size.precision( 18, 0 ) ); page.getPrimaryKey().addColumn( pageId ); page.getPrimaryKey().setName( "PAGE_PK" ); Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" ); - pageId.setDatatype( INTEGER ); + pageId.setJdbcDataType( INTEGER ); pageId.setSize( Size.precision( 18, 0 ) ); ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" ); pageBookFk.addColumn( pageBookId ); assertEquals( page, pageBookFk.getSourceTable() ); assertEquals( book, pageBookFk.getTargetTable() ); + + assertEquals( 1, pageBookFk.getColumnSpan() ); + assertEquals( 1, pageBookFk.getColumns().size() ); + assertEquals( 1, pageBookFk.getSourceColumns().size() ); + assertEquals( 1, pageBookFk.getTargetColumns().size() ); + assertSame( pageBookId, pageBookFk.getColumns().get( 0 ) ); + assertSame( pageBookId, pageBookFk.getSourceColumns().get( 0 ) ); + assertSame( bookId, pageBookFk.getTargetColumns().get( 0 ) ); } @Test public void testQualifiedName() { - Dialect dialect = TestingDatabaseInfo.DIALECT; - Schema schema = new Schema( Identifier.toIdentifier( "schema" ), Identifier.toIdentifier( "`catalog`" ) ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); - assertEquals( "my_table", table.getTableName().getName() ); - assertEquals( "my_table", table.getTableName().toString() ); - assertEquals( "schema.\"catalog\".my_table", table.getQualifiedName( dialect ) ); + Dialect dialect = new H2Dialect(); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( Identifier.toIdentifier( "my_table" ), Identifier.toIdentifier( "my_table" ) ); + assertEquals( "my_table", table.getPhysicalName().getText() ); + assertEquals( "my_table", table.getPhysicalName().toString() ); + assertEquals( "\"catalog\".schema.my_table", table.getQualifiedName( dialect ) ); - table = schema.createTable( Identifier.toIdentifier( "`my_table`" ) ); - assertEquals( "my_table", table.getTableName().getName() ); - assertEquals( "`my_table`", table.getTableName().toString() ); - assertEquals( "schema.\"catalog\".\"my_table\"", table.getQualifiedName( dialect ) ); + table = schema.createTable( Identifier.toIdentifier( "`my_table`" ), Identifier.toIdentifier( "`my_table`" ) ); + assertEquals( "my_table", table.getPhysicalName().getText() ); + assertEquals( "`my_table`", table.getPhysicalName().toString() ); + assertEquals( "\"catalog\".schema.\"my_table\"", table.getQualifiedName( dialect ) ); - InLineView inLineView = schema.createInLineView( "my_inlineview", "select ..." ); + InLineView inLineView = schema.createInLineView( Identifier.toIdentifier( "my_inlineview" ), "select ..." ); assertEquals( "( select ... )", inLineView.getQualifiedName( dialect ) ); } + + @Test + public void testTableIdentifier() { + Identifier tableIdentifier = Identifier.toIdentifier( "my_table" ); + assertEquals( "my_table", tableIdentifier.getText() ); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( tableIdentifier, tableIdentifier ); + assertSame( tableIdentifier, table.getPhysicalName() ); + assertSame( table, schema.locateTable( Identifier.toIdentifier( "my_table" ) ) ); + assertEquals( "my_table", table.getLogicalName().getText() ); + } + + @Test + public void testQuotedTableIdentifier() { + Identifier tableIdentifier = Identifier.toIdentifier( "`my_table`" ); + assertEquals( "my_table", tableIdentifier.getText() ); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( tableIdentifier, tableIdentifier ); + assertSame( tableIdentifier, table.getPhysicalName() ); + assertSame( table, schema.locateTable( Identifier.toIdentifier( "`my_table`" ) ) ); + assertEquals( "my_table", table.getLogicalName().getText() ); + assertTrue( table.getLogicalName().isQuoted() ); + assertNull( schema.locateTable( Identifier.toIdentifier( "my_table" ) ) ); + } + + @Test + public void testInLineViewLogicalName() { + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + InLineView view = schema.createInLineView( Identifier.toIdentifier( "my_view" ), "select" ); + assertEquals( "my_view", view.getLogicalName().getText() ); + assertEquals( "select", view.getSelect() ); + assertSame( view, schema.getInLineView( view.getLogicalName() ) ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java b/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java index 0d63c9ce08..752b035a72 100644 --- a/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java @@ -32,8 +32,10 @@ import org.junit.Test; import org.hibernate.SessionFactory; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.internal.SessionFactoryRegistry; import org.hibernate.internal.util.SerializationHelper; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.SerializationException; @@ -48,7 +50,11 @@ public class SessionFactorySerializationTest extends BaseUnitTestCase { public static final String NAME = "mySF"; @Test + @FailureExpectedWithNewMetamodel public void testNamedSessionFactorySerialization() throws Exception { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented for new metamodel." ); + } Configuration cfg = new Configuration() .setProperty( AvailableSettings.SESSION_FACTORY_NAME, NAME ) .setProperty( AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, "false" ); // default is true @@ -74,7 +80,12 @@ public class SessionFactorySerializationTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testUnNamedSessionFactorySerialization() throws Exception { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented for new metamodel." ); + } + // IMPL NOTE : this test is a control to testNamedSessionFactorySerialization // here, the test should fail based just on attempted uuid resolution Configuration cfg = new Configuration() diff --git a/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java index 82feda4e7e..cf86ab64c5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class AbstractComponentPropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "abstractembeddedcomponents/propertyref/Mappings.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java index 5f80af3240..71b24affc0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java @@ -40,6 +40,7 @@ import org.hibernate.Session; import org.hibernate.StaleStateException; import org.hibernate.Transaction; import org.hibernate.dialect.Oracle10gDialect; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.tool.hbm2ddl.SchemaExport; @@ -59,7 +60,15 @@ public class EntityTest extends BaseCoreFunctionalTestCase { @Test public void testLoad() throws Exception { //put an object in DB - assertEquals( "Flight", configuration().getClassMapping( Flight.class.getName() ).getTable().getName() ); + if ( isMetadataUsed() ) { + assertEquals( + "Flight", + metadata().getEntityBinding( Flight.class.getName() ).getPrimaryTableName() + ); + } + else { + assertEquals( "Flight", configuration().getClassMapping( Flight.class.getName() ).getTable().getName() ); + } Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -314,7 +323,16 @@ public class EntityTest extends BaseCoreFunctionalTestCase { @Test public void testEntityName() throws Exception { - assertEquals( "Corporation", configuration().getClassMapping( Company.class.getName() ).getTable().getName() ); + if ( isMetadataUsed() ) { + assertEquals( + "Corporation", + metadata().getEntityBinding( Company.class.getName() ).getPrimaryTableName() + ); + + } + else { + assertEquals( "Corporation", configuration().getClassMapping( Company.class.getName() ).getTable().getName() ); + } Session s = openSession(); Transaction tx = s.beginTransaction(); Company comp = new Company(); @@ -436,7 +454,12 @@ public class EntityTest extends BaseCoreFunctionalTestCase { } private SchemaExport schemaExport() { - return new SchemaExport( serviceRegistry(), configuration() ); + if ( isMetadataUsed() ) { + return new SchemaExport( metadata() ); + } + else { + return new SchemaExport( serviceRegistry(), configuration() ); + } } @After diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java index 229525fb5b..1a5aea1951 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java @@ -22,7 +22,7 @@ import javax.persistence.Embeddable; * @author Hardy Ferentschik */ @Embeddable -public class Closet extends Furniture { +public class Closet extends Woody { int numberOfDoors; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java index 1d81847cf2..9b99e7fdcb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java @@ -35,6 +35,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.property.BasicPropertyAccessor; import org.hibernate.property.DirectPropertyAccessor; import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.TestForIssue; import org.hibernate.tuple.entity.EntityTuplizer; @@ -65,6 +66,7 @@ public class AccessMappingTest { } @Test + @FailureExpectedWithNewMetamodel public void testInconsistentAnnotationPlacement() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Course1.class ); @@ -135,6 +137,7 @@ public class AccessMappingTest { } @Test + @FailureExpectedWithNewMetamodel public void testExplicitPropertyAccessAnnotationsOnField() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Course4.class ); @@ -176,6 +179,7 @@ public class AccessMappingTest { } @Test + @FailureExpectedWithNewMetamodel public void testExplicitPropertyAccessAnnotationsWithJpaStyleOverride() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); Class classUnderTest = Course5.class; @@ -216,6 +220,7 @@ public class AccessMappingTest { } @Test + @FailureExpectedWithNewMetamodel public void testDefaultPropertyAccessIsInherited() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Horse.class ); @@ -242,6 +247,7 @@ public class AccessMappingTest { @TestForIssue(jiraKey = "HHH-5004") @Test + @FailureExpectedWithNewMetamodel public void testAccessOnClassAndId() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Course8.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java index ad456887e0..b117e69261 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java @@ -43,6 +43,7 @@ public class Gardenshed Woody { private Integer id; private String brand; + @Access(javax.persistence.AccessType.FIELD) public long floors; @Transient @@ -66,7 +67,6 @@ public class Gardenshed // These 2 functions should not return in Hibernate, but the value should come from the field "floors" - @Access(javax.persistence.AccessType.FIELD) public long getFloors() { return this.floors + 2; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java index cd3c0a021b..dc1a104e7b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java @@ -33,9 +33,11 @@ import org.junit.Assert; import org.junit.Test; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.property.BasicPropertyAccessor; import org.hibernate.property.DirectPropertyAccessor; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.tuple.entity.EntityTuplizer; @@ -45,6 +47,7 @@ import org.hibernate.tuple.entity.EntityTuplizer; * * @author Hardy Ferentschik */ +@FailureExpectedWithNewMetamodel public class XmlAccessTest extends BaseUnitTestCase { @Test public void testAccessOnBasicXmlElement() throws Exception { @@ -174,6 +177,9 @@ public class XmlAccessTest extends BaseUnitTestCase { } private SessionFactoryImplementor buildSessionFactory(List> classesUnderTest, List configFiles) { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } assert classesUnderTest != null; assert configFiles != null; Configuration cfg = new Configuration(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java index 148e49388e..ab7812b51c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java @@ -28,12 +28,14 @@ import org.junit.Test; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +@FailureExpectedWithNewMetamodel public class AnyTest extends BaseCoreFunctionalTestCase { @Test public void testDefaultAnyAssociation() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java index 68093b65b9..13fa190218 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java @@ -32,6 +32,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -40,6 +41,7 @@ import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class BeanValidationAutoTest extends BaseCoreFunctionalTestCase { @Test public void testListeners() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java index 110b6b3fd0..ae322e9195 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java @@ -33,6 +33,9 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertTrue; @@ -61,9 +64,23 @@ public class BeanValidationDisabledTest extends BaseCoreFunctionalTestCase { @Test public void testDDLDisabled() { - PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); - Column countryColumn = (Column) classMapping.getProperty( "country" ).getColumnIterator().next(); - assertTrue( "DDL constraints are applied", countryColumn.isNullable() ); + final boolean isNullable; + if ( isMetadataUsed() ) { + final EntityBinding entityBinding = metadata().getEntityBinding( Address.class.getName() ); + final SingularAttributeBinding attributeBinding = + (SingularAttributeBinding) entityBinding.locateAttributeBinding( "country" ); + + + final org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) attributeBinding.getValues().get( 0 ); + isNullable = column.isNullable(); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); + Column countryColumn = (Column) classMapping.getProperty( "country" ).getColumnIterator().next(); + isNullable = countryColumn.isNullable(); + } + assertTrue( "DDL constraints are applied", isNullable ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationGroupsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationGroupsTest.java index 26967e9853..3aed6585d5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationGroupsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationGroupsTest.java @@ -34,6 +34,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -42,6 +43,8 @@ import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel + public class BeanValidationGroupsTest extends BaseCoreFunctionalTestCase { @Test public void testListeners() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java index 912b508dc8..63452fc04f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java @@ -35,6 +35,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -43,6 +44,7 @@ import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class BeanValidationProvidedFactoryTest extends BaseCoreFunctionalTestCase { @Test public void testListeners() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java index 4500f434e5..9345deba6c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java @@ -29,6 +29,11 @@ import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -44,58 +49,110 @@ import static org.junit.Assert.assertTrue; */ public class DDLTest extends BaseCoreFunctionalTestCase { @Test + @FailureExpectedWithNewMetamodel public void testBasicDDL() { - PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); - Column stateColumn = (Column) classMapping.getProperty( "state" ).getColumnIterator().next(); - assertEquals( stateColumn.getLength(), 3 ); - Column zipColumn = (Column) classMapping.getProperty( "zip" ).getColumnIterator().next(); - assertEquals( zipColumn.getLength(), 5 ); - assertFalse( zipColumn.isNullable() ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column stateColumn = SchemaUtil.getColumn( Address.class, "state", metadata() ); + assertEquals( stateColumn.getSize().getLength(), 3 ); + org.hibernate.metamodel.spi.relational.Column zipColumn = SchemaUtil.getColumn( Address.class, "zip", metadata() ); + assertEquals( zipColumn.getSize().getLength(), 5 ); + assertFalse( zipColumn.isNullable() ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); + Column stateColumn = (Column) classMapping.getProperty( "state" ).getColumnIterator().next(); + assertEquals( stateColumn.getLength(), 3 ); + Column zipColumn = (Column) classMapping.getProperty( "zip" ).getColumnIterator().next(); + assertEquals( zipColumn.getLength(), 5 ); + assertFalse( zipColumn.isNullable() ); + } } @Test + @FailureExpectedWithNewMetamodel public void testApplyOnIdColumn() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Column serialColumn = (Column) classMapping.getIdentifierProperty().getColumnIterator().next(); - assertEquals( "Validator annotation not applied on ids", 2, serialColumn.getLength() ); + if ( isMetadataUsed() ) { + PrimaryKey id = SchemaUtil.getPrimaryKey( Tv.class, metadata() ); + assertEquals( "Validator annotation not applied on ids", 2, + id.getColumns().get( 0 ).getSize().getLength() ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); + Column serialColumn = (Column) classMapping.getIdentifierProperty().getColumnIterator().next(); + assertEquals( "Validator annotation not applied on ids", 2, serialColumn.getLength() ); + } } @Test @TestForIssue( jiraKey = "HHH-5281" ) + @FailureExpectedWithNewMetamodel public void testLengthConstraint() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Column modelColumn = (Column) classMapping.getProperty( "model" ).getColumnIterator().next(); - assertEquals( modelColumn.getLength(), 5 ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column column = SchemaUtil.getColumn( Tv.class, "model", metadata() ); + assertEquals( column.getSize().getLength(), 5 ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); + Column modelColumn = (Column) classMapping.getProperty( "model" ).getColumnIterator().next(); + assertEquals( modelColumn.getLength(), 5 ); + } } @Test + @FailureExpectedWithNewMetamodel public void testApplyOnManyToOne() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( TvOwner.class.getName() ); - Column serialColumn = (Column) classMapping.getProperty( "tv" ).getColumnIterator().next(); - assertEquals( "Validator annotations not applied on associations", false, serialColumn.isNullable() ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column column = SchemaUtil.getColumn( TvOwner.class, "tv_serial", metadata() ); + assertEquals( "Validator annotations not applied on associations", false, column.isNullable() ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( TvOwner.class.getName() ); + Column serialColumn = (Column) classMapping.getProperty( "tv" ).getColumnIterator().next(); + assertEquals( "Validator annotations not applied on associations", false, serialColumn.isNullable() ); + } } @Test public void testSingleTableAvoidNotNull() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Rock.class.getName() ); - Column serialColumn = (Column) classMapping.getProperty( "bit" ).getColumnIterator().next(); - assertTrue( "Notnull should not be applied on single tables", serialColumn.isNullable() ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column column = SchemaUtil.getColumn( Rock.class, "bit", metadata() ); + assertTrue( "Notnull should not be applied on single tables", column.isNullable() ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Rock.class.getName() ); + Column serialColumn = (Column) classMapping.getProperty( "bit" ).getColumnIterator().next(); + assertTrue( "Notnull should not be applied on single tables", serialColumn.isNullable() ); + } } @Test + @FailureExpectedWithNewMetamodel public void testNotNullOnlyAppliedIfEmbeddedIsNotNullItself() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Property property = classMapping.getProperty( "tuner.frequency" ); - Column serialColumn = (Column) property.getColumnIterator().next(); - assertEquals( - "Validator annotations are applied on tuner as it is @NotNull", false, serialColumn.isNullable() - ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column column = SchemaUtil.getColumn( Tv.class, "frequency", metadata() ); + assertEquals( + "Validator annotations are applied on tuner as it is @NotNull", false, column.isNullable() + ); - property = classMapping.getProperty( "recorder.time" ); - serialColumn = (Column) property.getColumnIterator().next(); - assertEquals( - "Validator annotations are applied on tuner as it is @NotNull", true, serialColumn.isNullable() - ); + column = SchemaUtil.getColumn( Tv.class, "`time`", metadata() ); + assertEquals( + "Validator annotations were not applied on recorder", true, column.isNullable() + ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); + Property property = classMapping.getProperty( "tuner.frequency" ); + Column serialColumn = (Column) property.getColumnIterator().next(); + assertEquals( + "Validator annotations are applied on tuner as it is @NotNull", false, serialColumn.isNullable() + ); + + property = classMapping.getProperty( "recorder.time" ); + serialColumn = (Column) property.getColumnIterator().next(); + assertEquals( + "Validator annotations are applied on tuner as it is @NotNull", true, serialColumn.isNullable() + ); + } } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java index 252efbb25b..4b37b04245 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java @@ -34,6 +34,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -44,6 +45,7 @@ import static org.junit.Assert.fail; * @author Vladimir Klyushnikov * @author Hardy Ferentschik */ +@FailureExpectedWithNewMetamodel public class DDLWithoutCallbackTest extends BaseCoreFunctionalTestCase { @Test @RequiresDialectFeature(DialectChecks.SupportsColumnCheck.class) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java index b131277d9e..d19a22f239 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java @@ -33,6 +33,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -41,6 +42,7 @@ import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class HibernateTraversableResolverTest extends BaseCoreFunctionalTestCase { @Test public void testNonLazyAssocFieldWithConstraintsFailureExpected() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java index d277ae1e83..6c6e053071 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java @@ -35,6 +35,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Disjunction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -45,6 +46,7 @@ import static org.junit.Assert.assertNotNull; * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class CompositeIdTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneInCompositePk() throws Exception { @@ -364,9 +366,12 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[] { Parent.class, + ParentPk.class, Child.class, + ChildPk.class, Channel.class, TvMagazin.class, + TvMagazinPk.class, TvProgramIdClass.class, TvProgram.class, Presenter.class, @@ -376,6 +381,7 @@ public class CompositeIdTest extends BaseCoreFunctionalTestCase { OrderLinePk.class, LittleGenius.class, A.class, + AId.class, B.class, C.class, SomeEntity.class diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java index 70d2edd8f9..8c259bf234 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java @@ -2,11 +2,12 @@ package org.hibernate.test.annotations.cid; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ - +@Embeddable public class ParentPk implements Serializable { public String getFirstName() { return firstName; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java index 196173fb91..64356302bf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java @@ -36,7 +36,11 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.annotations.Country; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -51,11 +55,18 @@ import static org.junit.Assert.assertTrue; public class CollectionElementTest extends BaseCoreFunctionalTestCase { @Test public void testSimpleElement() throws Exception { - assertEquals( - "BoyFavoriteNumbers", - configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) - .getCollectionTable().getName() - ); + if ( isMetadataUsed() ) { + assertEquals( "BoyFavoriteNumbers", SchemaUtil.getCollection( Boy.class, "favoriteNumbers", metadata() ) + .getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().toString() ); + + } + else { + assertEquals( + "BoyFavoriteNumbers", + configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) + .getCollectionTable().getName() + ); + } Session s = openSession(); s.getTransaction().begin(); Boy boy = new Boy(); @@ -161,11 +172,19 @@ public class CollectionElementTest extends BaseCoreFunctionalTestCase { @Test public void testLazyCollectionofElements() throws Exception { - assertEquals( - "BoyFavoriteNumbers", - configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) - .getCollectionTable().getName() - ); + if ( isMetadataUsed() ) { + assertEquals( + "BoyFavoriteNumbers", SchemaUtil.getCollection( Boy.class, "favoriteNumbers", metadata() ) + .getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().toString() + ); + } + else { + assertEquals( + "BoyFavoriteNumbers", + configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) + .getCollectionTable().getName() + ); + } Session s = openSession(); s.getTransaction().begin(); Boy boy = new Boy(); @@ -270,23 +289,40 @@ public class CollectionElementTest extends BaseCoreFunctionalTestCase { } private void isCollectionColumnPresent(String collectionOwner, String propertyName, String columnName) { - final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); - final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); - boolean hasDefault = false; - while ( columnIterator.hasNext() ) { - Column column = (Column) columnIterator.next(); - if ( columnName.equals( column.getName() ) ) hasDefault = true; + if ( isMetadataUsed() ) { + final EntityBinding entityBinding = metadata().getEntityBinding( collectionOwner ); + final PluralAttributeBinding binding = (PluralAttributeBinding) entityBinding.locateAttributeBinding( propertyName ); + final TableSpecification table = binding.getPluralAttributeKeyBinding().getCollectionTable(); + + boolean hasColumn = table.locateColumn( propertyName ) != null; + assertTrue( "Could not find " + columnName, hasColumn ); + } + else { + final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); + final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); + boolean hasDefault = false; + while ( columnIterator.hasNext() ) { + Column column = (Column) columnIterator.next(); + if ( columnName.equals( column.getName() ) ) hasDefault = true; + } + assertTrue( "Could not find " + columnName, hasDefault ); } - assertTrue( "Could not find " + columnName, hasDefault ); } @Override protected Class[] getAnnotatedClasses() { return new Class[] { Boy.class, + Toy.class, + Brand.class, Country.class, + CountryAttitude.class, TestCourse.class, - Matrix.class + Matrix.class, + LocalizedString.class, + Toy.class, + CountryAttitude.class, + Brand.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java index 1c5609cd3c..4832581e5e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java @@ -26,6 +26,7 @@ package org.hibernate.test.annotations.collectionelement; import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.Id; @@ -55,7 +56,7 @@ public class EntityWithAnElementCollection { @ElementCollection // HHH-7732 -- "EntityWithAnElementCollection_someStrings" is too long for Oracle. - @JoinTable( + @CollectionTable( name = "SomeStrings", joinColumns = @JoinColumn( name = "EWAEC_ID") ) public Set getSomeStrings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java index 9ae1d29f6c..03ce6f6bc9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java @@ -45,17 +45,14 @@ public class OrderByTest extends BaseCoreFunctionalTestCase { Widgets widget = new Widgets(); widget.setName("hammer"); set.add(widget); - s.persist(widget); widget = new Widgets(); widget.setName("axel"); set.add(widget); - s.persist(widget); widget = new Widgets(); widget.setName("screwdriver"); set.add(widget); - s.persist(widget); p.setWidgets(set); s.persist(p); @@ -129,8 +126,10 @@ public class OrderByTest extends BaseCoreFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[] { Products.class, - Widgets.class, - BugSystem.class + BugSystem.class, + Bug.class, + Person.class, + Widgets.class }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java index b888a85bbb..5c5cc73d97 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java @@ -1,12 +1,9 @@ package org.hibernate.test.annotations.collectionelement; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import javax.persistence.Embeddable; -@Entity +@Embeddable public class Widgets { private String name; - private int id; public Widgets() { @@ -19,15 +16,4 @@ public class Widgets { public void setName(String name) { this.name = name; } - - @Id - @GeneratedValue - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java index e0d7502dbc..b0dd61e03f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java @@ -26,6 +26,7 @@ package org.hibernate.test.annotations.collectionelement.indexedCollection; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -33,6 +34,7 @@ import static org.junit.Assert.assertEquals; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class IndexedCollectionOfElementsTest extends BaseCoreFunctionalTestCase { @Test public void testIndexedCollectionOfElements() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java index 7c93ecd4fc..fecedea892 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java @@ -2,6 +2,7 @@ package org.hibernate.test.annotations.collectionelement.indexedCollection; import java.util.ArrayList; import java.util.List; +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; @@ -22,7 +23,7 @@ import org.hibernate.annotations.Type; public class Sale { @Id @GeneratedValue private Integer id; @ElementCollection - @JoinTable( + @CollectionTable( name = "contact", joinColumns = @JoinColumn(name = "n_key_person")) @CollectionId( diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java index 32176d73d9..1d3634540a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java @@ -23,12 +23,12 @@ */ package org.hibernate.test.annotations.collectionelement.ordered; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.OrderBy; import java.util.HashSet; @@ -75,7 +75,7 @@ public class Person { @ElementCollection @JoinColumn - @JoinTable(name = "T_NICKNAMES_A") + @CollectionTable(name = "T_NICKNAMES_A") @OrderBy // testing default @OrderBy mapping public Set getNickNamesAscendingNaturalSort() { return nickNamesAscendingNaturalSort; @@ -87,7 +87,7 @@ public class Person { @ElementCollection @JoinColumn - @JoinTable(name = "T_NICKNAMES_D") + @CollectionTable(name = "T_NICKNAMES_D") @OrderBy( "desc" ) public Set getNickNamesDescendingNaturalSort() { return nickNamesDescendingNaturalSort; @@ -101,7 +101,7 @@ public class Person { @ElementCollection @JoinColumn @OrderBy - @JoinTable(name = "T_ADDRESS_A") + @CollectionTable(name = "T_ADDRESS_A") public Set

getAddressesAscendingNaturalSort() { return addressesAscendingNaturalSort; } @@ -113,7 +113,7 @@ public class Person { @ElementCollection @JoinColumn @OrderBy( "desc" ) - @JoinTable(name = "T_ADDRESS_D") + @CollectionTable(name = "T_ADDRESS_D") public Set
getAddressesDescendingNaturalSort() { return addressesDescendingNaturalSort; } @@ -125,7 +125,7 @@ public class Person { @ElementCollection @JoinColumn @OrderBy( "city" ) - @JoinTable(name = "T_ADD_CITY_A") + @CollectionTable(name = "T_ADD_CITY_A") public Set
getAddressesCityAscendingSort() { return addressesCityAscendingSort; } @@ -137,7 +137,7 @@ public class Person { @ElementCollection @JoinColumn @OrderBy( "city desc" ) - @JoinTable(name = "T_ADD_CITY_D") + @CollectionTable(name = "T_ADD_CITY_D") public Set
getAddressesCityDescendingSort() { return addressesCityDescendingSort; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java index f6320eb244..b5fa716614 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java @@ -16,12 +16,12 @@ * limitations under the License. */ package org.hibernate.test.annotations.derivedidentities; +import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.OneToOne; -import org.hibernate.annotations.Entity; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java index 334857d80e..827faa1408 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java @@ -40,8 +40,14 @@ import static org.junit.Assert.assertTrue; public class DerivedIdentityWithBidirectionalAssociationTest extends BaseCoreFunctionalTestCase { @Test public void testBidirectionalAssociation() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( !SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( !SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); + assertTrue( !SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + } Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java index 9ae6942783..7c0c336923 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,12 +40,18 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", configuration() ) ); - + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", configuration() ) ); + } Session s = openSession(); s.getTransaction().begin(); Employee e = new Employee( 1L, "Emmanuel", "Manu" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java index 351fb57323..ad8bf1e66b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,11 +36,18 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + } Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; @@ -62,8 +70,14 @@ public class DerivedIdentitySimpleParentEmbeddedIdDepTest extends BaseCoreFuncti @Test public void testOneToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "ExclusiveDependent", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "ExclusiveDependent", "empPK", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "ExclusiveDependent", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "ExclusiveDependent", "empPK", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "ExclusiveDependent", "FK", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "ExclusiveDependent", "empPK", configuration() ) ); + } Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; @@ -88,6 +102,7 @@ public class DerivedIdentitySimpleParentEmbeddedIdDepTest extends BaseCoreFuncti protected Class[] getAnnotatedClasses() { return new Class[] { Dependent.class, + DependentId.class, Employee.class, ExclusiveDependent.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java index 5a1741b77c..989ebd1e29 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -38,6 +39,7 @@ import static org.junit.Assert.assertEquals; * * @author Stale W. Pedersen */ +@FailureExpectedWithNewMetamodel public class IdMapManyToOneSpecjTest extends BaseCoreFunctionalTestCase { public IdMapManyToOneSpecjTest() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java index 52b2266560..192a2715ae 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java @@ -32,9 +32,11 @@ import junit.framework.Assert; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.Item; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +@FailureExpectedWithNewMetamodel // i think the whole SpecJ "partially generated id" thing causes problems in the new code public class CompositeKeyDeleteTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java index ae0b5c701d..398268142b 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -40,6 +41,7 @@ import static org.junit.Assert.assertTrue; * * @author Stale W. Pedersen */ +@FailureExpectedWithNewMetamodel public class IdClassGeneratedValueManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testComplexIdClass() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java index 066e91528f..6fac2c67e3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java @@ -38,8 +38,14 @@ import static org.junit.Assert.assertTrue; public class DerivedIdentitySimpleParentEmbeddedDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + } Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java index 13ddd694f5..5b84d672bb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java @@ -1,9 +1,14 @@ package org.hibernate.test.annotations.derivedidentities.e2.a; +import java.util.List; + import org.junit.Test; import org.hibernate.Session; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -13,14 +18,30 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testManytoOne() { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + final TableSpecification dependentTable = SchemaUtil.getTable( "Dependent", metadata() ); + final List dependentPkColumns = dependentTable.getPrimaryKey().getColumns(); + assertEquals( 3, dependentPkColumns.size() ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "name" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK1" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK2" ) ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + } Employee e = new Employee(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java index e99e48a5f6..5007e0694d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -13,14 +14,24 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_firstName", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_lastName", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_firstName", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_lastName", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_firstName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_lastName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + } Employee e = new Employee(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; @@ -45,8 +56,8 @@ public class DerivedIdentityIdClassParentEmbeddedIdDepTest extends BaseCoreFunct protected Class[] getAnnotatedClasses() { return new Class[] { Employee.class, - Dependent.class - + Dependent.class, + DependentId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java index 84e78a8700..7eaf490cfa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,14 +37,24 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentIdClassTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + } Employee e = new Employee(); e.empId = new EmployeeId(); e.empId.firstName = "Emmanuel"; @@ -76,7 +87,8 @@ public class DerivedIdentityEmbeddedIdParentIdClassTest extends BaseCoreFunctio protected Class[] getAnnotatedClasses() { return new Class[] { Dependent.class, - Employee.class + Employee.class, + EmployeeId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java index 7308e99a34..532865e221 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,14 +37,24 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + } Employee e = new Employee(); e.empId = new EmployeeId(); e.empId.firstName = "Emmanuel"; @@ -67,6 +78,6 @@ public class DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest extends BaseCoreFu @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Dependent.class, Employee.class }; + return new Class[] { Dependent.class, DependentId.class, Employee.class, EmployeeId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java index 634a6b317a..6766dd4378 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java @@ -41,8 +41,14 @@ import static org.junit.Assert.assertTrue; public class DerivedIdentitySimpleParentSimpleDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + } Session s = openSession(); s.getTransaction().begin(); @@ -73,8 +79,14 @@ public class DerivedIdentitySimpleParentSimpleDepTest extends BaseCoreFunctional @Test public void testManyToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + } Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java index 5e877a2185..662dc5eb63 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,11 +40,18 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + } Person e = new Person(); e.ssn = "aaa"; Session s = openSession( ); @@ -68,8 +76,14 @@ public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends BaseCoreFunc @Test public void testManyToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "FK", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + } Person e = new Person(); e.ssn = "aaa"; Session s = openSession( ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java index 8628b0b4ef..09d165873b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,15 +36,23 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentSameIdTypeIdClassDepTest extends BaseCoreFunctionalTestCase { private static final String FIRST_NAME = "Emmanuel"; private static final String LAST_NAME = "Bernard"; @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + } Session s = openSession(); s.getTransaction().begin(); @@ -71,9 +80,16 @@ public class DerivedIdentityIdClassParentSameIdTypeIdClassDepTest extends BaseCo @Test public void testTckLikeBehavior() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + } Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java index daf0e5758c..a701a3bb7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,21 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + } + Person e = new Person(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; @@ -62,7 +72,8 @@ public class DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest extends Bas protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java index e3d1f9256e..fb08a88d54 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java @@ -1,9 +1,11 @@ package org.hibernate.test.annotations.derivedidentities.e5.b; import java.io.Serializable; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ +@Embeddable public class PersonId implements Serializable { String firstName; String lastName; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java index f6757b38a0..79ed501a42 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,10 +36,17 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ForeignGeneratorViaMapsIdTest extends BaseCoreFunctionalTestCase { @Test public void testForeignGenerator() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "patient_id", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "patient_id", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "patient_id", configuration() ) ); + } + Person e = new Person(); Session s = openSession( ); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java index f848e1b259..abdda7fbe6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,20 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + } Person e = new Person(); e.id = new PersonId(); e.id.firstName = "Emmanuel"; @@ -68,7 +77,8 @@ public class DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest extends Bas protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java index ff97c4b81a..c8080981b3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,20 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + } Person e = new Person(); e.id = new PersonId(); e.id.firstName = "Emmanuel"; @@ -66,7 +75,8 @@ public class DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest extends protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java index 651003e947..05b1c62861 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java @@ -26,7 +26,7 @@ package org.hibernate.test.annotations.embeddables; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java index 267d99f287..f76a33a0ea 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java @@ -37,6 +37,7 @@ import org.hibernate.Transaction; import org.hibernate.test.annotations.embedded.FloatLeg.RateIndex; import org.hibernate.test.annotations.embedded.Leg.Frequency; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -153,6 +154,7 @@ public class EmbeddedTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testEmbeddedSuperclass() { Session s; Transaction tx; @@ -190,6 +192,7 @@ public class EmbeddedTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testDottedProperty() { Session s; Transaction tx; @@ -405,12 +408,19 @@ public class EmbeddedTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testDefaultCollectionTable() throws Exception { //are the tables correct? - assertTrue( SchemaUtil.isTablePresent("WealthyPerson_vacationHomes", configuration() ) ); - assertTrue( SchemaUtil.isTablePresent("WealthyPerson_legacyVacationHomes", configuration() ) ); - assertTrue( SchemaUtil.isTablePresent("WelPers_VacHomes", configuration() ) ); - + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_vacationHomes", metadata() ) ); + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_legacyVacationHomes", metadata() ) ); + assertTrue( SchemaUtil.isTablePresent("WelPers_VacHomes", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_vacationHomes", configuration() ) ); + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_legacyVacationHomes", configuration() ) ); + assertTrue( SchemaUtil.isTablePresent("WelPers_VacHomes", configuration() ) ); + } //just to make sure, use the mapping Session s; Transaction tx; @@ -531,7 +541,17 @@ public class EmbeddedTest extends BaseCoreFunctionalTestCase { CorpType.class, Nationality.class, Manager.class, - FavoriteThings.class + FavoriteThings.class, + Address.class, + Country.class, + InternetFavorites.class, + FixedLeg.class, + FloatLeg.class, + Swap.class, + RegionalArticlePk.class, + LegalStructure.class, + Summary.class, + URLFavorite.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java index f018512d4e..8003f5110b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java @@ -1,15 +1,15 @@ package org.hibernate.test.annotations.embedded; import java.util.Collection; +import javax.persistence.ElementCollection; import javax.persistence.Embeddable; -import javax.persistence.Embedded; @Embeddable public class InternetFavorites { - @Embedded + @ElementCollection Collection links; - @Embedded + @ElementCollection Collection ideas; public Collection getIdeas() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java index 569ae8ab3e..91d7a26967 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java @@ -54,6 +54,6 @@ public class NestedEmbeddableAttributeOverrideTest extends BaseCoreFunctionalTes @Override protected Class[] getAnnotatedClasses() { - return new Class[] { EntityWithNestedEmbeddables.class }; + return new Class[] { EntityWithNestedEmbeddables.class, EmbeddableA.class, EmbeddableB.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java index 196b0d61e3..c9ef5c113a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java @@ -46,6 +46,7 @@ import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -99,6 +100,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase { @Test @RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class ) + @FailureExpectedWithNewMetamodel public void testVersioning() throws Exception { Forest forest = new Forest(); forest.setName( "Fontainebleau" ); @@ -461,6 +463,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase { * defined on a parent MappedSuperclass(s) */ @Test + @FailureExpectedWithNewMetamodel public void testInheritFiltersFromMappedSuperclass() throws Exception { Session s; Transaction tx; @@ -709,6 +712,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase { ZipCode.class, Flight.class, Name.class, + LastName.class, FormalLastName.class, Car.class, Peugot.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java index 5e81af1c68..ea9e0b4232 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java @@ -27,6 +27,7 @@ import org.hibernate.mapping.RootClass; import org.junit.Test; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -47,12 +48,27 @@ public class NewCustomEntityMappingAnnotationsTest extends BaseCoreFunctionalTes @Test public void testSameMappingValues() { - RootClass forest = (RootClass) configuration().getClassMapping( Forest.class.getName() ); - RootClass forest2 = (RootClass) configuration().getClassMapping( Forest2.class.getName() ); - assertEquals( forest.useDynamicInsert(), forest2.useDynamicInsert() ); - assertEquals( forest.useDynamicUpdate(), forest2.useDynamicUpdate() ); - assertEquals( forest.hasSelectBeforeUpdate(), forest2.hasSelectBeforeUpdate() ); - assertEquals( forest.getOptimisticLockStyle(), forest2.getOptimisticLockStyle() ); - assertEquals( forest.isExplicitPolymorphism(), forest2.isExplicitPolymorphism() ); + if ( isMetadataUsed() ) { + EntityBinding forest = metadata().getEntityBinding( Forest.class.getName() ); + EntityBinding forest2 = metadata().getEntityBinding( Forest2.class.getName() ); + assertEquals( forest.isDynamicInsert(), forest2.isDynamicInsert() ); + assertEquals( forest.isDynamicUpdate(), forest2.isDynamicUpdate() ); + assertEquals( forest.isSelectBeforeUpdate(), forest2.isSelectBeforeUpdate() ); + assertEquals( + forest.getHierarchyDetails().getOptimisticLockStyle(), + forest2.getHierarchyDetails().getOptimisticLockStyle() + ); + assertEquals( forest.isPolymorphic(), forest2.isPolymorphic() ); + + } + else { + RootClass forest = (RootClass) configuration().getClassMapping( Forest.class.getName() ); + RootClass forest2 = (RootClass) configuration().getClassMapping( Forest2.class.getName() ); + assertEquals( forest.useDynamicInsert(), forest2.useDynamicInsert() ); + assertEquals( forest.useDynamicUpdate(), forest2.useDynamicUpdate() ); + assertEquals( forest.hasSelectBeforeUpdate(), forest2.hasSelectBeforeUpdate() ); + assertEquals( forest.getOptimisticLockStyle(), forest2.getOptimisticLockStyle() ); + assertEquals( forest.isExplicitPolymorphism(), forest2.isExplicitPolymorphism() ); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java index cb044db75b..7b8146f388 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,6 +37,7 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class EntityNonEntityTest extends BaseCoreFunctionalTestCase { @Test public void testMix() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java index 6d5260d33b..6e1f59ba7d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java @@ -16,6 +16,8 @@ import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; import org.hibernate.test.annotations.enumerated.EntityEnum.Common; import org.hibernate.test.annotations.enumerated.EntityEnum.FirstLetter; import org.hibernate.test.annotations.enumerated.EntityEnum.LastNumber; @@ -36,33 +38,80 @@ public class EnumeratedTypeTest extends BaseCoreFunctionalTestCase { @Test public void testTypeDefinition() { - Configuration cfg = configuration(); - PersistentClass pc = cfg.getClassMapping( EntityEnum.class.getName() ); + if ( isMetadataUsed() ) { + EntityBinding binding = metadata().getEntityBinding( EntityEnum.class.getName() ); - // ordinal default of EnumType - Type ordinalEnum = pc.getProperty( "ordinal" ).getType(); - assertEquals( Common.class, ordinalEnum.getReturnedClass() ); - assertEquals( EnumType.class.getName(), ordinalEnum.getName() ); + // ordinal default of EnumType + HibernateTypeDescriptor ordinalEnum = binding + .locateAttributeBinding( "ordinal" ) + .getHibernateTypeDescriptor(); + assertEquals( Common.class, ordinalEnum.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), ordinalEnum.getExplicitTypeName() ); - // string defined by Enumerated(STRING) - Type stringEnum = pc.getProperty( "string" ).getType(); - assertEquals( Common.class, stringEnum.getReturnedClass() ); - assertEquals( EnumType.class.getName(), stringEnum.getName() ); + // string defined by Enumerated(STRING) + HibernateTypeDescriptor stringEnum = binding + .locateAttributeBinding( "string" ) + .getHibernateTypeDescriptor(); + assertEquals( Common.class, stringEnum.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), stringEnum.getExplicitTypeName() ); - // explicit defined by @Type - Type first = pc.getProperty( "firstLetter" ).getType(); - assertEquals( FirstLetter.class, first.getReturnedClass() ); - assertEquals( FirstLetterType.class.getName(), first.getName() ); + // explicit defined by @Type + HibernateTypeDescriptor first = binding + .locateAttributeBinding( "firstLetter" ) + .getHibernateTypeDescriptor(); + assertEquals( FirstLetter.class, first.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( FirstLetterType.class.getName(), first.getExplicitTypeName() ); - // implicit defined by @TypeDef in somewhere - Type last = pc.getProperty( "lastNumber" ).getType(); - assertEquals( LastNumber.class, last.getReturnedClass() ); - assertEquals( LastNumberType.class.getName(), last.getName() ); + // implicit defined by @TypeDef in somewhere + HibernateTypeDescriptor last = binding + .locateAttributeBinding( "lastNumber" ) + .getHibernateTypeDescriptor(); + assertEquals( LastNumber.class, last.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( LastNumberType.class.getName(), last.getExplicitTypeName() ); - // implicit defined by @TypeDef in anywhere, but overrided by Enumerated(STRING) - Type implicitOverrideExplicit = pc.getProperty( "explicitOverridingImplicit" ).getType(); - assertEquals( LastNumber.class, implicitOverrideExplicit.getReturnedClass() ); - assertEquals( EnumType.class.getName(), implicitOverrideExplicit.getName() ); + // implicit defined by @TypeDef in anywhere, but overrided by Enumerated(STRING) + HibernateTypeDescriptor implicitOverrideExplicit = binding + .locateAttributeBinding( "explicitOverridingImplicit" ) + .getHibernateTypeDescriptor(); + assertEquals( LastNumber.class, + implicitOverrideExplicit.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), + implicitOverrideExplicit.getExplicitTypeName() ); + } + else { + Configuration cfg = configuration(); + PersistentClass pc = cfg.getClassMapping( EntityEnum.class.getName() ); + + // ordinal default of EnumType + Type ordinalEnum = pc.getProperty( "ordinal" ).getType(); + assertEquals( Common.class, ordinalEnum.getReturnedClass() ); + assertEquals( EnumType.class.getName(), ordinalEnum.getName() ); + + // string defined by Enumerated(STRING) + Type stringEnum = pc.getProperty( "string" ).getType(); + assertEquals( Common.class, stringEnum.getReturnedClass() ); + assertEquals( EnumType.class.getName(), stringEnum.getName() ); + + // explicit defined by @Type + Type first = pc.getProperty( "firstLetter" ).getType(); + assertEquals( FirstLetter.class, first.getReturnedClass() ); + assertEquals( FirstLetterType.class.getName(), first.getName() ); + + // implicit defined by @TypeDef in somewhere + Type last = pc.getProperty( "lastNumber" ).getType(); + assertEquals( LastNumber.class, last.getReturnedClass() ); + assertEquals( LastNumberType.class.getName(), last.getName() ); + + // implicit defined by @TypeDef in anywhere, but overrided by Enumerated(STRING) + Type implicitOverrideExplicit = pc.getProperty( "explicitOverridingImplicit" ).getType(); + assertEquals( LastNumber.class, implicitOverrideExplicit.getReturnedClass() ); + assertEquals( EnumType.class.getName(), implicitOverrideExplicit.getName() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java index 0fee63658e..19c0a734be 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java @@ -23,6 +23,7 @@ */ package org.hibernate.test.annotations.enumerated.ormXml; +import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.type.CustomType; import org.hibernate.type.EnumType; import org.hibernate.type.Type; @@ -47,9 +48,19 @@ public class OrmXmlEnumTypeTest extends BaseCoreFunctionalTestCase { @Test public void testOrmXmlDefinedEnumType() { - Type bindingPropertyType = configuration().getClassMapping( BookWithOrmEnum.class.getName() ) - .getProperty( "bindingStringEnum" ) - .getType(); + final Type bindingPropertyType; + if ( isMetadataUsed() ) { + AttributeBinding attributeBinding = metadata().getEntityBinding( BookWithOrmEnum.class.getName() ) + .locateAttributeBinding( "bindingStringEnum" ); + bindingPropertyType = + attributeBinding.getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + else { + bindingPropertyType = configuration().getClassMapping( BookWithOrmEnum.class.getName() ) + .getProperty( "bindingStringEnum" ) + .getType(); + } CustomType customType = ExtraAssertions.assertTyping( CustomType.class, bindingPropertyType ); EnumType enumType = ExtraAssertions.assertTyping( EnumType.class, customType.getUserType() ); assertFalse( enumType.isOrdinal() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java index a0f1d8e10f..07b8871df0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java @@ -1,6 +1,7 @@ package org.hibernate.test.annotations.generics; import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Embedded; @@ -9,7 +10,6 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.Table; public class Classes { @@ -40,7 +40,7 @@ public class Classes { Long id; @ElementCollection - @JoinTable(name="PopularBook_Editions",joinColumns={@JoinColumn(name="PopularBook_id")}) + @CollectionTable(name="PopularBook_Editions",joinColumns={@JoinColumn(name="PopularBook_id")}) Set> editions = new HashSet>(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java index 936fe9b218..8eeed96e13 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java @@ -76,7 +76,8 @@ public class EmbeddedGenericsTest extends BaseCoreFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[]{ Classes.Book.class, - Classes.PopularBook.class + Classes.PopularBook.class, + Classes.Edition.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java index 1cb09fe6f9..4fb25797ad 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java @@ -81,6 +81,9 @@ public class GenericsTest extends BaseCoreFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[]{ Paper.class, + Stuff.class, + PricedStuff.class, + Item.class, PaperType.class, SomeGuy.class, Price.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java index 0ab1975070..c4b38df46b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java @@ -26,11 +26,13 @@ package org.hibernate.test.annotations.genericsinheritance; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class GenericsInheritanceTest extends BaseCoreFunctionalTestCase { @Test public void testMapping() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java index 34f2181615..366e24534f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java @@ -46,6 +46,7 @@ import org.hibernate.test.annotations.id.entities.Shoe; import org.hibernate.test.annotations.id.entities.SoundSystem; import org.hibernate.test.annotations.id.entities.Store; import org.hibernate.test.annotations.id.entities.Tree; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -327,9 +328,16 @@ public class IdTest extends BaseCoreFunctionalTestCase { @Test public void testColumnDefinition() { - Column idCol = (Column) configuration().getClassMapping(Ball.class.getName()) - .getIdentifierProperty().getValue().getColumnIterator().next(); - assertEquals( "ball_id", idCol.getName() ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column idCol = SchemaUtil.getPrimaryKey( Ball.class, metadata() ) + .getColumns().get( 0 ); + assertEquals( "ball_id", idCol.getColumnName().getText() ); + } + else { + Column idCol = (Column) configuration().getClassMapping(Ball.class.getName()) + .getIdentifierProperty().getValue().getColumnIterator().next(); + assertEquals( "ball_id", idCol.getName() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java index af9bee9c05..7d49331450 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java @@ -30,10 +30,12 @@ import org.jboss.logging.Logger; import org.junit.Test; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.test.annotations.id.entities.Bunny; import org.hibernate.test.annotations.id.entities.PointyTooth; import org.hibernate.test.annotations.id.entities.TwinkleToes; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -47,12 +49,17 @@ import static org.junit.Assert.fail; * @author Hardy Ferentschik */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class JoinColumnOverrideTest extends BaseUnitTestCase { private static final Logger log = Logger.getLogger( JoinColumnOverrideTest.class ); @Test @TestForIssue( jiraKey = "ANN-748" ) public void testBlownPrecision() throws Exception { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } + try { Configuration config = new Configuration(); config.addAnnotatedClass(Bunny.class); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java index 6c856ecd5e..1ef6ca9c8c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java @@ -23,6 +23,7 @@ */ package org.hibernate.test.annotations.id.sequences; +import org.junit.Assert; import org.junit.Test; import org.hibernate.Session; @@ -47,6 +48,7 @@ import org.hibernate.test.annotations.id.sequences.entities.Shoe; import org.hibernate.test.annotations.id.sequences.entities.SoundSystem; import org.hibernate.test.annotations.id.sequences.entities.Store; import org.hibernate.test.annotations.id.sequences.entities.Tree; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; @@ -314,9 +316,20 @@ public class IdTest extends BaseCoreFunctionalTestCase { @Test public void testColumnDefinition() { - Column idCol = ( Column ) configuration().getClassMapping( Ball.class.getName() ) - .getIdentifierProperty().getValue().getColumnIterator().next(); - assertEquals( "ball_id", idCol.getName() ); + if ( isMetadataUsed() ) { + org.hibernate.metamodel.spi.relational.Column idCol = SchemaUtil.getPrimaryKey( + Ball.class, + metadata() + ) + .getColumns().get( 0 ); + Assert.assertEquals( "ball_id", idCol.getColumnName().getText() ); + + } + else { + Column idCol = ( Column ) configuration().getClassMapping( Ball.class.getName() ) + .getIdentifierProperty().getValue().getColumnIterator().next(); + assertEquals( "ball_id", idCol.getName() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java index 8629c96082..5dcbf6b38c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java @@ -8,10 +8,12 @@ import org.jboss.logging.Logger; import org.junit.Test; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.test.annotations.id.sequences.entities.Bunny; import org.hibernate.test.annotations.id.sequences.entities.PointyTooth; import org.hibernate.test.annotations.id.sequences.entities.TwinkleToes; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -25,12 +27,17 @@ import static org.junit.Assert.fail; * @author Hardy Ferentschik */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class JoinColumnOverrideTest extends BaseUnitTestCase { private static final Logger log = Logger.getLogger( JoinColumnOverrideTest.class ); @Test @TestForIssue( jiraKey = "ANN-748" ) public void testBlownPrecision() throws Exception { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } + try { Configuration config = new Configuration(); config.addAnnotatedClass(Bunny.class); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java index 77c247d0e2..fabf125791 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java @@ -29,6 +29,7 @@ import java.util.List; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -65,6 +66,7 @@ public class IdClassGeneratedValueTest extends BaseCoreFunctionalTestCase { @Test @SuppressWarnings({ "unchecked" }) + @FailureExpectedWithNewMetamodel public void testSingleGeneratedValue() { Session s = openSession(); s.beginTransaction(); @@ -90,6 +92,7 @@ public class IdClassGeneratedValueTest extends BaseCoreFunctionalTestCase { @Test @SuppressWarnings({ "unchecked" }) + @FailureExpectedWithNewMetamodel public void testMultipleGeneratedValue() { Session s = openSession(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java index 452e008ba9..ee971250ea 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertEquals; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class IdentifierCollectionTest extends BaseCoreFunctionalTestCase { @Test public void testIdBag() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java index d259fe2cf1..b33f3aedab 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java @@ -25,11 +25,13 @@ package org.hibernate.test.annotations.idmanytoone.alphabetical; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class AlphabeticalIdManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testAlphabeticalTest() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java index 3c774427af..d0d8b2b979 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java @@ -37,6 +37,9 @@ import org.hibernate.mapping.Property; import org.hibernate.mapping.Set; import org.hibernate.mapping.Table; import org.hibernate.mapping.UniqueKey; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -50,88 +53,161 @@ import static org.junit.Assert.assertTrue; public abstract class AbstractJPAIndexTest extends BaseCoreFunctionalTestCase { @Test public void testTableIndex() { - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); - Iterator itr = entity.getTable().getUniqueKeyIterator(); - assertTrue( itr.hasNext() ); - UniqueKey uk = (UniqueKey) itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( StringHelper.isNotEmpty( uk.getName() ) ); - assertEquals( 2, uk.getColumnSpan() ); - Column column = (Column) uk.getColumns().get( 0 ); - assertEquals( "brand", column.getName() ); - column = (Column) uk.getColumns().get( 1 ); - assertEquals( "producer", column.getName() ); - assertSame( entity.getTable(), uk.getTable() ); + if ( isMetadataUsed() ) { + TableSpecification table = SchemaUtil.getTable( Car.class, metadata() ); + Iterator uniqueKeys = table.getUniqueKeys().iterator(); + assertTrue( uniqueKeys.hasNext() ); + org.hibernate.metamodel.spi.relational.UniqueKey uk = uniqueKeys.next(); + assertFalse( uniqueKeys.hasNext() ); + assertTrue( StringHelper.isNotEmpty( uk.getName() ) ); + assertEquals( 2, uk.getColumnSpan() ); + org.hibernate.metamodel.spi.relational.Column column = uk.getColumns().get( 0 ); + assertEquals( "brand", column.getColumnName().getText() ); + column = uk.getColumns().get( 1 ); + assertEquals( "producer", column.getColumnName().getText() ); + assertSame( table, uk.getTable() ); - itr = entity.getTable().getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = (Index)itr.next(); - assertFalse( itr.hasNext() ); - assertEquals( "Car_idx", index.getName() ); - assertEquals( 1, index.getColumnSpan() ); - column = index.getColumnIterator().next(); - assertEquals( "since", column.getName() ); - assertSame( entity.getTable(), index.getTable() ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertEquals( "Car_idx", index.getName() ); + assertEquals( 1, index.getColumnSpan() ); + column = index.getColumns().get( 0 ); + assertEquals( "since", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); + } + else { + PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); + Iterator itr = entity.getTable().getUniqueKeyIterator(); + assertTrue( itr.hasNext() ); + UniqueKey uk = (UniqueKey) itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( StringHelper.isNotEmpty( uk.getName() ) ); + assertEquals( 2, uk.getColumnSpan() ); + Column column = (Column) uk.getColumns().get( 0 ); + assertEquals( "brand", column.getName() ); + column = (Column) uk.getColumns().get( 1 ); + assertEquals( "producer", column.getName() ); + assertSame( entity.getTable(), uk.getTable() ); + + + itr = entity.getTable().getIndexIterator(); + assertTrue( itr.hasNext() ); + Index index = (Index)itr.next(); + assertFalse( itr.hasNext() ); + assertEquals( "Car_idx", index.getName() ); + assertEquals( 1, index.getColumnSpan() ); + column = index.getColumnIterator().next(); + assertEquals( "since", column.getName() ); + assertSame( entity.getTable(), index.getTable() ); + } } @Test public void testSecondaryTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); + if ( isMetadataUsed() ) { + EntityBinding entity = metadata().getEntityBinding( Car.class.getName() ); - Join join = (Join)entity.getJoinIterator().next(); - Iterator itr = join.getTable().getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); - assertEquals( 2, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "dealer_name", column.getName() ); - column = columnIterator.next(); - assertEquals( "rate", column.getName() ); - assertSame( join.getTable(), index.getTable() ); + TableSpecification table = entity.locateTable( "T_DEALER" ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 2, index.getColumnSpan() ); + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "dealer_name", column.getColumnName().getText() ); + column = index.getColumns().get( 1 ); + assertEquals( "rate", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); + } + else { + PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); + Join join = (Join)entity.getJoinIterator().next(); + Iterator itr = join.getTable().getIndexIterator(); + assertTrue( itr.hasNext() ); + Index index = itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 2, index.getColumnSpan() ); + Iterator columnIterator = index.getColumnIterator(); + Column column = columnIterator.next(); + assertEquals( "dealer_name", column.getName() ); + column = columnIterator.next(); + assertEquals( "rate", column.getName() ); + assertSame( join.getTable(), index.getTable() ); + } } @Test public void testCollectionTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); - Property property = entity.getProperty( "otherDealers" ); - Set set = (Set)property.getValue(); - Table collectionTable = set.getCollectionTable(); + if ( isMetadataUsed() ) { + TableSpecification table = SchemaUtil.getCollectionTable( Car.class, "otherDealers", metadata() ); - Iterator itr = collectionTable.getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); - assertEquals( 1, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "name", column.getName() ); - assertSame( collectionTable, index.getTable() ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 1, index.getColumnSpan() ); + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "name", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); + } + else { + PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); + Property property = entity.getProperty( "otherDealers" ); + Set set = (Set)property.getValue(); + Table collectionTable = set.getCollectionTable(); + Iterator itr = collectionTable.getIndexIterator(); + assertTrue( itr.hasNext() ); + Index index = itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 1, index.getColumnSpan() ); + Iterator columnIterator = index.getColumnIterator(); + Column column = columnIterator.next(); + assertEquals( "name", column.getName() ); + assertSame( collectionTable, index.getTable() ); + } } @Test public void testJoinTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Importer.class.getName() ); - Property property = entity.getProperty( "cars" ); - Bag set = (Bag)property.getValue(); - Table collectionTable = set.getCollectionTable(); + if ( isMetadataUsed() ) { + TableSpecification table = SchemaUtil.getCollectionTable( Importer.class, "cars", metadata() ); - Iterator itr = collectionTable.getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); - assertEquals( 1, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "importers_id", column.getName() ); - assertSame( collectionTable, index.getTable() ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 1, index.getColumnSpan() ); + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "importers_id", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); + } + else { + PersistentClass entity = configuration().getClassMapping( Importer.class.getName() ); + Property property = entity.getProperty( "cars" ); + Bag set = (Bag)property.getValue(); + Table collectionTable = set.getCollectionTable(); + + Iterator itr = collectionTable.getIndexIterator(); + assertTrue( itr.hasNext() ); + Index index = itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 1, index.getColumnSpan() ); + Iterator columnIterator = index.getColumnIterator(); + Column column = columnIterator.next(); + assertEquals( "importers_id", column.getName() ); + assertSame( collectionTable, index.getTable() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java index 156c4ec4fc..fad3c3542d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java @@ -39,6 +39,9 @@ import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -53,36 +56,46 @@ import static org.junit.Assert.assertTrue; * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumns not supported yet." ) public class IndexedCollectionTest extends BaseCoreFunctionalTestCase { @Test public void testJPA2DefaultMapColumns() throws Exception { - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDef", "_KEY" ); - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesPerKeyDef", "_KEY" ); - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDefLeg", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesDef", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesPerKeyDef", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesDefLeg", "_KEY" ); } @Test public void testJPA2DefaultIndexColumns() throws Exception { - isDefaultKeyColumnPresent( Drawer.class.getName(), "dresses", "_ORDER" ); + isDefaultKeyColumnPresent( Drawer.class, "dresses", "_ORDER" ); } - private void isDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { + private void isDefaultKeyColumnPresent(Class collectionOwner, String propertyName, String suffix) { assertTrue( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } - private boolean isDefaultColumnPresent(String collectionOwner, String propertyName, String suffix) { - final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); - final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); + private boolean isDefaultColumnPresent(Class collectionOwner, String propertyName, String suffix) { boolean hasDefault = false; - while ( columnIterator.hasNext() ) { - Column column = (Column) columnIterator.next(); - if ( (propertyName + suffix).equals( column.getName() ) ) hasDefault = true; + if ( isMetadataUsed() ) { + List values = SchemaUtil.getCollectionTable( collectionOwner, propertyName, metadata() ).values(); + for ( Value value : values ) { + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) value; + if ( (propertyName + suffix).equals( column.getColumnName().getText() ) ) hasDefault = true; + } + } + else { + final Collection collection = configuration().getCollectionMapping( collectionOwner.getName() + "." + propertyName ); + final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); + while ( columnIterator.hasNext() ) { + Column column = (Column) columnIterator.next(); + if ( (propertyName + suffix).equals( column.getName() ) ) hasDefault = true; + } } return hasDefault; } - private void isNotDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { + private void isNotDefaultKeyColumnPresent(Class collectionOwner, String propertyName, String suffix) { assertFalse( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java index cd74323903..7f82c59af8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertEquals; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class MapKeyTest extends BaseCoreFunctionalTestCase { @Test public void testMapKeyOnEmbeddedId() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java index 2ab15d09f4..53661ae073 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java @@ -88,6 +88,6 @@ public class JoinedSubclassAndSecondaryTable extends BaseCoreFunctionalTestCase @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Pool.class, SwimmingPool.class }; + return new Class[] { Pool.class, PoolAddress.class, SwimmingPool.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java index 187c6717c3..275e8d3127 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java @@ -35,6 +35,12 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.mapping.Join; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -48,11 +54,18 @@ import static org.junit.Assert.fail; public class JoinTest extends BaseCoreFunctionalTestCase { @Test public void testDefaultValue() throws Exception { - Join join = (Join) configuration().getClassMapping( Life.class.getName() ).getJoinClosureIterator().next(); - assertEquals( "ExtendedLife", join.getTable().getName() ); - org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); - owner.setName( "LIFE_ID" ); - assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + if ( isMetadataUsed() ) { + TableSpecification joinTable = metadata().getEntityBinding( Life.class.getName() ).locateTable( "ExtendedLife" ); + assertNotNull( joinTable ); + assertTrue( joinTable.getPrimaryKey().hasColumn( "LIFE_ID" ) ); + } + else { + Join join = (Join) configuration().getClassMapping( Life.class.getName() ).getJoinClosureIterator().next(); + assertEquals( "ExtendedLife", join.getTable().getName() ); + org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); + owner.setName( "LIFE_ID" ); + assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + } Session s = openSession(); Transaction tx = s.beginTransaction(); Life life = new Life(); @@ -73,11 +86,27 @@ public class JoinTest extends BaseCoreFunctionalTestCase { @Test public void testCompositePK() throws Exception { - Join join = (Join) configuration().getClassMapping( Dog.class.getName() ).getJoinClosureIterator().next(); - assertEquals( "DogThoroughbred", join.getTable().getName() ); - org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); - owner.setName( "OWNER_NAME" ); - assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + if ( isMetadataUsed() ) { + SecondaryTable secondaryTable = + metadata().getEntityBinding( Dog.class.getName() ).getSecondaryTables().values().iterator().next(); + Table table = (Table) secondaryTable.getSecondaryTableReference(); + assertEquals( "DogThoroughbred", table.getPhysicalName().getText() ); + PrimaryKey pk = table.getPrimaryKey(); + assertEquals( 2, pk.getColumnSpan() ); + Column c0 = pk.getColumns().get( 0 ); + Column c1 = pk.getColumns().get( 1 ); + assertTrue( + "OWNER_NAME".equals( c0.getColumnName().getText() ) || + "OWNER_NAME".equals( c1.getColumnName().getText() ) + ); + } + else { + Join join = (Join) configuration().getClassMapping( Dog.class.getName() ).getJoinClosureIterator().next(); + assertEquals( "DogThoroughbred", join.getTable().getName() ); + org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); + owner.setName( "OWNER_NAME" ); + assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + } Session s = openSession(); Transaction tx = s.beginTransaction(); Dog dog = new Dog(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java index f3ca7b6669..5f1ab08f26 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertEquals; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -21,28 +22,57 @@ import org.junit.Test; public class SerializableToBlobTypeTest extends BaseCoreFunctionalTestCase { @Test public void testTypeDefinition() { - Configuration cfg = configuration(); - PersistentClass pc = cfg.getClassMapping( EntitySerialize.class.getName() ); + if ( isMetadataUsed() ) { + EntityBinding binding = metadata().getEntityBinding( EntitySerialize.class.getName() ); - // explicitLob of SerializableToBlobType - Type explicitLobType = pc.getProperty( "explicitLob" ).getType(); - assertEquals( ExplicitSerializable.class, explicitLobType.getReturnedClass() ); - assertEquals( SerializableToBlobType.class.getName(), explicitLobType.getName() ); + // explicitLob of SerializableToBlobType + Type explicitLobType = binding.locateAttributeBinding( "explicitLob" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); + assertEquals( ExplicitSerializable.class, explicitLobType.getReturnedClass() ); + assertEquals( SerializableToBlobType.class.getName(), explicitLobType.getName() ); - // explicit of ExplicitSerializableType - Type explicitType = pc.getProperty( "explicit" ).getType(); - assertEquals( ExplicitSerializable.class, explicitType.getReturnedClass() ); - assertEquals( ExplicitSerializableType.class.getName(), explicitType.getName() ); + // explicit of ExplicitSerializableType + Type explicitType = binding.locateAttributeBinding( "explicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); + assertEquals( ExplicitSerializable.class, explicitType.getReturnedClass() ); + assertEquals( ExplicitSerializableType.class.getName(), explicitType.getName() ); - // implicit of ImplicitSerializableType - Type implicitType = pc.getProperty( "implicit" ).getType(); - assertEquals( ImplicitSerializable.class, implicitType.getReturnedClass() ); - assertEquals( ImplicitSerializableType.class.getName(), implicitType.getName() ); + // implicit of ImplicitSerializableType + Type implicitType = binding.locateAttributeBinding( "implicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); + assertEquals( ImplicitSerializable.class, implicitType.getReturnedClass() ); + assertEquals( ImplicitSerializableType.class.getName(), implicitType.getName() ); - // explicitOverridingImplicit ExplicitSerializableType overrides ImplicitSerializableType - Type overrideType = pc.getProperty( "explicitOverridingImplicit" ).getType(); - assertEquals( ImplicitSerializable.class, overrideType.getReturnedClass() ); - assertEquals( ExplicitSerializableType.class.getName(), overrideType.getName() ); + // explicitOverridingImplicit ExplicitSerializableType overrides ImplicitSerializableType + Type overrideType = binding.locateAttributeBinding( "explicitOverridingImplicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); + assertEquals( ImplicitSerializable.class, overrideType.getReturnedClass() ); + assertEquals( ExplicitSerializableType.class.getName(), overrideType.getName() ); + } + else { + Configuration cfg = configuration(); + PersistentClass pc = cfg.getClassMapping( EntitySerialize.class.getName() ); + + // explicitLob of SerializableToBlobType + Type explicitLobType = pc.getProperty( "explicitLob" ).getType(); + assertEquals( ExplicitSerializable.class, explicitLobType.getReturnedClass() ); + assertEquals( SerializableToBlobType.class.getName(), explicitLobType.getName() ); + + // explicit of ExplicitSerializableType + Type explicitType = pc.getProperty( "explicit" ).getType(); + assertEquals( ExplicitSerializable.class, explicitType.getReturnedClass() ); + assertEquals( ExplicitSerializableType.class.getName(), explicitType.getName() ); + + // implicit of ImplicitSerializableType + Type implicitType = pc.getProperty( "implicit" ).getType(); + assertEquals( ImplicitSerializable.class, implicitType.getReturnedClass() ); + assertEquals( ImplicitSerializableType.class.getName(), implicitType.getName() ); + + // explicitOverridingImplicit ExplicitSerializableType overrides ImplicitSerializableType + Type overrideType = pc.getProperty( "explicitOverridingImplicit" ).getType(); + assertEquals( ImplicitSerializable.class, overrideType.getReturnedClass() ); + assertEquals( ExplicitSerializableType.class.getName(), overrideType.getName() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java index 72b99f1ff2..f8078f35d4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java @@ -2,10 +2,12 @@ package org.hibernate.test.annotations.manytomany; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ +@Embeddable public class CatPk implements Serializable { private String name; private String thoroughbred; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java index f2d27e1633..b498937180 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java @@ -763,6 +763,8 @@ public class ManyToManyTest extends BaseCoreFunctionalTestCase { Friend.class, Employer.class, Employee.class, + ContactInfo.class, + JobInfo.class, Contractor.class, Man.class, Woman.class, @@ -771,6 +773,7 @@ public class ManyToManyTest extends BaseCoreFunctionalTestCase { Supplier.class, City.class, Cat.class, + CatPk.class, Group.class, GroupWithSet.class, Permission.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java index ec61f61b2b..43d42a9e00 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java @@ -39,6 +39,7 @@ import org.hibernate.test.annotations.Discount; import org.hibernate.test.annotations.Flight; import org.hibernate.test.annotations.Passport; import org.hibernate.test.annotations.Ticket; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -49,6 +50,7 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testEager() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java index 8f89fad0c8..e340352b4e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java @@ -29,12 +29,14 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ManyToOneReferencedColumnNameTest extends BaseCoreFunctionalTestCase { @Test @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java index d18378fe55..9a9b6d0ccf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java @@ -35,6 +35,7 @@ import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.SQLServer2005Dialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.SkipForDialects; @@ -67,6 +68,7 @@ public class ManyToOneWithFormulaTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testManyToOneFromPk() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -91,6 +93,7 @@ public class ManyToOneWithFormulaTest extends BaseCoreFunctionalTestCase { @Test @SkipForDialect(value = { HSQLDialect.class }, comment = "The used join conditions does not work in HSQLDB. See HHH-4497") + @FailureExpectedWithNewMetamodel public void testManyToOneToPkWithOnlyFormula() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -160,6 +163,7 @@ public class ManyToOneWithFormulaTest extends BaseCoreFunctionalTestCase { @SkipForDialect( value = { SQLServer2005Dialect.class } ), @SkipForDialect( value = { Oracle8iDialect.class }, comment = "Oracle/DB2 do not support 'substring' function" ), @SkipForDialect( value = { DB2Dialect.class }, comment = "Oracle/DB2 do not support 'substring' function" ) } ) + @FailureExpectedWithNewMetamodel public void testManyToOneFromNonPkToNonPk() throws Exception { // also tests usage of the stand-alone @JoinFormula annotation (i.e. not wrapped within @JoinColumnsOrFormulas) Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java index 7c175c7401..c1404b90e0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java @@ -28,6 +28,7 @@ import java.math.BigDecimal; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,6 +36,7 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class IntermediateMappedSuperclassTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java index 3c2c45a2d3..f2da16d69a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java @@ -17,6 +17,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.cfg.Mappings; import org.hibernate.mapping.Table; import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; import static org.junit.Assert.assertFalse; @@ -59,6 +60,7 @@ public class NamingStrategyTest { } } @Test + @FailureExpectedWithNewMetamodel public void testWithEJB3NamingStrategy() throws Exception { SessionFactory sf = null; try { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java index 06741eea2d..91ce4bf34a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNull; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertNull; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916") public class NotFoundTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java index 36455024ea..2d5ea1ab88 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java @@ -42,12 +42,16 @@ import org.hibernate.Transaction; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.test.annotations.Customer; import org.hibernate.test.annotations.Discount; import org.hibernate.test.annotations.Passport; import org.hibernate.test.annotations.Ticket; import org.hibernate.test.annotations.TicketComparator; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -66,6 +70,7 @@ import static org.junit.Assert.fail; * @author Hardy Ferentschik */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class OneToManyTest extends BaseCoreFunctionalTestCase { @Test public void testColumnDefinitionPropagation() throws Exception { @@ -478,14 +483,27 @@ public class OneToManyTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-4605" ) public void testJoinColumnConfiguredInXml() { - PersistentClass pc = configuration().getClassMapping( Model.class.getName() ); - Table table = pc.getRootTable(); - Iterator iter = table.getColumnIterator(); boolean joinColumnFound = false; - while(iter.hasNext()) { - Column column = (Column) iter.next(); - if(column.getName().equals( "model_manufacturer_join" )) { - joinColumnFound = true; + if ( isMetadataUsed() ) { + EntityBinding entityBinding = metadata().getEntityBinding( Model.class.getName() ); + TableSpecification table = entityBinding.getPrimaryTable(); + for ( Value value : table.values() ) { + org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) value; + if(column.getColumnName().getText().equals( "model_manufacturer_join" )) { + joinColumnFound = true; + } + } + } + else { + PersistentClass pc = configuration().getClassMapping( Model.class.getName() ); + Table table = pc.getRootTable(); + Iterator iter = table.getColumnIterator(); + while(iter.hasNext()) { + Column column = (Column) iter.next(); + if(column.getName().equals( "model_manufacturer_join" )) { + joinColumnFound = true; + } } } assertTrue( "The mapping defines a joing column which could not be found in the metadata.", joinColumnFound ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java index c1f631a1c3..d56c18322d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java @@ -47,6 +47,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.sql.SimpleSelect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -58,6 +59,7 @@ import org.junit.Test; * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) * @author Brett Meyer */ +@FailureExpectedWithNewMetamodel public class OrderByTest extends BaseCoreFunctionalTestCase { @Test public void testOrderByOnIdClassProperties() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java index 0da443dc7a..ada87180c9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java @@ -9,6 +9,7 @@ import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Environment; import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; /** @@ -16,6 +17,7 @@ import org.hibernate.testing.ServiceRegistryBuilder; */ public class OneToOneErrorTest { @Test + @FailureExpectedWithNewMetamodel public void testWrongOneToOne() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Show.class ) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java index 7e6e8c2851..7bf3de8ed3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java @@ -36,6 +36,8 @@ import org.hibernate.mapping.Column; import org.hibernate.mapping.Join; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.annotations.Customer; import org.hibernate.test.annotations.Discount; import org.hibernate.test.annotations.Passport; @@ -309,24 +311,35 @@ public class OneToOneTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-4606" ) public void testJoinColumnConfiguredInXml() { - PersistentClass pc = configuration().getClassMapping( Son.class.getName() ); - Iterator iter = pc.getJoinIterator(); - Table table = ( ( Join ) iter.next() ).getTable(); - Iterator columnIter = table.getColumnIterator(); - boolean fooFound = false; - boolean barFound = false; - while ( columnIter.hasNext() ) { - Column column = ( Column ) columnIter.next(); - if ( column.getName().equals( "foo" ) ) { - fooFound = true; - } - if ( column.getName().equals( "bar" ) ) { - barFound = true; - } + if ( isMetadataUsed() ) { + EntityBinding entityBinding = metadata().getEntityBinding( Son.class.getName() ); + TableSpecification table = entityBinding.getSecondaryTables().values().iterator().next().getSecondaryTableReference(); + org.hibernate.metamodel.spi.relational.Column c1= table.locateColumn( "foo" ); + assertNotNull( c1 ); + org.hibernate.metamodel.spi.relational.Column c2= table.locateColumn( "bar" ); + assertNotNull( c2 ); + } + else { + + PersistentClass pc = configuration().getClassMapping( Son.class.getName() ); + Iterator iter = pc.getJoinIterator(); + Table table = ( ( Join ) iter.next() ).getTable(); + Iterator columnIter = table.getColumnIterator(); + boolean fooFound = false; + boolean barFound = false; + while ( columnIter.hasNext() ) { + Column column = ( Column ) columnIter.next(); + if ( column.getName().equals( "foo" ) ) { + fooFound = true; + } + if ( column.getName().equals( "bar" ) ) { + barFound = true; + } + } + assertTrue( + "The mapping defines join columns which could not be found in the metadata.", fooFound && barFound + ); } - assertTrue( - "The mapping defines join columns which could not be found in the metadata.", fooFound && barFound - ); } @Test @@ -398,6 +411,7 @@ public class OneToOneTest extends BaseCoreFunctionalTestCase { Client.class, Address.class, Computer.class, + ComputerPk.class, SerialNumber.class, Body.class, Heart.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java index cb754fae1c..4aac884a99 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java @@ -29,6 +29,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.id.IdentifierGenerationException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -44,6 +45,7 @@ public class OptionalOneToOneMappedByTest extends BaseCoreFunctionalTestCase { // @OneToOne(mappedBy="address") with foreign generator @Test + @FailureExpectedWithNewMetamodel( message = "mappedBy @OneToOne with foreign generator" ) public void testBidirForeignIdGenerator() { Session s = openSession(); Transaction tx = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java index f3aa4e874d..61ff2fdf42 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java @@ -7,7 +7,9 @@ import org.junit.Test; import org.hibernate.dialect.H2Dialect; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -17,6 +19,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; */ @RequiresDialect({ H2Dialect.class }) @TestForIssue(jiraKey = "HHH-6662") +@FailureExpectedWithNewMetamodel public class AssociationOverrideSchemaTest extends BaseCoreFunctionalTestCase { public static final String SCHEMA_NAME = "OTHER_SCHEMA"; public static final String TABLE_NAME = "BLOG_TAGS"; @@ -35,24 +38,41 @@ public class AssociationOverrideSchemaTest extends BaseCoreFunctionalTestCase { @Test public void testJoinTableSchemaName() { - Iterator
tableIterator = configuration().getTableMappings(); - while ( tableIterator.hasNext() ) { - Table table = tableIterator.next(); - if ( TABLE_NAME.equals( table.getName() ) ) { - Assert.assertEquals( SCHEMA_NAME, table.getSchema() ); - return; - } + if ( isMetadataUsed() ) { + TableSpecification table = SchemaUtil.getTable( TABLE_NAME, metadata() ); + Assert.assertNotNull( table ); + Assert.assertEquals( SCHEMA_NAME, table.getSchema().getName().getSchema().getText()); + } + else { + Iterator
tableIterator = configuration().getTableMappings(); + while ( tableIterator.hasNext() ) { + Table table = tableIterator.next(); + if ( TABLE_NAME.equals( table.getName() ) ) { + Assert.assertEquals( SCHEMA_NAME, table.getSchema() ); + return; + } + } + Assert.fail(); } - Assert.fail(); } @Test public void testJoinTableJoinColumnName() { - Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, ID_COLUMN_NAME, configuration() ) ); + if ( isMetadataUsed() ) { + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, ID_COLUMN_NAME, metadata() ) ); + } + else { + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, ID_COLUMN_NAME, configuration() ) ); + } } @Test public void testJoinTableColumnName() { - Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, VALUE_COLUMN_NAME, configuration() ) ); + if ( isMetadataUsed() ) { + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, VALUE_COLUMN_NAME, metadata() ) ); + } + else { + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, VALUE_COLUMN_NAME, configuration() ) ); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java index dc76dcc9fb..ccf28990ed 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java @@ -10,6 +10,7 @@ import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertTrue; @@ -18,6 +19,7 @@ import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class AssociationOverrideTest extends BaseCoreFunctionalTestCase { @Test public void testOverriding() throws Exception { @@ -48,16 +50,28 @@ public class AssociationOverrideTest extends BaseCoreFunctionalTestCase { @Test public void testDottedNotation() throws Exception { - assertTrue( SchemaUtil.isTablePresent( "Employee", configuration() ) ); - assertTrue( "Overridden @JoinColumn fails", - SchemaUtil.isColumnPresent( "Employee", "fld_address_fk", configuration() ) ); + if ( isMetadataUsed() ) { + assertTrue( SchemaUtil.isTablePresent( "Employee", metadata() ) ); + assertTrue( "Overridden @JoinColumn fails", + SchemaUtil.isColumnPresent( "Employee", "fld_address_fk", metadata() ) ); - assertTrue( "Overridden @JoinTable name fails", SchemaUtil.isTablePresent( "tbl_empl_sites", configuration() ) ); - assertTrue( "Overridden @JoinTable with default @JoinColumn fails", - SchemaUtil.isColumnPresent( "tbl_empl_sites", "employee_id", configuration() ) ); - assertTrue( "Overridden @JoinTable.inverseJoinColumn fails", - SchemaUtil.isColumnPresent( "tbl_empl_sites", "to_website_fk", configuration() ) ); + assertTrue( "Overridden @JoinTable name fails", SchemaUtil.isTablePresent( "tbl_empl_sites", metadata() ) ); + assertTrue( "Overridden @JoinTable with default @JoinColumn fails", + SchemaUtil.isColumnPresent( "tbl_empl_sites", "employee_id", metadata() ) ); + assertTrue( "Overridden @JoinTable.inverseJoinColumn fails", + SchemaUtil.isColumnPresent( "tbl_empl_sites", "to_website_fk", metadata() ) ); + } + else { + assertTrue( SchemaUtil.isTablePresent( "Employee", configuration() ) ); + assertTrue( "Overridden @JoinColumn fails", + SchemaUtil.isColumnPresent( "Employee", "fld_address_fk", configuration() ) ); + assertTrue( "Overridden @JoinTable name fails", SchemaUtil.isTablePresent( "tbl_empl_sites", configuration() ) ); + assertTrue( "Overridden @JoinTable with default @JoinColumn fails", + SchemaUtil.isColumnPresent( "tbl_empl_sites", "employee_id", configuration() ) ); + assertTrue( "Overridden @JoinTable.inverseJoinColumn fails", + SchemaUtil.isColumnPresent( "tbl_empl_sites", "to_website_fk", configuration() ) ); + } Session s = openSession(); Transaction tx = s.beginTransaction(); ContactInfo ci = new ContactInfo(); @@ -106,7 +120,8 @@ public class AssociationOverrideTest extends BaseCoreFunctionalTestCase { PhoneNumber.class, Addr.class, SocialSite.class, - SocialTouchPoints.class + SocialTouchPoints.class, + ContactInfo.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java index 481730b117..1f9c6bb047 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java @@ -26,6 +26,7 @@ package org.hibernate.test.annotations.override; import org.junit.Test; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertTrue; @@ -33,6 +34,7 @@ import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class AttributeOverrideTest extends BaseCoreFunctionalTestCase { @Test public void testMapKeyValue() throws Exception { @@ -57,7 +59,12 @@ public class AttributeOverrideTest extends BaseCoreFunctionalTestCase { } public boolean isColumnPresent(String tableName, String columnName) { - return SchemaUtil.isColumnPresent( tableName, columnName, configuration() ); + if ( isMetadataUsed() ) { + return SchemaUtil.isColumnPresent( tableName, columnName, metadata() ); + } + else { + return SchemaUtil.isColumnPresent( tableName, columnName, configuration() ); + } } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java index 5d357925ce..1ef4c01b73 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java @@ -27,10 +27,12 @@ import org.junit.Test; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * @author Shawn Clowater @@ -39,25 +41,62 @@ public class PersisterTest extends BaseCoreFunctionalTestCase { @Test public void testEntityEntityPersisterAndPersisterSpecified() throws Exception { //checks to see that the persister specified with the @Persister annotation takes precedence if a @Entity.persister() is also specified - PersistentClass persistentClass = configuration().getClassMapping( Deck.class.getName() ); - assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), EntityPersister.class, - persistentClass.getEntityPersisterClass() ); + if ( isMetadataUsed() ) { + Class clazz = + metadata().getEntityBinding( Deck.class.getName() ).getCustomEntityPersisterClass(); + assertEquals( "Incorrect Persister class for " + Deck.class.getName(), + org.hibernate.test.annotations.persister.EntityPersister.class, clazz ); + + } + else { + PersistentClass persistentClass = configuration().getClassMapping( Deck.class.getName() ); + assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), EntityPersister.class, + persistentClass.getEntityPersisterClass() ); + } } @Test public void testEntityEntityPersisterSpecified() throws Exception { //tests the persister specified with an @Entity.persister() - PersistentClass persistentClass = configuration().getClassMapping( Card.class.getName() ); - assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), - SingleTableEntityPersister.class, persistentClass.getEntityPersisterClass() ); + if ( isMetadataUsed() ) { + Class clazz = + metadata().getEntityBinding( Card.class.getName() ).getCustomEntityPersisterClass(); + assertEquals( "Incorrect Persister class for " + Card.class.getName(), + SingleTableEntityPersister.class, clazz ); + + } + else { + PersistentClass persistentClass = configuration().getClassMapping( Card.class.getName() ); + assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), + SingleTableEntityPersister.class, persistentClass.getEntityPersisterClass() ); + } } @Test public void testCollectionPersisterSpecified() throws Exception { //tests the persister specified by the @Persister annotation on a collection - Collection collection = configuration().getCollectionMapping( Deck.class.getName() + ".cards" ); - assertEquals( "Incorrect Persister class for collection " + collection.getRole(), CollectionPersister.class, - collection.getCollectionPersisterClass() ); + if ( isMetadataUsed() ) { + String expectedRole = Deck.class.getName() + ".cards"; + boolean found = false; + for ( PluralAttributeBinding attributeBinding : metadata().getCollectionBindings() ) { + String role = attributeBinding.getAttribute().getRole(); + //tests the persister specified by the @Persister annotation on a collection + if ( expectedRole.equals( role ) ) { + assertEquals( + "Incorrect Persister class for collection " + role, CollectionPersister.class, + attributeBinding.getExplicitPersisterClass() + ); + found = true; + break; + } + } + assertTrue( found ); + } + else { + Collection collection = configuration().getCollectionMapping( Deck.class.getName() + ".cards" ); + assertEquals( "Incorrect Persister class for collection " + collection.getRole(), CollectionPersister.class, + collection.getCollectionPersisterClass() ); + } } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java index 7f358a4b12..bca16375ad 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java @@ -45,6 +45,7 @@ import org.hibernate.test.annotations.A320; import org.hibernate.test.annotations.A320b; import org.hibernate.test.annotations.Plane; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -60,6 +61,7 @@ import static org.junit.Assert.fail; * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel(message = "due to derived ids are not supported") public class QueryAndSQLTest extends BaseCoreFunctionalTestCase { @Override protected boolean isCleanupTestDataRequired() { @@ -284,6 +286,7 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testNativeQueryAndCompositePKAndComponents() throws Exception { Session s; Transaction tx; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java index aa51b685b4..91a04f3a70 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java @@ -31,6 +31,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ReferencedColumnNameTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { @@ -284,7 +286,8 @@ public class ReferencedColumnNameTest extends BaseCoreFunctionalTestCase { Vendor.class, WarehouseItem.class, Place.class, - HousePlaces.class + HousePlaces.class, + Places.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java index 9b5b5df745..e52d0007c4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java @@ -2,9 +2,12 @@ package org.hibernate.test.annotations.strategy; +import javax.persistence.Embeddable; + /** * @author Emmanuel Bernard */ +@Embeddable public class Location { private String city; private String country; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java index 7f0901fe74..9f404e4e06 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java @@ -9,11 +9,13 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.Index; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Emmanuel Bernard */ @Entity +@FailureExpectedWithNewMetamodel @Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"start.country", "start.city"})}) public class Storm { private Integer id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java index 39aeff948a..808b1f1a51 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java @@ -29,11 +29,13 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.DefaultComponentSafeNamingStrategy; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class StrategyTest extends BaseCoreFunctionalTestCase { @Test public void testComponentSafeStrategy() throws Exception { @@ -61,6 +63,6 @@ public class StrategyTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Storm.class }; + return new Class[] { Storm.class, Location.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java index b0ec9c21be..c77d92e70b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java @@ -26,6 +26,7 @@ package org.hibernate.test.annotations.target; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,6 +36,7 @@ import static org.junit.Assert.assertEquals; */ public class TargetTest extends BaseCoreFunctionalTestCase { @Test + @FailureExpectedWithNewMetamodel public void testTargetOnEmbedded() throws Exception { Session s = openSession(); s.getTransaction().begin(); @@ -103,6 +105,6 @@ public class TargetTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { LuggageImpl.class, Brand.class }; + return new Class[] { LuggageImpl.class, Brand.class, OwnerImpl.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java index d7fbb09d2b..3c132d68fe 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java @@ -1,6 +1,7 @@ //$Id$ package org.hibernate.test.annotations.tuplizer; import org.hibernate.mapping.Component; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.component.PojoComponentTuplizer; @@ -13,7 +14,17 @@ public class DynamicComponentTuplizer extends PojoComponentTuplizer { super( component ); } - protected Instantiator buildInstantiator(Component component) { - return new DynamicInstantiator( component.getComponentClassName() ); //To change body of overridden methods use File | Settings | File Templates. + public DynamicComponentTuplizer(CompositeAttributeBindingContainer compositeAttributeBindingContainer, boolean isIdentifierMapper) { + super( compositeAttributeBindingContainer, isIdentifierMapper); } -} + + protected Instantiator buildInstantiator(Component component) { + return new DynamicInstantiator( component.getComponentClassName() ); + } + + protected Instantiator buildInstantiator( + CompositeAttributeBindingContainer compositeAttributeBindingContainer, + boolean isIdentifierMapper) { + return new DynamicInstantiator( compositeAttributeBindingContainer.getClassReference().getName() ); + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java index 34a13e9a8f..b5bb978e41 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java @@ -1,6 +1,7 @@ //$Id$ package org.hibernate.test.annotations.tuplizer; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; @@ -13,15 +14,29 @@ import org.hibernate.tuple.entity.PojoEntityTuplizer; */ public class DynamicEntityTuplizer extends PojoEntityTuplizer { - public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super( entityMetamodel, mappedEntity ); - } + public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { + super( entityMetamodel, mappedEntity ); + } - protected Instantiator buildInstantiator(PersistentClass persistentClass) { - return new DynamicInstantiator( persistentClass.getEntityName() ); - } + public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super( entityMetamodel, mappedEntity ); + } - protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { + protected Instantiator buildInstantiator(PersistentClass persistentClass) { + return new DynamicInstantiator( persistentClass.getEntityName() ); + } + + @Override + protected Instantiator buildInstantiator(EntityBinding entityBinding) { + return new DynamicInstantiator( entityBinding.getEntityName() ); + } + + @Override + protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + return super.buildProxyFactoryInternal( entityBinding, idGetter, idSetter ); + } + + protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { // allows defining a custom proxy factory, which is responsible for // generating lazy proxies for a given entity. // diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java index 72483e3233..3b7e260dec 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java @@ -57,6 +57,6 @@ public class TuplizerTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Cuisine.class }; + return new Class[] { Cuisine.class, Country.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java index d1976fd2b0..778ec91d99 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java @@ -10,7 +10,9 @@ import javax.persistence.UniqueConstraint; import org.hibernate.AnnotationException; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; @@ -19,6 +21,7 @@ import org.junit.Test; * @author Nikolay Shestakov * */ +@FailureExpectedWithNewMetamodel public class UniqueConstraintValidationTest extends BaseUnitTestCase { @Test(expected = AnnotationException.class) @@ -38,6 +41,10 @@ public class UniqueConstraintValidationTest extends BaseUnitTestCase { } private void buildSessionFactory(Class entity) { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } + Configuration cfg = new Configuration(); cfg.addAnnotatedClass(entity); cfg.buildMappings(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java index cd2948a871..566861250e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java @@ -28,9 +28,11 @@ import org.junit.Test; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.metadata.ClassMetadata; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.DbTimestampType; import org.hibernate.type.TimestampType; +import org.hibernate.type.Type; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -57,11 +59,23 @@ public class TimestampTest extends BaseCoreFunctionalTestCase { ClassMetadata meta = sessionFactory().getClassMetadata( clazz ); assertTrue( "Entity is annotated with @Timestamp and should hence be versioned", meta.isVersioned() ); - PersistentClass persistentClass = configuration().getClassMapping( clazz.getName() ); - assertNotNull( persistentClass ); - Property versionProperty = persistentClass.getVersion(); - assertNotNull( versionProperty ); - assertEquals( "Wrong timestamp type", expectedTypeClass, versionProperty.getType().getClass() ); + if ( isMetadataUsed() ) { + EntityBinding binding = metadata().getEntityBinding( clazz.getName() ); + assertNotNull( binding ); + Type type = binding.getHierarchyDetails().getEntityVersion() + .getVersioningAttributeBinding().getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + assertNotNull( type ); + assertEquals( "Wrong timestamp type", expectedTypeClass, + type.getClass() ); + } + else { + PersistentClass persistentClass = configuration().getClassMapping( clazz.getName() ); + assertNotNull( persistentClass ); + Property versionProperty = persistentClass.getVersion(); + assertNotNull( versionProperty ); + assertEquals( "Wrong timestamp type", expectedTypeClass, versionProperty.getType().getClass() ); + } } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java index 21a2308357..7d353a9e52 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java @@ -34,6 +34,7 @@ import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.persister.collection.BasicCollectionPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -43,6 +44,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class Ejb3XmlTest extends BaseCoreFunctionalTestCase { @Test @SkipForDialect(value = { PostgreSQL81Dialect.class, PostgreSQLDialect.class }, diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java index b4e32a3876..f54ff4a90e 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java @@ -32,6 +32,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -42,6 +43,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class AuctionTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "bidi/Auction.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java index 92860dfa20..f9e12942b2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java @@ -24,6 +24,8 @@ package org.hibernate.test.cfg.cache; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; @@ -32,11 +34,16 @@ import org.junit.Test; * * @author Tair Sabirgaliev */ +@FailureExpectedWithNewMetamodel public class CacheConfigurationTest extends BaseUnitTestCase { public static final String CFG_XML = "org/hibernate/test/cfg/cache/hibernate.cfg.xml"; @Test public void testCacheConfiguration() throws Exception { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } + // we only care if the SF builds successfully. Configuration cfg = new Configuration().configure(CFG_XML); cfg.buildSessionFactory().close(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java index f1ded8bd34..97d46af3a5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java @@ -51,8 +51,8 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.spi.PersisterClassResolver; diff --git a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java index c681eafd42..b8cee297b9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java @@ -31,6 +31,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -51,6 +52,7 @@ import static org.junit.Assert.assertTrue; * @author Jacob Robertson */ @TestForIssue( jiraKey = "HHH-2060" ) +@FailureExpectedWithNewMetamodel public class CompositeIdWithGeneratorTest extends BaseCoreFunctionalTestCase { private DateFormat df = SimpleDateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java index 51a0d326ad..ad3c63e07f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.basic; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class UserCollectionTypeAnnotationsVariantTest extends UserCollectionTypeTest { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java index 4b9b51d698..f03a7b4701 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.basic; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class UserCollectionTypeHbmVariantTest extends UserCollectionTypeTest { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java index 5130064a7a..9ac6b109ac 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.parameterized; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ParameterizedUserCollectionTypeAnnotationsVariantTest extends ParameterizedUserCollectionTypeTest { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java index fb3650c5fd..9bb1bd0974 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.parameterized; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ParameterizedUserCollectionTypeHbmVariantTest extends ParameterizedUserCollectionTypeTest { public String[] getMappings() { return new String[] { "collection/custom/parameterized/Mapping.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java index 7a35590a8d..f62635218e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.collection.internal.PersistentIdentifierBag; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertFalse; @@ -38,6 +39,7 @@ import static org.junit.Assert.assertTrue; * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( message = " not supported" ) public class PersistentIdBagTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java index 4334c51eeb..503291ea52 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java @@ -27,12 +27,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; /** * @author Vasily Kochnev */ +@FailureExpectedWithNewMetamodel public class LazyAssociationNoCascadeTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java index 28665abbbb..a5cb556c4e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java @@ -45,6 +45,7 @@ import javax.persistence.OneToMany; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.collection.internal.PersistentMap; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -55,6 +56,7 @@ import org.junit.Test; * @author Steve Ebersole * @author Brett Meyer */ +@FailureExpectedWithNewMetamodel public class PersistentMapTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java index 5dfa28a905..4a2886fb72 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java @@ -31,12 +31,14 @@ import org.hibernate.Session; import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Elizabeth Chatman * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel // missing unique-constraint default naming public class EntityMapTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java index 8a754e5f99..c929ec8023 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java @@ -30,6 +30,7 @@ import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -42,6 +43,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916") public class CollectionTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java index 22c7e77ea0..fb0af6d3df 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java +++ b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java @@ -30,14 +30,23 @@ import java.util.Set; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; +import org.hibernate.engine.jdbc.env.internal.ExtractedDatabaseMetaDataImpl; +import org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl; import org.hibernate.engine.jdbc.spi.TypeInfo; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.ResultSetWrapper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.Stoppable; import org.hibernate.testing.env.ConnectionProviderBuilder; @@ -49,11 +58,10 @@ import org.hibernate.testing.env.ConnectionProviderBuilder; * @author Steve Ebersole */ public class BasicTestingJdbcServiceImpl implements JdbcServices { - private ConnectionProvider connectionProvider; - private Dialect dialect; - private SqlStatementLogger sqlStatementLogger; - private SqlExceptionHelper exceptionHelper; - private final ExtractedDatabaseMetaData metaDataSupport = new MetaDataSupportImpl(); + + private TestingJdbcEnvironmentImpl jdbcEnvironment; + + private SqlStatementLogger sqlStatementLogger = new SqlStatementLogger( true, false );; private final ResultSetWrapper resultSetWrapper = ResultSetWrapperImpl.INSTANCE; public void start() { @@ -64,33 +72,34 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices { } public void prepare(boolean allowAggressiveRelease) { - connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); - dialect = ConnectionProviderBuilder.getCorrespondingDialect(); - sqlStatementLogger = new SqlStatementLogger( true, false ); - exceptionHelper = new SqlExceptionHelper(); + jdbcEnvironment = new TestingJdbcEnvironmentImpl( allowAggressiveRelease ); } public void release() { - if ( connectionProvider instanceof Stoppable ) { - ( (Stoppable) connectionProvider ).stop(); + if ( jdbcEnvironment.connectionProvider instanceof Stoppable ) { + ( (Stoppable) jdbcEnvironment.connectionProvider ).stop(); } } public ConnectionProvider getConnectionProvider() { - return connectionProvider; + return jdbcEnvironment.connectionProvider; } public Dialect getDialect() { - return dialect; + return jdbcEnvironment.dialect; } public LobCreator getLobCreator(LobCreationContext lobCreationContext) { - return null; - } + return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext ); } public ResultSetWrapper getResultSetWrapper() { - return null; + return resultSetWrapper; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; } public SqlStatementLogger getSqlStatementLogger() { @@ -98,65 +107,78 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices { } public SqlExceptionHelper getSqlExceptionHelper() { - return exceptionHelper; + return jdbcEnvironment.exceptionHelper; } public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { - return metaDataSupport; + return jdbcEnvironment.extractedDatabaseMetaData; } - private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData { - @Override - public boolean supportsRefCursors() { - return false; + private static class TestingJdbcEnvironmentImpl implements JdbcEnvironment { + private final ExtractedDatabaseMetaData extractedDatabaseMetaData = new ExtractedDatabaseMetaDataImpl( this ); + private final SqlExceptionHelper exceptionHelper = new SqlExceptionHelper(); + private final LobCreatorBuilder lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(); + + private ConnectionProvider connectionProvider; + private Dialect dialect; + + private TestingJdbcEnvironmentImpl(boolean allowAggressiveRelease) { + connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); + dialect = ConnectionProviderBuilder.getCorrespondingDialect(); } @Override - public boolean supportsNamedParameters() { - return false; + public Dialect getDialect() { + return dialect; } - public boolean supportsScrollableResults() { - return false; + @Override + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() { + return extractedDatabaseMetaData; } - public boolean supportsGetGeneratedKeys() { - return false; + @Override + public Identifier getCurrentCatalog() { + return null; } - public boolean supportsBatchUpdates() { - return false; + @Override + public Identifier getCurrentSchema() { + return null; } - public boolean supportsDataDefinitionInTransaction() { - return false; + @Override + public QualifiedObjectNameSupport getQualifiedObjectNameSupport() { + return null; } - public boolean doesDataDefinitionCauseTransactionCommit() { - return false; + @Override + public IdentifierHelper getIdentifierHelper() { + return null; } - public Set getExtraKeywords() { + @Override + public Set getReservedWords() { return Collections.emptySet(); } - public SQLStateType getSqlStateType() { - return SQLStateType.UNKOWN; + @Override + public SqlExceptionHelper getSqlExceptionHelper() { + return exceptionHelper; } - public boolean doesLobLocatorUpdateCopy() { - return false; + @Override + public LobCreatorBuilder getLobCreatorBuilder() { + return lobCreatorBuilder; } - public String getConnectionSchemaName() { + @Override + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) { return null; } - public String getConnectionCatalogName() { - return null; - } - - public LinkedHashSet getTypeInfoSet() { + @Override + public ServiceRegistry getServiceRegistry() { return null; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java index fdf1ee9281..220d85ce5c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java @@ -38,6 +38,7 @@ public class ComponentJoinsTest extends BaseCoreFunctionalTestCase { @Override public Class[] getAnnotatedClasses() { return new Class[] { + Name.class, Person.class, Component.class, Component.Emb.Stuff.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java index b329a6a0e3..d9fb46b0d6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java @@ -120,6 +120,7 @@ public class SuppliedConnectionTest extends ConnectionManagementTestCase { return false; } + /* @Override protected void prepareTest() throws Exception { super.prepareTest(); @@ -155,4 +156,52 @@ public class SuppliedConnectionTest extends ConnectionManagementTestCase { } super.cleanupTest(); } + */ + + @Override + protected void prepareTest() throws Exception { + super.prepareTest(); + Connection conn = cp.getConnection(); + try { + if ( isMetadataUsed() ) { + new SchemaExport( metadata(), conn ).create( false, true ); + } + else { + new SchemaExport( configuration(), conn ).create( false, true ); + } + } + finally { + if ( conn != null ) { + try { + cp.closeConnection( conn ); + } + catch( Throwable ignore ) { + } + } + } + } + + @Override + protected void cleanupTest() throws Exception { + Connection conn = cp.getConnection(); + try { + if ( isMetadataUsed() ) { + new SchemaExport( metadata(), conn ).drop( false, true ); + } + else { + new SchemaExport( configuration(), conn ).drop( false, true ); + } + } + finally { + if ( conn != null ) { + try { + cp.closeConnection( conn ); + } + catch( Throwable ignore ) { + } + } + } + super.cleanupTest(); + } + } diff --git a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java index 6a7fa9044a..eaf0647f65 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java @@ -1,6 +1,6 @@ -/* +/* * Hibernate, Relational Persistence for Idiomatic Java - * + * * JBoss, Home of Professional Open Source * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. @@ -40,6 +40,7 @@ import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.mapping.Column; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.UniqueKey; @@ -52,11 +53,11 @@ import org.junit.Test; * @author Brett Meyer */ public class ConstraintTest extends BaseCoreFunctionalTestCase { - + private static final int MAX_NAME_LENGTH = 30; - + private static final String EXPLICIT_UK_NAME = "EXPLICIT_UK_NAME"; - + private static final String EXPLICIT_COLUMN_NAME_NATIVE = "EXPLICIT_COLUMN_NAME_NATIVE"; private static final String EXPLICIT_FK_NAME_NATIVE = "EXPLICIT_FK_NAME_NATIVE"; private static final String EXPLICIT_COLUMN_NAME_JPA_O2O = "EXPLICIT_COLUMN_NAME_JPA_O2O"; @@ -67,17 +68,20 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase { private static final String EXPLICIT_FK_NAME_JPA_M2M = "EXPLICIT_FK_NAME_JPA_M2M"; private static final String EXPLICIT_COLUMN_NAME_JPA_ELEMENT = "EXPLICIT_COLUMN_NAME_JPA_ELEMENT"; private static final String EXPLICIT_FK_NAME_JPA_ELEMENT = "EXPLICIT_FK_NAME_JPA_ELEMENT"; - + @Override protected Class[] getAnnotatedClasses() { return new Class[] { DataPoint.class, DataPoint2.class }; } - + @Test @TestForIssue( jiraKey = "HHH-7797" ) public void testUniqueConstraints() { + if ( isMetadataUsed() ) { + throw new NotYetImplementedException( "Test case does not work with new metamodel yet." ); + } Column column = (Column) configuration().getClassMapping( DataPoint.class.getName() ) .getProperty( "foo1" ).getColumnIterator().next(); assertFalse( column.isNullable() ); @@ -93,20 +97,23 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase { assertFalse( column.isNullable() ); assertTrue( column.isUnique() ); } - + @Test @FailureExpected(jiraKey = "HHH-8862") public void testConstraintNames() { + if ( isMetadataUsed() ) { + throw new NotYetImplementedException( "Test case does not work with new metamodel yet." ); + } Iterator tableItr = configuration().getTableMappings(); int foundCount = 0; while (tableItr.hasNext()) { org.hibernate.mapping.Table table = tableItr.next(); - + Iterator fkItr = table.getForeignKeyIterator(); while (fkItr.hasNext()) { ForeignKey fk = (ForeignKey) fkItr.next(); assertTrue( fk.getName().length() <= MAX_NAME_LENGTH ); - + // ensure the randomly generated constraint name doesn't // happen if explicitly given Iterator cItr = fk.columnIterator(); @@ -134,12 +141,12 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase { } } } - + Iterator ukItr = table.getUniqueKeyIterator(); while (ukItr.hasNext()) { UniqueKey uk = (UniqueKey) ukItr.next(); assertTrue( uk.getName().length() <= MAX_NAME_LENGTH ); - + // ensure the randomly generated constraint name doesn't // happen if explicitly given Column column = uk.getColumn( 0 ); @@ -149,10 +156,10 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase { } } } - + assertEquals("Could not find the necessary columns.", 5, foundCount); } - + @Entity @Table( name = "DataPoint", uniqueConstraints = { @UniqueConstraint( name = EXPLICIT_UK_NAME, columnNames = { "explicit" } ) @@ -162,53 +169,53 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase { @GeneratedValue @javax.persistence.Column( nullable = false, unique = true) public long id; - + @javax.persistence.Column( nullable = false, unique = true) public String foo1; - + @javax.persistence.Column( nullable = true, unique = true) public String foo2; - + public String explicit; } - + @Entity @Table( name = "DataPoint2" ) public static class DataPoint2 { @Id @GeneratedValue public long id; - + @OneToOne public DataPoint dp; - + @OneToOne @org.hibernate.annotations.ForeignKey(name = EXPLICIT_FK_NAME_NATIVE) @JoinColumn(name = EXPLICIT_COLUMN_NAME_NATIVE) public DataPoint explicit_native; - + @OneToOne @JoinColumn(name = EXPLICIT_COLUMN_NAME_JPA_O2O, foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_JPA_O2O)) public DataPoint explicit_jpa_o2o; - + @ManyToOne @JoinColumn(name = EXPLICIT_COLUMN_NAME_JPA_M2O, foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_JPA_M2O)) private DataPoint explicit_jpa_m2o; - + @ManyToMany @JoinTable(joinColumns = @JoinColumn(name = EXPLICIT_COLUMN_NAME_JPA_M2M), foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_JPA_M2M)) private Set explicit_jpa_m2m; - + @ElementCollection @CollectionTable(joinColumns = @JoinColumn(name = EXPLICIT_COLUMN_NAME_JPA_ELEMENT), foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_JPA_ELEMENT)) private Set explicit_jpa_element; } - + public static enum SimpleEnum { FOO1, FOO2, FOO3; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java index 0bf8f0d0f0..c2c803d946 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java @@ -32,6 +32,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -44,6 +45,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class CompositePropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "cuk/Person.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java index f39f1362e1..472de2eeb1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java @@ -33,6 +33,8 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Property; import org.hibernate.criterion.Restrictions; +import org.hibernate.mapping.MetadataSource; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -49,7 +51,7 @@ import static org.junit.Assert.assertTrue; public class SimpleInheritanceTest extends BaseCoreFunctionalTestCase { public void configure(Configuration cfg) { super.configure( cfg ); - cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); + cfg.setProperty( MetadataSources.USE_NEW_METADATA_MAPPINGS, "true"); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java index 5519b773e5..852315860f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java @@ -1,5 +1,6 @@ package org.hibernate.test.dynamicentity.tuplizer; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; @@ -16,6 +17,10 @@ public class MyEntityTuplizer extends PojoEntityTuplizer { super( entityMetamodel, mappedEntity ); } + public MyEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding entityBinding) { + super( entityMetamodel, entityBinding); + } + protected Instantiator buildInstantiator(PersistentClass persistentClass) { return new MyEntityInstantiator( persistentClass.getEntityName() ); } @@ -27,4 +32,15 @@ public class MyEntityTuplizer extends PojoEntityTuplizer { // Here we simply use the default... return super.buildProxyFactory( persistentClass, idGetter, idSetter ); } + + @Override + protected Instantiator buildInstantiator(EntityBinding entityBinding) { + return new MyEntityInstantiator( entityBinding.getEntityName() ); + } + + @Override + protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + return super.buildProxyFactory( entityBinding, idGetter, idSetter ); + } + } diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java index cb993c2e37..95337141f1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java @@ -36,6 +36,7 @@ import org.hibernate.test.dynamicentity.Company; import org.hibernate.test.dynamicentity.Customer; import org.hibernate.test.dynamicentity.Person; import org.hibernate.test.dynamicentity.ProxyHelper; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -65,6 +66,7 @@ public class ImprovedTuplizerDynamicEntityTest extends BaseCoreFunctionalTestCas @Test @SuppressWarnings( {"unchecked"}) + @FailureExpectedWithNewMetamodel public void testIt() { // Test saving these dyna-proxies Session session = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java index 80b971ab19..025be9e997 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java @@ -26,7 +26,7 @@ package org.hibernate.test.dynamicentity.tuplizer2; import org.hibernate.EntityNameResolver; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; @@ -57,6 +57,10 @@ public class MyEntityTuplizer extends PojoEntityTuplizer { return new MyEntityInstantiator( persistentClass.getEntityName() ); } + protected Instantiator buildInstantiator(EntityBinding persistentClass) { + return new MyEntityInstantiator( persistentClass.getEntityName() ); + } + public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) { String entityName = ProxyHelper.extractEntityName( entityInstance ); if ( entityName == null ) { @@ -73,6 +77,14 @@ public class MyEntityTuplizer extends PojoEntityTuplizer { return super.buildProxyFactory( persistentClass, idGetter, idSetter ); } + protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + // allows defining a custom proxy factory, which is responsible for + // generating lazy proxies for a given entity. + // + // Here we simply use the default... + return super.buildProxyFactory( entityBinding, idGetter, idSetter ); + } + public static class MyEntityNameResolver implements EntityNameResolver { public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/basic/DynamicClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/basic/DynamicClassTest.java index 29a0582eb4..1b3ff06bfc 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/basic/DynamicClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/basic/DynamicClassTest.java @@ -36,6 +36,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -45,6 +46,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class DynamicClassTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java index 4345555f3a..4573447b00 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java @@ -28,11 +28,13 @@ import java.util.HashMap; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class SubclassDynamicMapTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java index 1f2b2cd7e0..81d7acab3b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java @@ -51,7 +51,7 @@ import org.hibernate.event.spi.PreCollectionRemoveEventListener; import org.hibernate.event.spi.PreCollectionUpdateEvent; import org.hibernate.event.spi.PreCollectionUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java index acf281804b..94e1f4f030 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java @@ -38,7 +38,7 @@ import org.hibernate.event.spi.DeleteEvent; import org.hibernate.event.spi.DeleteEventListener; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java index a843d481b0..65eaf40b0a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java @@ -34,7 +34,7 @@ import org.hibernate.event.spi.ClearEvent; import org.hibernate.event.spi.ClearEventListener; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java b/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java index b86bf36cfa..9103f0f380 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java +++ b/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java @@ -43,7 +43,7 @@ import org.hibernate.event.spi.PreUpdateEvent; import org.hibernate.event.spi.PreUpdateEventListener; import org.hibernate.integrator.spi.Integrator; import org.hibernate.internal.SessionImpl; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.TestForIssue; diff --git a/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java b/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java index 8170107e61..f120d2b017 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java +++ b/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java @@ -35,7 +35,7 @@ import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.PreUpdateEvent; import org.hibernate.event.spi.PreUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java index de3f0728ea..fa02b5e1d4 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java @@ -31,6 +31,7 @@ import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -40,6 +41,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class FormulaJoinTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "formulajoin/Master.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java index d6aed4a5b6..e528427a81 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java @@ -80,6 +80,7 @@ import org.hibernate.test.cid.Order; import org.hibernate.test.cid.Product; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -115,6 +116,7 @@ import static org.junit.Assert.fail; comment = "As of verion 8.4.1 CUBRID doesn't support temporary tables. This test fails with" + "HibernateException: cannot doAfterTransactionCompletion multi-table deletes using dialect not supporting temp tables" ) +@FailureExpectedWithNewMetamodel public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { private static final Logger log = Logger.getLogger( ASTParserLoadingTest.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java index 100047ffe4..2bd1616917 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java @@ -45,6 +45,7 @@ import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.IdentifierGenerator; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.SkipLog; @@ -57,6 +58,7 @@ import org.junit.Test; * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class BulkManipulationTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { @@ -687,6 +689,7 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { @SuppressWarnings( {"unchecked"}) @Test + @FailureExpectedWithNewMetamodel public void testUpdateWithWhereExistsSubquery() { // multi-table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Session s = openSession(); @@ -1346,6 +1349,7 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-8476" ) + @FailureExpectedWithNewMetamodel public void testManyToManyBulkDelete() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java index bc00e31e45..1e27e322b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java @@ -29,6 +29,7 @@ import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * Some simple test queries using the classic translator explicitly @@ -38,6 +39,7 @@ import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ClassicTranslatorTest extends QueryTranslatorTestCase { @Override public void configure(Configuration cfg) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java index 12b18a5030..4253efc356 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java @@ -34,6 +34,7 @@ import org.hibernate.hql.internal.ast.QueryTranslatorImpl; import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.BigDecimalType; import org.hibernate.type.BigIntegerType; import org.hibernate.type.DoubleType; @@ -46,6 +47,7 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class CriteriaClassicAggregationReturnTest extends QueryTranslatorTestCase { @Override public void configure(Configuration cfg) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java index aed3032336..d941467541 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java @@ -39,6 +39,7 @@ import org.hibernate.hql.internal.ast.QueryTranslatorImpl; import org.hibernate.hql.internal.ast.util.ASTUtil; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static junit.framework.Assert.assertEquals; @@ -47,6 +48,7 @@ import static junit.framework.Assert.assertTrue; /** * @author Alexey Loubyansky */ +@FailureExpectedWithNewMetamodel public class EJBQLTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java index 8705bc3819..f93e8ac64a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java @@ -70,6 +70,7 @@ import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; @@ -88,6 +89,7 @@ import static org.junit.Assert.assertTrue; * * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class HQLTest extends QueryTranslatorTestCase { @Override public boolean createSchema() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java index e470e2cbfc..52b3815cd1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java @@ -36,6 +36,7 @@ import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.hql.internal.ast.InvalidWithClauseException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -51,6 +52,7 @@ public class WithClauseTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testWithClauseFailsWithFetch() { TestData data = new TestData(); data.prepare(); @@ -106,6 +108,7 @@ public class WithClauseTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testWithClause() { TestData data = new TestData(); data.prepare(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java b/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java index 27e89ab67e..adfa006082 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java @@ -31,6 +31,7 @@ import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel( message = " not supported" ) public class IdBagTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java index 37af55a267..f003468dd3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java @@ -30,6 +30,7 @@ import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -37,6 +38,7 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class IdentifierPropertyReferencesTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java index 838204dc5d..88a4403156 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java @@ -35,6 +35,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.criterion.Projections; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.AbstractSingleColumnStandardBasicType; import org.hibernate.type.TextType; @@ -51,6 +52,7 @@ import static org.junit.Assert.fail; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class ImmutableTest extends BaseCoreFunctionalTestCase { private static class TextAsMaterializedClobType extends AbstractSingleColumnStandardBasicType { public final static TextAsMaterializedClobType INSTANCE = new TextAsMaterializedClobType(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java index f87c8de092..dbd5d57e7a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java @@ -32,6 +32,7 @@ import org.hibernate.bytecode.spi.BytecodeProvider; import org.hibernate.bytecode.spi.InstrumentedClassLoader; import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.MySQLDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.ClassLoadingIsolater; diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java index ab836a61ba..1b9f601b97 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java @@ -14,6 +14,7 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; import org.hibernate.persister.entity.Loadable; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -75,6 +76,7 @@ public class JoinedSubclassWithExplicitDiscriminatorTest extends BaseCoreFunctio } @Test + @FailureExpectedWithNewMetamodel public void metadataAssertions() { EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() ); assertNotNull( p ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java index 95b1337917..44c3c3971d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java @@ -16,6 +16,7 @@ import org.hibernate.cfg.Ejb3DiscriminatorColumn; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -78,6 +79,7 @@ public class JoinedSubclassWithImplicitDiscriminatorTest extends BaseCoreFunctio } @Test + @FailureExpectedWithNewMetamodel public void metadataAssertions() { EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() ); assertNotNull( p ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java index 06ec5a95ea..f3bcb7d636 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java @@ -44,7 +44,7 @@ import org.hibernate.event.spi.FlushEntityEventListener; import org.hibernate.event.spi.FlushEventListener; import org.hibernate.event.spi.PersistEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java index 6b22592a89..09ff2a438e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java @@ -36,9 +36,10 @@ import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.LoadEvent; import org.hibernate.event.spi.LoadEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -49,6 +50,7 @@ import static org.junit.Assert.fail; * @author Steve Ebersole */ @SuppressWarnings( {"unchecked"}) +@FailureExpectedWithNewMetamodel public class EagerKeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java index 3d73a4e692..c0bbdd78e2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,6 +37,7 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class LazyKeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java index 350f93713c..04e20506a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java @@ -32,6 +32,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class KeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/ondelete/KeyManyToOneCascadeDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/ondelete/KeyManyToOneCascadeDeleteTest.java index a76ea49571..e5f26471d1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/ondelete/KeyManyToOneCascadeDeleteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/ondelete/KeyManyToOneCascadeDeleteTest.java @@ -29,6 +29,7 @@ import org.junit.Assert; import org.junit.Test; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -37,6 +38,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @RequiresDialectFeature(DialectChecks.SupportsCascadeDeleteCheck.class) +@FailureExpectedWithNewMetamodel public class KeyManyToOneCascadeDeleteTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/unidir/ondelete/KeyManyToOneCascadeDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/unidir/ondelete/KeyManyToOneCascadeDeleteTest.java index f69dc98e9e..94cd3e16ce 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/unidir/ondelete/KeyManyToOneCascadeDeleteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/unidir/ondelete/KeyManyToOneCascadeDeleteTest.java @@ -29,6 +29,7 @@ import org.junit.Assert; import org.junit.Test; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -37,6 +38,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @RequiresDialectFeature(DialectChecks.SupportsCascadeDeleteCheck.class) +@FailureExpectedWithNewMetamodel public class KeyManyToOneCascadeDeleteTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java index 3d638bb855..adb75c0dc3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java @@ -29,6 +29,9 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -75,14 +78,29 @@ public class ABCTest extends LegacyTestCase { @Test public void testHigherLevelIndexDefinition() throws Throwable { - String[] commands = configuration().generateSchemaCreationScript( getDialect() ); - int max = commands.length; boolean found = false; - for (int indx = 0; indx < max; indx++) { - System.out.println("Checking command : " + commands[indx]); - found = commands[indx].indexOf("create index indx_a_name") >= 0; - if (found) - break; + if ( isMetadataUsed() ) { + for ( Schema schema : metadata().getDatabase().getSchemas() ) { + for ( Table table : schema.getTables() ) { + for ( Index index : table.getIndexes() ) { + if ( index.getName().equals( "indx_a_name" ) ) { + found = true; + break; + } + } + } + } + } + else { + String[] commands = configuration().generateSchemaCreationScript( getDialect() ); + int max = commands.length; + for (int indx = 0; indx < max; indx++) { + System.out.println("Checking command : " + commands[indx]); + found = commands[indx].indexOf("create index indx_a_name") >= 0; + if ( found ) { + break; + } + } } assertTrue("Unable to locate indx_a_name index creation", found); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java index 95eddbb564..8969794ac8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java @@ -31,6 +31,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.fail; @@ -39,6 +40,7 @@ import static org.junit.Assert.fail; * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ComponentNotNullTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java index c7bd7511be..409098b4cf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.testing.DialectCheck; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -25,6 +26,7 @@ import static org.junit.Assert.assertTrue; * @author MAX * */ +@FailureExpectedWithNewMetamodel public class CustomSQLTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java index c56710181b..6c475a6a94 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java @@ -96,6 +96,7 @@ import org.hibernate.jdbc.AbstractWork; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -105,6 +106,7 @@ import org.hibernate.type.StandardBasicTypes; import org.jboss.logging.Logger; import org.junit.Test; +@FailureExpectedWithNewMetamodel public class FooBarTest extends LegacyTestCase { private static final Logger log = Logger.getLogger( FooBarTest.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java index c944b67d4c..b4837de534 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java @@ -42,6 +42,7 @@ import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.PointbaseDialect; import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.dialect.TimesTenDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.transform.Transformers; import org.hibernate.type.CalendarType; @@ -51,6 +52,7 @@ import org.hibernate.type.StringType; import org.hibernate.type.Type; import org.junit.Test; +@FailureExpectedWithNewMetamodel public class FumTest extends LegacyTestCase { private static short fumKeyShort = 1; diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java index 103d05eb01..8ab1495ce6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java @@ -35,9 +35,11 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Example; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertTrue; +@FailureExpectedWithNewMetamodel public class MapTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java index fd155405d7..10faf3f6be 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java @@ -49,13 +49,15 @@ import org.hibernate.dialect.SAPDBDialect; import org.hibernate.jdbc.AbstractWork; import org.hibernate.mapping.MetaAttribute; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipLog; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; - +@FailureExpectedWithNewMetamodel public class MasterDetailTest extends LegacyTestCase { @Override public String[] getMappings() { @@ -102,11 +104,20 @@ public class MasterDetailTest extends LegacyTestCase { @Test public void testMeta() throws Exception { - PersistentClass clazz = configuration().getClassMapping( Master.class.getName() ); - MetaAttribute meta = clazz.getMetaAttribute("foo"); - assertTrue( "foo".equals( meta.getValue() ) ); - meta = clazz.getProperty("name").getMetaAttribute("bar"); - assertTrue( meta.isMultiValued() ); + if ( isMetadataUsed() ) { + EntityBinding binding = metadata().getEntityBinding( Master.class.getName() ); + org.hibernate.metamodel.spi.binding.MetaAttribute meta = binding.getMetaAttributeContext().getMetaAttribute("foo"); + assertTrue( "foo".equals( meta.getValue() ) ); + meta = binding.getMetaAttributeContext().getMetaAttribute("bar"); + assertTrue( meta.isMultiValued() ); + } + else { + PersistentClass clazz = configuration().getClassMapping( Master.class.getName() ); + MetaAttribute meta = clazz.getMetaAttribute("foo"); + assertTrue( "foo".equals( meta.getValue() ) ); + meta = clazz.getProperty("name").getMetaAttribute("bar"); + assertTrue( meta.isMultiValued() ); + } } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java index 875ca2598e..1447305ad7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java @@ -54,6 +54,7 @@ import org.hibernate.internal.SessionImpl; import org.hibernate.jdbc.AbstractWork; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.StandardBasicTypes; import static org.junit.Assert.assertEquals; @@ -63,7 +64,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - +@FailureExpectedWithNewMetamodel public class ParentChildTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java index 78a9151f0f..64e72c92e9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java @@ -63,6 +63,7 @@ import org.hibernate.persister.entity.OuterJoinLoadable; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -77,7 +78,14 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Customer.class }; + return new Class[] { + Person.class, + Customer.class, + Address.class, + AddressType.class, + Investment.class, + MonetaryAmount.class + }; } @Test @@ -164,6 +172,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo } @Test + @FailureExpectedWithNewMetamodel public void testNestedCompositeElementCollectionProcessing() throws Exception { // create some test data Session session = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java index 15fc3816a6..6a4cc1a089 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java @@ -46,6 +46,7 @@ import org.hibernate.loader.plan.exec.query.spi.NamedParameterContext; import org.hibernate.loader.plan.exec.spi.LoadQueryDetails; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.Type; import org.junit.Test; @@ -119,6 +120,7 @@ public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunct } @Test + @FailureExpectedWithNewMetamodel public void testCompositeIdWithKeyManyToOne() throws Exception { final String cardId = "ace-of-spades"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java index 3694d91430..58b6710dda 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java @@ -52,6 +52,7 @@ import org.hibernate.persister.entity.EntityPersister; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -63,6 +64,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gail Badner */ +@FailureExpectedWithNewMetamodel public class EntityWithNonLazyCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java index 859a6cdf28..a3da0e03b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java @@ -50,6 +50,7 @@ import org.hibernate.persister.entity.EntityPersister; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -69,6 +70,7 @@ public class EntityWithNonLazyOneToManyListResultSetProcessorTest extends BaseCo } @Test + @FailureExpectedWithNewMetamodel public void testEntityWithList() throws Exception { final EntityPersister entityPersister = sessionFactory().getEntityPersister( Poster.class.getName() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java index 13f866ad6d..48e0b88622 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java @@ -52,6 +52,7 @@ import org.hibernate.persister.entity.EntityPersister; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -64,6 +65,7 @@ import static org.junit.Assert.fail; /** * @author Gail Badner */ +@FailureExpectedWithNewMetamodel public class EntityWithNonLazyOneToManySetResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/NonEncapsulatedCompositeIdResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/NonEncapsulatedCompositeIdResultSetProcessorTest.java index 388233493b..82c6f4d1dd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/NonEncapsulatedCompositeIdResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/NonEncapsulatedCompositeIdResultSetProcessorTest.java @@ -41,6 +41,7 @@ import org.hibernate.loader.plan.exec.query.spi.NamedParameterContext; import org.hibernate.loader.plan.exec.spi.LoadQueryDetails; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.Type; import org.junit.Test; @@ -55,6 +56,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class NonEncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/KeyManyToOneWalkingTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/KeyManyToOneWalkingTest.java index d47e424c45..3ad33df6a5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/KeyManyToOneWalkingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/KeyManyToOneWalkingTest.java @@ -28,12 +28,14 @@ import org.hibernate.persister.walking.spi.MetamodelGraphWalker; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.onetoone.formula.Address; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class KeyManyToOneWalkingTest extends BaseCoreFunctionalTestCase { @Override protected String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java index 40621e7b40..a841547b21 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java @@ -28,6 +28,7 @@ import org.hibernate.persister.walking.spi.MetamodelGraphWalker; import org.junit.Test; +import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Person; import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Customer; @@ -38,7 +39,14 @@ import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResult public class NestedCompositeElementTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Customer.class }; + return new Class[] { + Person.class, + Customer.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.Address.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.AddressType.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.Investment.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.MonetaryAmount.class + }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java b/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java index 642bfa2387..0bcd7b8d81 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.Locale; import org.hibernate.HibernateException; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; @@ -64,15 +65,20 @@ public class LocaleTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-8765") public void testMetadataWithLocale() { - SchemaValidator sv = new SchemaValidator( configuration() ); - try { - // Rather than building TableMetadata and checking for ascii values in table/column names, simply - // attempt to validate. - sv.validate(); + if ( isMetadataUsed() ) { + fail( "SchemaValidator is not supported using new metamodel yet." ); } - catch (HibernateException e) { - fail("Failed with the Turkish locale, most likely due to the use of String#toLowerCase() within hbm2ddl. " - + "Search for all instaces and replace with StringHelper#toLowerCase(String)! " + e.getMessage()); + else { + SchemaValidator sv = new SchemaValidator( configuration() ); + try { + // Rather than building TableMetadata and checking for ascii values in table/column names, simply + // attempt to validate. + sv.validate(); + } + catch (HibernateException e) { + fail("Failed with the Turkish locale, most likely due to the use of String#toLowerCase() within hbm2ddl. " + + "Search for all instaces and replace with StringHelper#toLowerCase(String)! " + e.getMessage()); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java index 0eacb416da..6d56207750 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; import org.hibernate.test.manytomanyassociationclass.Membership; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.fail; @@ -50,6 +51,7 @@ public class ManyToManyAssociationClassGeneratedIdTest extends AbstractManyToMan } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualElement() { deleteMembership( getUser(), getGroup(), getMembership() ); addMembership( getUser(), getGroup(), createMembership( "membership" ) ); @@ -76,6 +78,7 @@ public class ManyToManyAssociationClassGeneratedIdTest extends AbstractManyToMan } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualCollection() { deleteMembership( getUser(), getGroup(), getMembership() ); getUser().setMemberships( new HashSet() ); @@ -104,6 +107,7 @@ public class ManyToManyAssociationClassGeneratedIdTest extends AbstractManyToMan } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualElementNonKeyModified() { deleteMembership( getUser(), getGroup(), getMembership() ); Membership membershipNew = createMembership( "membership" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java index 92b7db6bfd..3f0ac2deb9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java @@ -30,6 +30,9 @@ import java.util.Iterator; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -45,6 +48,7 @@ import org.junit.Test; * * @author Brett Meyer */ +@FailureExpectedWithNewMetamodel public class AliasTest extends BaseCoreFunctionalTestCase { /** @@ -57,20 +61,27 @@ public class AliasTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-2448" ) public void testAliasOrdering() { - Iterator
tables = configuration().getTableMappings(); - Table table1 = null; - Table table2 = null; - while ( tables.hasNext() ) { - Table table = tables.next(); - if ( table.getName().equals( "Table1" ) ) { - table1 = table; - } - else if ( table.getName().equals( "Table2" ) ) { - table2 = table; - } + if ( isMetadataUsed() ) { + TableSpecification table1 = SchemaUtil.getTable( "Table1", metadata() ); + TableSpecification table2 = SchemaUtil.getTable( "Table2", metadata() ); + assertTrue( table1.getTableNumber() < table2.getTableNumber() ); + } + else { + Iterator
tables = configuration().getTableMappings(); + Table table1 = null; + Table table2 = null; + while ( tables.hasNext() ) { + Table table = tables.next(); + if ( table.getName().equals( "Table1" ) ) { + table1 = table; + } + else if ( table.getName().equals( "Table2" ) ) { + table2 = table; + } + } + + assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() ); } - - assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java index 08fe660213..fb55a4b860 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java @@ -20,9 +20,12 @@ */ package org.hibernate.test.mapping; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Brett Meyer */ +@FailureExpectedWithNewMetamodel public class MappingReorderedAliasTest extends AliasTest { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java index 2b63545666..79cb574fc2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java @@ -28,10 +28,18 @@ import org.junit.Test; import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard @@ -60,18 +68,58 @@ public class NamingStrategyTest extends BaseCoreFunctionalTestCase { @Test public void testDatabaseColumnNames() { - PersistentClass classMapping = configuration().getClassMapping( Customers.class.getName() ); - Column stateColumn = (Column) classMapping.getProperty( "specified_column" ).getColumnIterator().next(); - assertEquals( "CN_specified_column", stateColumn.getName() ); + if ( isMetadataUsed() ) { + EntityBinding entityBinding = metadata().getEntityBinding( Customers.class.getName() ); + assertNotNull( entityBinding ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "specified_column" ); + assertNotNull( attributeBinding ); + assertTrue( SingularAttributeBinding.class.isInstance( attributeBinding ) ); + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) valueBinding + .getValue(); + assertEquals( "CN_specified_column", column.getColumnName().getText() ); + } + else { + PersistentClass classMapping = configuration().getClassMapping( Customers.class.getName() ); + Column stateColumn = (Column) classMapping.getProperty( "specified_column" ).getColumnIterator().next(); + assertEquals( "CN_specified_column", stateColumn.getName() ); + } } @Test @TestForIssue(jiraKey = "HHH-5848") public void testDatabaseTableNames() { - PersistentClass classMapping = configuration().getClassMapping( Item.class.getName() ); - Column secTabColumn = (Column) classMapping.getProperty( "specialPrice" ).getColumnIterator().next(); - assertEquals( "TAB_ITEMS_SEC", secTabColumn.getValue().getTable().getName() ); - Column tabColumn = (Column) classMapping.getProperty( "price" ).getColumnIterator().next(); - assertEquals( "TAB_ITEMS", tabColumn.getValue().getTable().getName() ); + if ( isMetadataUsed() ) { + EntityBinding entityBinding = metadata().getEntityBinding( Item.class.getName() ); + assertNotNull( entityBinding ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "specialPrice" ); + assertNotNull( attributeBinding ); + assertTrue( SingularAttributeBinding.class.isInstance( attributeBinding ) ); + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + Table table = (Table)valueBinding.getTable(); + + assertEquals( "TAB_ITEMS_SEC", table.getPhysicalName().getText() ); + + singularAttributeBinding = (SingularAttributeBinding)entityBinding.locateAttributeBinding( "price" ); + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + table = (Table)valueBinding.getTable(); + assertEquals( "TAB_ITEMS", table.getPhysicalName().getText()); + + } + else { + PersistentClass classMapping = configuration().getClassMapping( Item.class.getName() ); + Column secTabColumn = (Column) classMapping.getProperty( "specialPrice" ).getColumnIterator().next(); + assertEquals( "TAB_ITEMS_SEC", secTabColumn.getValue().getTable().getName() ); + Column tabColumn = (Column) classMapping.getProperty( "price" ).getColumnIterator().next(); + assertEquals( "TAB_ITEMS", tabColumn.getValue().getTable().getName() ); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java b/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java index 6dfcd164e5..a723e973a2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java @@ -35,8 +35,10 @@ import javax.persistence.Lob; import org.hibernate.annotations.Nationalized; import org.hibernate.annotations.Type; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.CharacterNCharType; import org.hibernate.type.MaterializedNClobType; @@ -48,6 +50,7 @@ import org.junit.Test; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class SimpleNationalizedTest extends BaseUnitTestCase { @Entity( name="NationalizedEntity") @@ -78,6 +81,9 @@ public class SimpleNationalizedTest extends BaseUnitTestCase { @Test public void simpleNationalizedTest() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAnnotatedClass( NationalizedEntity.class ); cfg.buildMappings(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java index 86b591c28a..0d9cb03a77 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java @@ -27,6 +27,8 @@ import org.junit.Test; import org.hibernate.AnnotationException; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -36,9 +38,13 @@ import static org.junit.Assert.fail; * @author Steve Ebersole */ @TestForIssue( jiraKey = "HHH-7129" ) +@FailureExpectedWithNewMetamodel public class SpreadNaturalIdTest extends BaseUnitTestCase { @Test public void testSpreadNaturalIdDeclarationGivesMappingException() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration() .addAnnotatedClass( Principal.class ) .addAnnotatedClass( User.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java index d4f97be72e..3e544e80e2 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java @@ -33,6 +33,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Property; import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.AbstractSingleColumnStandardBasicType; import org.hibernate.type.TextType; @@ -48,6 +49,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class OneToOneFormulaTest extends BaseCoreFunctionalTestCase { private static class TextAsMaterializedClobType extends AbstractSingleColumnStandardBasicType { public final static TextAsMaterializedClobType INSTANCE = new TextAsMaterializedClobType(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java index 215c0886c1..79918f6493 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java @@ -11,6 +11,7 @@ import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.stat.EntityStatistics; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -19,6 +20,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class DynamicMapOneToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java index 61c73d8a11..1da109a60c 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java @@ -29,6 +29,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.metamodel.MetadataSources; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -40,7 +41,7 @@ import static org.junit.Assert.assertTrue; public class SimpleOpsTest extends AbstractOperationTestCase { public void configure(Configuration cfg) { super.configure( cfg ); - cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); + cfg.setProperty( MetadataSources.USE_NEW_METADATA_MAPPINGS, "true"); } public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java index 9a31f474e6..febc1415f1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java @@ -40,7 +40,7 @@ import org.junit.Test; public class DoesNotWorkTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {DoesNotWork.class}; + return new Class[] { DoesNotWork.class, DoesNotWorkPk.class }; } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java index 4e973472f9..3303c4b4ee 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java @@ -32,6 +32,7 @@ import org.hibernate.Session; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.H2Dialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -39,6 +40,7 @@ import org.junit.Test; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel @RequiresDialect(H2Dialect.class) public class DoesNotWorkWithHbmTest extends BaseCoreFunctionalTestCase { diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java index 35750de714..8fd337a0f1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java @@ -37,6 +37,10 @@ import org.hibernate.cfg.Environment; import org.hibernate.mapping.Column; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -101,6 +105,7 @@ public class PropertyRefTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testManyToManyPropertyRef() { // prepare some test data relating to the Group->Person many-to-many association Session s = openSession(); @@ -271,24 +276,38 @@ public class PropertyRefTest extends BaseCoreFunctionalTestCase { @Test public void testForeignKeyCreation() { - PersistentClass classMapping = configuration().getClassMapping("org.hibernate.test.propertyref.basic.Account"); - - Iterator foreignKeyIterator = classMapping.getTable().getForeignKeyIterator(); boolean found = false; - while ( foreignKeyIterator.hasNext() ) { - ForeignKey element = (ForeignKey) foreignKeyIterator.next(); - if(element.getReferencedEntityName().equals(Person.class.getName() ) ) { - - if(!element.isReferenceToPrimaryKey() ) { - List referencedColumns = element.getReferencedColumns(); - Column column = (Column) referencedColumns.get(0); - if(column.getName().equals("person_userid") ) { - found = true; // extend test to include the columns - } + if ( isMetadataUsed() ) { + TableSpecification table = SchemaUtil.getTable( Account.class, metadata() ); + EntityBinding personEntityBinding = metadata().getEntityBinding( Person.class.getName() ); + for ( org.hibernate.metamodel.spi.relational.ForeignKey element : table.getForeignKeys() ) { + if ( element.getTargetTable().equals( personEntityBinding.getPrimaryTable() ) ) { + for ( org.hibernate.metamodel.spi.relational.Column column : element.getTargetColumns() ) { + if ( column.getColumnName().getText( getDialect() ).equals( "person_userid" ) ) { + found = true; + } + } + } + } + } + else { + PersistentClass classMapping = configuration().getClassMapping("org.hibernate.test.propertyref.basic.Account"); + + Iterator foreignKeyIterator = classMapping.getTable().getForeignKeyIterator(); + while ( foreignKeyIterator.hasNext() ) { + ForeignKey element = (ForeignKey) foreignKeyIterator.next(); + if(element.getReferencedEntityName().equals(Person.class.getName() ) ) { + + if(!element.isReferenceToPrimaryKey() ) { + List referencedColumns = element.getReferencedColumns(); + Column column = (Column) referencedColumns.get(0); + if(column.getName().equals("person_userid") ) { + found = true; // extend test to include the columns + } + } } } } - assertTrue("Property ref foreign key not found",found); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java index 1b717c1e0c..af377116cd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java @@ -29,6 +29,7 @@ import org.hibernate.FetchMode; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -37,6 +38,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class JoinedSubclassPropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "propertyref/inheritence/joined/Person.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java index 3c31ecd111..0cff075172 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java @@ -42,6 +42,8 @@ import org.hibernate.cfg.Environment; import org.hibernate.mapping.Column; import org.hibernate.mapping.Table; import org.hibernate.mapping.UniqueKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.tool.hbm2ddl.SchemaExport; @@ -57,13 +59,24 @@ public class QuoteGlobalTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-7890") public void testQuotedUniqueConstraint() { - Iterator itr = configuration().getClassMapping( Person.class.getName() ) - .getTable().getUniqueKeyIterator(); - while ( itr.hasNext() ) { - UniqueKey uk = itr.next(); - assertEquals( uk.getColumns().size(), 1 ); - assertEquals( uk.getColumn( 0 ).getName(), "name"); - return; + if ( isMetadataUsed() ) { + Iterable uniqueKeys = + SchemaUtil.getTable( Person.class, metadata() ).getUniqueKeys(); + for ( org.hibernate.metamodel.spi.relational.UniqueKey uk : uniqueKeys ) { + assertEquals( uk.getColumns().size(), 1 ); + assertEquals( uk.getColumns().get( 0 ).getColumnName().getText(), "name"); + return; + } + } + else { + Iterator itr = configuration().getClassMapping( Person.class.getName() ) + .getTable().getUniqueKeyIterator(); + while ( itr.hasNext() ) { + UniqueKey uk = itr.next(); + assertEquals( uk.getColumns().size(), 1 ); + assertEquals( uk.getColumn( 0 ).getName(), "name"); + return; + } } fail( "GLOBALLY_QUOTED_IDENTIFIERS caused the unique key creation to fail." ); } @@ -83,7 +96,13 @@ public class QuoteGlobalTest extends BaseCoreFunctionalTestCase { assertEquals( 1, u.getRoles().size() ); tx.rollback(); String role = User.class.getName() + ".roles"; - assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + + if ( isMetadataUsed() ) { + assertEquals( "User_Role", SchemaUtil.getCollectionTable( User.class, "roles", metadata() ).getLogicalName().getText() ); + } + else { + assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + } s.close(); } @@ -109,12 +128,24 @@ public class QuoteGlobalTest extends BaseCoreFunctionalTestCase { } private void doTestHbmQuoting(Class clazz) { - Table table = configuration().getClassMapping( clazz.getName() ).getTable(); - assertTrue( table.isQuoted() ); - Iterator itr = table.getColumnIterator(); - while(itr.hasNext()) { - Column column = (Column) itr.next(); - assertTrue( column.isQuoted() ); + if ( isMetadataUsed() ) { + final TableSpecification tableSpecification = SchemaUtil.getTable( clazz, metadata() ); + assertTrue( tableSpecification.getLogicalName().isQuoted() ); + for ( org.hibernate.metamodel.spi.relational.Value value : tableSpecification.values() ) { + assertTrue( org.hibernate.metamodel.spi.relational.Column.class.isInstance( value ) ); + org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) value; + assertTrue( column.getColumnName().isQuoted() ); + } + } + else { + Table table = configuration().getClassMapping( clazz.getName() ).getTable(); + assertTrue( table.isQuoted() ); + Iterator itr = table.getColumnIterator(); + while(itr.hasNext()) { + Column column = (Column) itr.next(); + assertTrue( column.isQuoted() ); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java index 7a15b2fa7e..3c3da1e2a8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java @@ -43,6 +43,10 @@ import javax.persistence.Table; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -68,7 +72,14 @@ public class QuoteTest extends BaseCoreFunctionalTestCase { assertEquals( 1, u.getRoles().size() ); tx.rollback(); String role = User.class.getName() + ".roles"; - assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + if ( isMetadataUsed() ) { + AttributeBinding attributeBinding = metadata().getEntityBinding( User.class.getName() ).locateAttributeBinding( "roles" ); + PluralAttributeKeyBinding keyBinding = ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeKeyBinding(); + assertEquals( "User_Role", ( (Table) keyBinding.getCollectionTable() ).getPhysicalName().getText() ); + } + else { + assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + } s.close(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java b/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java index 1ff447eafb..8aeb183f20 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java +++ b/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java @@ -23,7 +23,7 @@ package org.hibernate.test.service; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java b/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java index 287ed08a18..84377f790c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java @@ -36,6 +36,7 @@ import org.hibernate.test.sql.hand.SpaceShip; import org.hibernate.test.sql.hand.Speech; import org.hibernate.test.sql.hand.TextHolder; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -59,6 +60,7 @@ import static org.junit.Assert.fail; * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class NativeSQLQueriesTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "sql/hand/query/NativeSQLQueries.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java b/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java index d850a4f4f7..210c05a87d 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java @@ -35,6 +35,7 @@ import org.junit.Test; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -45,6 +46,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class TernaryTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java index 436c83e070..c820962679 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java @@ -40,6 +40,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.criterion.Order; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.jta.TestingJtaBootstrap; import org.hibernate.testing.jta.TestingJtaPlatformImpl; @@ -54,6 +55,7 @@ import static org.junit.Assert.fail; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class CMTTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java b/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java index 2826c97756..380e524097 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java @@ -45,11 +45,13 @@ import org.hibernate.SessionFactory; import org.hibernate.cfg.AttributeConverterDefinition; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.internal.util.ConfigHelper; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.SimpleValue; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.AbstractStandardBasicType; @@ -66,7 +68,11 @@ import org.junit.Test; */ public class AttributeConverterTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testBasicOperation() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); SimpleValue simpleValue = new SimpleValue( cfg.createMappings() ); simpleValue.setJpaAttributeConverterDefinition( @@ -85,7 +91,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testNonAutoApplyHandling() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAttributeConverter( NotAutoAppliedConverter.class, false ); cfg.addAnnotatedClass( Tester.class ); @@ -102,7 +112,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testBasicConverterApplication() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAttributeConverter( StringClobConverter.class, true ); cfg.addAnnotatedClass( Tester.class ); @@ -126,7 +140,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { @Test @TestForIssue(jiraKey = "HHH-8462") + @FailureExpectedWithNewMetamodel public void testBasicOrmXmlConverterApplication() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAnnotatedClass( Tester.class ); cfg.addURL( ConfigHelper.findAsResource( "org/hibernate/test/type/orm.xml") ); @@ -148,7 +166,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testBasicConverterDisableApplication() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAttributeConverter( StringClobConverter.class, true ); cfg.addAnnotatedClass( Tester2.class ); @@ -170,7 +192,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testBasicUsage() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAttributeConverter( IntegerToVarcharConverter.class, false ); cfg.addAnnotatedClass( Tester4.class ); @@ -215,7 +241,11 @@ public class AttributeConverterTest extends BaseUnitTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testBasicTimestampUsage() { + if ( isDefaultUseNewMetamodel() ) { + throw new NotYetImplementedException( "Not implemented using new metamodel." ); + } Configuration cfg = new Configuration(); cfg.addAttributeConverter( InstantConverter.class, false ); cfg.addAnnotatedClass( IrrelevantInstantEntity.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java index 8ecd2d3ab0..7f095263ec 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -46,6 +47,7 @@ public class TypedManyToOneTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testCreateQuery() { Customer cust = new Customer(); cust.setCustomerId("abc123"); diff --git a/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java b/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java index da743cba94..be31964527 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java @@ -30,6 +30,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -39,6 +40,7 @@ import static org.junit.Assert.assertTrue; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916") public class UnconstrainedTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java b/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java index 8b815b8df0..5b28d71ff9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java +++ b/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java @@ -24,16 +24,31 @@ package org.hibernate.test.util; import java.util.Iterator; +import org.hibernate.AssertionFailure; import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * Check that the Hibernate metamodel contains some database objects * * @author Emmanuel Bernard + * @author Brett Meyer */ -public abstract class SchemaUtil { +public class SchemaUtil { + + private SchemaUtil() {} + public static boolean isColumnPresent(String tableName, String columnName, Configuration cfg) { final Iterator
tables = cfg.getTableMappings(); while (tables.hasNext()) { @@ -61,4 +76,104 @@ public abstract class SchemaUtil { } return false; } + + public static boolean isColumnPresent(String tableName, String columnName, MetadataImplementor metadata) { + try { + TableSpecification table = getTable( tableName, metadata ); + return ( table.locateColumn( columnName ) != null ); + } + catch ( AssertionFailure e ) { + return false; + } + } + + public static boolean isTablePresent(String tableName, MetadataImplementor metadata) { + try { + TableSpecification table = getTable( tableName, metadata ); + return ( table != null ); + } + catch ( AssertionFailure e ) { + return false; + } + } + + public static TableSpecification getTable(Class entityClass, MetadataImplementor metadata) + throws AssertionFailure { + return metadata.getEntityBinding( entityClass.getName() ).getPrimaryTable(); + } + + public static TableSpecification getTable(String tableName, MetadataImplementor metadata) throws AssertionFailure { + Iterable schemas = metadata.getDatabase().getSchemas(); + for ( Schema schema : schemas ) { + TableSpecification table = schema.locateTable( Identifier.toIdentifier( tableName ) ); + if ( table != null ) { + return table; + } + } + throw new AssertionFailure( "can't find table " + tableName ); + } + + public static org.hibernate.metamodel.spi.relational.Column getColumn(Class entityClass, String columnName, MetadataImplementor metadata) + throws AssertionFailure { + return getTable( entityClass, metadata ).locateColumn( columnName ); + } + + public static PrimaryKey getPrimaryKey(Class entityClass, MetadataImplementor metadata) throws AssertionFailure { + return getTable( entityClass, metadata ).getPrimaryKey(); + } + + // TODO: this is not a "schema" method; this should be in MetadataImplmentor + public static PluralAttributeBinding getCollection(Class entityClass, String fieldName, Metadata metadata) { + Iterator collectionBindings = metadata.getCollectionBindings().iterator(); + while ( collectionBindings.hasNext() ) { + PluralAttributeBinding collectionBinding = collectionBindings.next(); + if ( collectionBinding.getAttribute().getName().equals( fieldName ) + && collectionBinding.getAttribute().getAttributeContainer().getClassReference() + .equals( entityClass ) ) { + return collectionBinding; + } + } + return null; + } + + public static TableSpecification getCollectionTable(Class entityClass, String fieldName, Metadata metadata) { + PluralAttributeBinding collection = getCollection( entityClass, fieldName, metadata ); + return collection.getPluralAttributeKeyBinding().getCollectionTable(); + } + + public static boolean hasUniqueKeys(TableSpecification table, String... columnNames) { + for ( String columnName : columnNames ) { + if ( !table.hasUniqueKey( table.locateColumn( columnName ) ) ) { + return false; + } + } + return true; + } + + public static boolean hasUniqueKey(TableSpecification table, String keyName) { + for ( UniqueKey uk : table.getUniqueKeys() ) { + if ( uk.getName().equals( keyName ) ) { + return true; + } + } + return false; + } + + public static boolean hasForeignKey(TableSpecification table, String keyName) { + for ( ForeignKey fk : table.getForeignKeys() ) { + if ( fk.getName().equals( keyName ) ) { + return true; + } + } + return false; + } + + public static boolean hasIndex(TableSpecification table, String indexName) { + for ( Index index : table.getIndexes() ) { + if ( index.getName().equals( indexName ) ) { + return true; + } + } + return false; + } } diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml new file mode 100644 index 0000000000..3b945f8c1a --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml similarity index 78% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml index b12d583056..3ae71f37cf 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml @@ -1,14 +1,14 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml similarity index 75% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml index 9a9689492f..ff4246aa69 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> XML_SCHEMA diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml similarity index 50% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml index 3d3c49d449..c3a8da811e 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml @@ -1,9 +1,9 @@ - org.hibernate.metamodel.source.annotations.xml.mocker + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> + org.hibernate.metamodel.internal.source.annotations.xml.mocker XML_SCHEMA XML_CATALOG diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml similarity index 53% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml index f31ede7088..d5a507b89b 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml @@ -1,9 +1,9 @@ - org.hibernate.metamodel.source.annotations.xml.mocker + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> + org.hibernate.metamodel.internal.source.annotations.xml.mocker diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml similarity index 79% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml index 486798aef9..3a36c08035 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml @@ -8,17 +8,17 @@ FIELD - + - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker - + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml similarity index 86% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml index b2cc07b664..a84268bacb 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml similarity index 93% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml index 766e7690f5..966a111145 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml @@ -8,7 +8,7 @@ FIELD - + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml similarity index 84% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml index 04aa71fe58..38057ac227 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml similarity index 85% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml index 8709ce0741..0323af6cf1 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml similarity index 100% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml similarity index 86% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml index b3ef070049..d4eb5d63b3 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml similarity index 62% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml index dc6baf6321..328912bc3e 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml @@ -1,15 +1,16 @@ - - + - + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml new file mode 100644 index 0000000000..91498541f0 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml similarity index 50% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml index 14f88143aa..ee77f942d8 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml @@ -1,14 +1,13 @@ - - - - - - - + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml index af62001456..48ff255aef 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml @@ -3,7 +3,7 @@ xmlns="http://www.hibernate.org/xsd/hibernate-mapping" xsi:schemaLocation="http://www.hibernate.org/xsd/hibernate-mapping hibernate-mapping-4.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - package="org.hibernate.metamodel.binding"> + package="org.hibernate.metamodel.spi.binding"> diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml index 13425bf8d8..57e376c385 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml @@ -22,7 +22,7 @@ ~ 51 Franklin Street, Fifth Floor ~ Boston, MA 02110-1301 USA --> - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml index 24882262d1..718c12aa7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml @@ -22,7 +22,7 @@ ~ 51 Franklin Street, Fifth Floor ~ Boston, MA 02110-1301 USA --> - diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml new file mode 100644 index 0000000000..59e82776ea --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml new file mode 100644 index 0000000000..799d331e31 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml new file mode 100644 index 0000000000..99b330e293 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml new file mode 100644 index 0000000000..34e332a4b9 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml new file mode 100644 index 0000000000..66c44df1f0 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml new file mode 100644 index 0000000000..6b7e8221c3 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index fd30a8b062..6963eb85d0 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -69,7 +69,7 @@ import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.ValueHolder; import org.hibernate.jpa.AvailableSettings; @@ -95,8 +95,8 @@ import org.hibernate.jpa.internal.schemagen.JpaSchemaGenerator; import org.hibernate.jpa.internal.util.LogHelper; import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper; import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.spi.TypeContributor; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.secure.spi.GrantedPermission; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java index 05fc13ff71..60b61b274e 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java @@ -50,7 +50,7 @@ import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.boot.archive.internal.ArchiveHelper; import org.hibernate.jpa.internal.EntityManagerMessageLogger; import org.hibernate.jpa.internal.util.ConfigurationHelper; -import org.hibernate.metamodel.source.XsdException; +import org.hibernate.metamodel.spi.source.XsdException; import org.jboss.logging.Logger; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java index d7bcda53f5..df241a99dc 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java @@ -27,14 +27,16 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import org.hibernate.EntityMode; import org.hibernate.MappingException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.ListenerFactory; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.source.JpaCallbackSource; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.jboss.logging.Logger; @@ -62,47 +64,49 @@ public class CallbackProcessorImpl implements CallbackProcessor { @Override public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) { final EntityBinding entityBinding = (EntityBinding) entityObject; - final String entityClassName = entityBinding.getEntity().getClassName(); - if ( entityClassName == null ) { + if ( entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) { return; } - - try { - final Class entityClass = classLoaderService.classForName( entityClassName ); - for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) { - callbackRegistry.addEntityCallbacks( - entityClass, - annotationClass, - collectCallbacks( entityBinding, entityClass, annotationClass ) - ); - } - } - catch (ClassLoadingException e) { - throw new MappingException( "entity class not found: " + entityClassName, e ); + final Class entityClass = entityBinding.getEntity().getClassReference(); + for ( final Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) { + callbackRegistry.addEntityCallbacks( + entityClass, + annotationClass, + collectCallbacks( entityBinding, entityClass, annotationClass ) + ); } } - private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) { - final List callbacks = new ArrayList(); - for ( JpaCallbackClass jpaCallbackClass : entityBinding.getJpaCallbackClasses() ) { - final Class listenerClass = classLoaderService.classForName( jpaCallbackClass.getName() ); - final String methodName = jpaCallbackClass.getCallbackMethod( annotationClass ); + private final static Callback[] EMPTY_CALLBACK = new Callback[0]; + private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) { + final List jpaCallbackSources = entityBinding.getJpaCallbackClasses(); + if ( CollectionHelper.isEmpty( jpaCallbackSources ) ) { + return EMPTY_CALLBACK; + } + final List result = new ArrayList( jpaCallbackSources.size() ); + for ( final JpaCallbackSource jpaCallbackSource : entityBinding.getJpaCallbackClasses() ) { + final Class listenerClass = classLoaderService.classForName( jpaCallbackSource.getName() ); + final String methodName = jpaCallbackSource.getCallbackMethod( annotationClass ); + if ( methodName == null ) { + continue; + } log.debugf( - "Adding $s.%s as %s callback for entity %s", + "Adding %s.%s as %s callback for entity %s", listenerClass.getName(), methodName, annotationClass.getName(), entityClass.getName() ); - final Callback callback = jpaCallbackClass.isListener() + final Callback callback = jpaCallbackSource.isListener() ? createListenerCallback( listenerClass, entityClass, methodName ) : createBeanCallback( listenerClass, methodName ); - assert callback != null; - callbacks.add(callback); + if ( callback != null ) { + result.add( callback ); + } } - return callbacks.toArray(new Callback[callbacks.size()]); + return result.toArray( new Callback[result.size()] ); } private Callback createListenerCallback( diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java index 0688d81389..9739094a18 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java @@ -63,8 +63,8 @@ import org.hibernate.jpa.event.internal.jpa.LegacyCallbackProcessor; import org.hibernate.jpa.event.internal.jpa.StandardListenerFactory; import org.hibernate.jpa.event.spi.jpa.ListenerFactory; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java index 07399e245f..2eb79ea4cd 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java @@ -71,13 +71,6 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger { @Message( value = "Exploded jar file not a directory (ignored): %s", id = 15006 ) void explodedJarNotDirectory( URL jarUrl ); - @LogMessage( level = ERROR ) - @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 ) - void illegalArgumentOnStaticMetamodelFieldInjection( String name, - String name2, - String name3, - String name4 ); - @LogMessage( level = ERROR ) @Message( value = "Malformed URL: %s", id = 15008 ) void malformedUrl( URL jarUrl, @@ -93,11 +86,6 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger { void unableToFindFile( URL jarUrl, @Cause Exception e ); - @LogMessage( level = ERROR ) - @Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 ) - void unableToLocateStaticMetamodelField( String name, - String name2 ); - @LogMessage( level = INFO ) @Message( value = "Using provided datasource", id = 15012 ) void usingProvidedDataSource(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java index 787ba76fbf..a2ec4b707f 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java @@ -55,8 +55,8 @@ import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.internal.PersisterClassResolverInitiator; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java b/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java new file mode 100644 index 0000000000..d5fb910341 --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.testing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to mark test classes or methods as expecting to fail when using the new metamodel introduced in 5.0. This annotation is + * only honored when the system property + * {@value org.hibernate.metamodel.MetadataSources#USE_NEW_METADATA_MAPPINGS} is set to true. + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.METHOD, ElementType.TYPE } ) +public @interface FailureExpectedWithNewMetamodel { + + /** + * @return an optional JIRA issue key that covers the expected failure + */ + String jiraKey() default ""; + + /** + * @return an optional message related to the expected failure + */ + String message() default ""; +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java similarity index 70% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java rename to hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java index 52a040af39..303346dd11 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java @@ -21,33 +21,38 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.testing.junit4; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataBuilder; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.After; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.runners.model.FrameworkMethod; +import org.junit.rules.TestRule; +import org.junit.runner.Description; import org.junit.runners.model.Statement; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; + /** * @author Hardy Ferentschik */ public abstract class BaseAnnotationBindingTestCase extends BaseUnitTestCase { protected MetadataSources sources; protected MetadataImpl meta; + protected List> annotatedClasses = new ArrayList>(); @Rule - public MethodRule buildMetaData = new MethodRule() { + public TestRule buildMetaData = new TestRule() { @Override - public Statement apply(final Statement statement, FrameworkMethod frameworkMethod, Object o) { - return new KeepSetupFailureStatement( statement, frameworkMethod ); + public Statement apply(Statement base, Description description) { + return new KeepSetupFailureStatement( base, description ); } }; @@ -65,15 +70,20 @@ public abstract class BaseAnnotationBindingTestCase extends BaseUnitTestCase { return meta.getRootEntityBinding( clazz.getName() ); } + public List> getAnnotatedClasses() { + return annotatedClasses; + } + class KeepSetupFailureStatement extends Statement { private final Statement origStatement; - private final FrameworkMethod origFrameworkMethod; + private final Description description; private Throwable setupError; private boolean expectedException; + private StandardServiceRegistry serviceRegistry; - KeepSetupFailureStatement(Statement statement, FrameworkMethod frameworkMethod) { + KeepSetupFailureStatement(Statement statement, Description description) { this.origStatement = statement; - this.origFrameworkMethod = frameworkMethod; + this.description = description; } @Override @@ -95,29 +105,34 @@ public abstract class BaseAnnotationBindingTestCase extends BaseUnitTestCase { } } } + finally { + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + serviceRegistry = null; + } } private void createBindings() { try { - sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); + serviceRegistry = new StandardServiceRegistryBuilder( ).build(); + sources = new MetadataSources( serviceRegistry ); MetadataBuilder metadataBuilder = sources.getMetadataBuilder(); - Resources resourcesAnnotation = origFrameworkMethod.getAnnotation( Resources.class ); + Resources resourcesAnnotation = description.getAnnotation( Resources.class ); if ( resourcesAnnotation != null ) { metadataBuilder.with( resourcesAnnotation.cacheMode() ); for ( Class annotatedClass : resourcesAnnotation.annotatedClasses() ) { + annotatedClasses.add( annotatedClass ); sources.addAnnotatedClass( annotatedClass ); } if ( !resourcesAnnotation.ormXmlPath().isEmpty() ) { sources.addResource( resourcesAnnotation.ormXmlPath() ); } } - meta = ( MetadataImpl ) metadataBuilder.build(); } catch ( final Throwable t ) { setupError = t; - Test testAnnotation = origFrameworkMethod.getAnnotation( Test.class ); + Test testAnnotation = description.getAnnotation( Test.class ); Class expected = testAnnotation.expected(); if ( t.getClass().equals( expected ) ) { expectedException = true; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java index 8e2dc4d8c8..a8bfbe7d4c 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java @@ -47,9 +47,11 @@ import org.hibernate.cfg.Environment; import org.hibernate.cfg.Mappings; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.H2Dialect; +import org.hibernate.engine.config.internal.ConfigurationServiceImpl; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; @@ -59,8 +61,9 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.SimpleValue; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.testing.AfterClassOnce; import org.hibernate.testing.BeforeClassOnce; import org.hibernate.testing.OnExpectedFailure; @@ -80,14 +83,14 @@ import static org.junit.Assert.fail; @SuppressWarnings( {"deprecation"} ) public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { public static final String VALIDATE_DATA_CLEANUP = "hibernate.test.validateDataCleanup"; - public static final String USE_NEW_METADATA_MAPPINGS = "hibernate.test.new_metadata_mappings"; public static final Dialect DIALECT = Dialect.getDialect(); - private boolean isMetadataUsed; private Configuration configuration; private StandardServiceRegistryImpl serviceRegistry; private SessionFactoryImplementor sessionFactory; + private MetadataImplementor metadataImplementor; + private final boolean isMetadataUsed; protected Session session; @@ -95,11 +98,38 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { return DIALECT; } + protected BaseCoreFunctionalTestCase() { + // configure(Configuration) may add a setting for using the new metamodel, so, for now, + // build a dummy configuration to get all the property settings. + final Configuration dummyConfiguration = constructAndConfigureConfiguration(); + + // Can't build the ServiceRegistry until after the constructor executes + // (otherwise integrators don't get added). + // Create a dummy ConfigurationService just to find out if the new metamodel will be used. + final ConfigurationService dummyConfigurationService = new ConfigurationServiceImpl( + dummyConfiguration.getProperties() + ); + isMetadataUsed = dummyConfigurationService.getSetting( + MetadataSources.USE_NEW_METADATA_MAPPINGS, + new ConfigurationService.Converter() { + @Override + public Boolean convert(Object value) { + return Boolean.parseBoolean( ( String ) value ); + } + }, + DEFAULT_USE_NEW_METAMODEL + ); + } + protected Configuration configuration() { return configuration; } - protected StandardServiceRegistryImpl serviceRegistry() { + protected MetadataImplementor metadata() { + return metadataImplementor; + } + + protected final StandardServiceRegistryImpl serviceRegistry() { return serviceRegistry; } @@ -123,24 +153,18 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { @BeforeClassOnce @SuppressWarnings( {"UnusedDeclaration"}) protected void buildSessionFactory() { - // for now, build the configuration to get all the property settings - configuration = constructAndConfigureConfiguration(); BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry(); + configuration = constructAndConfigureConfiguration(); serviceRegistry = buildServiceRegistry( bootRegistry, configuration ); - isMetadataUsed = serviceRegistry.getService( ConfigurationService.class ).getSetting( - USE_NEW_METADATA_MAPPINGS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( ( String ) value ); - } - }, - false - ); + if ( isMetadataUsed ) { - MetadataImplementor metadataImplementor = buildMetadata( bootRegistry, serviceRegistry ); + metadataImplementor = buildMetadata(); afterConstructAndConfigureMetadata( metadataImplementor ); - sessionFactory = ( SessionFactoryImplementor ) metadataImplementor.buildSessionFactory(); + final SessionFactoryBuilder sessionFactoryBuilder = metadataImplementor.getSessionFactoryBuilder(); + if ( configuration.getInterceptor() != null ) { + sessionFactoryBuilder.with( configuration.getInterceptor() ); + } + sessionFactory = (SessionFactoryImpl) sessionFactoryBuilder.build(); } else { // this is done here because Configuration does not currently support 4.0 xsd @@ -150,6 +174,10 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { afterSessionFactoryBuilt(); } + protected boolean isMetadataUsed() { + return isMetadataUsed; + } + protected void rebuildSessionFactory() { if ( sessionFactory == null ) { return; @@ -168,10 +196,9 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { } - private MetadataImplementor buildMetadata( - BootstrapServiceRegistry bootRegistry, - StandardServiceRegistryImpl serviceRegistry) { - MetadataSources sources = new MetadataSources( bootRegistry ); + private MetadataImplementor buildMetadata() { + assert BootstrapServiceRegistry.class.isInstance( serviceRegistry.getParentServiceRegistry() ); + MetadataSources sources = new MetadataSources( serviceRegistry.getParentServiceRegistry() ); addMappings( sources ); return (MetadataImplementor) sources.getMetadataBuilder( serviceRegistry ).build(); } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java index 4959fdc89f..4f653a8f9c 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java @@ -27,6 +27,7 @@ import javax.transaction.SystemException; import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.junit.After; import org.junit.Rule; @@ -45,6 +46,16 @@ import org.jboss.logging.Logger; public abstract class BaseUnitTestCase { private static final Logger log = Logger.getLogger( BaseUnitTestCase.class ); + public static final boolean DEFAULT_USE_NEW_METAMODEL = Boolean.valueOf( + System.getProperty( + MetadataSources.USE_NEW_METADATA_MAPPINGS, "true" + ) + ); + + public boolean isDefaultUseNewMetamodel() { + return DEFAULT_USE_NEW_METAMODEL; + } + @Rule public TestRule globalTimeout= new Timeout(30 * 60 * 1000); // no test should run longer than 30 minutes @After diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java index d24466d62b..96b4c0aae5 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java @@ -25,6 +25,9 @@ package org.hibernate.testing.junit4; import org.junit.runners.model.Statement; +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ @@ -39,7 +42,16 @@ public class BeforeClassCallbackHandler extends Statement { @Override public void evaluate() throws Throwable { - runner.getTestClassMetadata().performBeforeClassCallbacks( runner.getTestInstance() ); - wrappedStatement.evaluate(); + try { + runner.getTestClassMetadata().performBeforeClassCallbacks( runner.getTestInstance() ); + wrappedStatement.evaluate(); + } catch ( Throwable error ) { + runner.setBeforeClassMethodFailed(); + if ( runner.getTestClass().getJavaClass().getAnnotation( FailureExpected.class ) == null && + ( !runner.useNewMetamodel() || + runner.getTestClass().getJavaClass().getAnnotation( FailureExpectedWithNewMetamodel.class ) == null ) ) { + throw error; + } + } } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java index fb286422cc..e9d83be31f 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java @@ -35,6 +35,7 @@ import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.testing.DialectCheck; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.RequiresDialects; @@ -64,6 +65,7 @@ public class CustomRunner extends BlockJUnit4ClassRunner { private static final Logger log = Logger.getLogger( CustomRunner.class ); private TestClassMetadata testClassMetadata; + private boolean beforeClassMethodFailed; public CustomRunner(Class clazz) throws InitializationError, NoTestsRemainException { super( clazz ); @@ -76,6 +78,14 @@ public class CustomRunner extends BlockJUnit4ClassRunner { testClassMetadata.validate( errors ); } + boolean beforeClassMethodFailed() { + return beforeClassMethodFailed; + } + + void setBeforeClassMethodFailed() { + beforeClassMethodFailed = true; + } + public TestClassMetadata getTestClassMetadata() { return testClassMetadata; } @@ -132,6 +142,11 @@ public class CustomRunner extends BlockJUnit4ClassRunner { protected Statement classBlock( RunNotifier notifier ) { log.info( BeforeClass.class.getSimpleName() + ": " + getName() ); + if ( getTestClass().getJavaClass().getAnnotation( FailureExpected.class ) != null + || ( useNewMetamodel() && getTestClass().getJavaClass().getAnnotation( FailureExpectedWithNewMetamodel.class ) != null ) ) { + log.info( FailureExpected.class.getSimpleName() ); + } + return super.classBlock( notifier ); } @@ -139,9 +154,15 @@ public class CustomRunner extends BlockJUnit4ClassRunner { protected Statement methodBlock(FrameworkMethod method) { log.info( Test.class.getSimpleName() + ": " + method.getName() ); + if ( method.getAnnotation( FailureExpected.class ) != null + || ( useNewMetamodel() && method.getAnnotation( FailureExpectedWithNewMetamodel.class ) != null ) ) { + log.info( FailureExpected.class.getSimpleName() ); + } + + final Statement originalMethodBlock = super.methodBlock( method ); final ExtendedFrameworkMethod extendedFrameworkMethod = (ExtendedFrameworkMethod) method; - return new FailureExpectedHandler( originalMethodBlock, testClassMetadata, extendedFrameworkMethod, testInstance ); + return new FailureExpectedHandler( this, originalMethodBlock, testClassMetadata, extendedFrameworkMethod, testInstance ); } private Object testInstance; @@ -193,8 +214,35 @@ public class CustomRunner extends BlockJUnit4ClassRunner { Ignore virtualIgnore; for ( FrameworkMethod frameworkMethod : methods ) { + // Convert @FailureExpectedWithNewMetamodel annotations to @FailureExpected annotations + FailureExpected failureExpected = null; + if ( useNewMetamodel() ) { + final FailureExpectedWithNewMetamodel failureExpectedWithNewMetamodel = + Helper.locateAnnotation( FailureExpectedWithNewMetamodel.class, frameworkMethod, getTestClass() ); + if ( failureExpectedWithNewMetamodel != null ) { + failureExpected = new FailureExpected() { + + @Override + public Class< ? extends Annotation > annotationType() { + return FailureExpected.class; + } + + @Override + public String message() { + return failureExpectedWithNewMetamodel.message(); + } + + @Override + public String jiraKey() { + return failureExpectedWithNewMetamodel.jiraKey(); + } + }; + } + } + if ( failureExpected == null ) { + failureExpected = Helper.locateAnnotation( FailureExpected.class, frameworkMethod, getTestClass() ); + } // potentially ignore based on expected failure - final FailureExpected failureExpected = Helper.locateAnnotation( FailureExpected.class, frameworkMethod, getTestClass() ); if ( failureExpected != null && !doValidation ) { virtualIgnore = new IgnoreImpl( Helper.extractIgnoreMessage( failureExpected, frameworkMethod ) ); } @@ -240,6 +288,19 @@ public class CustomRunner extends BlockJUnit4ClassRunner { } } + boolean useNewMetamodel() { + try { + Object object = getTestInstance(); + if ( object != null && object instanceof BaseCoreFunctionalTestCase ) { + return ( (BaseCoreFunctionalTestCase) object ).isMetadataUsed(); + } + } + catch ( Exception e ) { + + } + return BaseCoreFunctionalTestCase.DEFAULT_USE_NEW_METAMODEL; + } + protected Ignore convertSkipToIgnore(FrameworkMethod frameworkMethod) { // @Skip Skip skip = Helper.locateAnnotation( Skip.class, frameworkMethod, getTestClass() ); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java index 9e0a75a941..1040bcc23f 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java @@ -35,16 +35,19 @@ import org.jboss.logging.Logger; class FailureExpectedHandler extends Statement { private static final Logger log = Logger.getLogger( FailureExpectedHandler.class ); + private final CustomRunner runner; private final TestClassMetadata testClassMetadata; private final ExtendedFrameworkMethod extendedFrameworkMethod; private final Statement realInvoker; private final Object testInstance; public FailureExpectedHandler( + CustomRunner runner, Statement realInvoker, TestClassMetadata testClassMetadata, ExtendedFrameworkMethod extendedFrameworkMethod, Object testInstance) { + this.runner = runner; this.realInvoker = realInvoker; this.testClassMetadata = testClassMetadata; this.extendedFrameworkMethod = extendedFrameworkMethod; @@ -53,6 +56,9 @@ class FailureExpectedHandler extends Statement { @Override public void evaluate() throws Throwable { + if ( runner.beforeClassMethodFailed() ) { + return; + } final FailureExpected failureExpected = extendedFrameworkMethod.getFailureExpectedAnnotation(); try { realInvoker.evaluate(); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java rename to hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java index f5f0fd3b9b..8c68b92857 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.testing.junit4; import java.lang.annotation.Retention; import java.lang.annotation.Target; diff --git a/libraries.gradle b/libraries.gradle index 931a88bbf5..0bb1ddd495 100644 --- a/libraries.gradle +++ b/libraries.gradle @@ -66,9 +66,11 @@ ext { slf4j_log4j: "org.slf4j:slf4j-log4j12:1.7.5", // jaxb task - jaxb: 'com.sun.xml.bind:jaxb-xjc:2.1.6', - jaxb2_basics: 'org.jvnet.jaxb2_commons:jaxb2-basics:0.6.0', - jaxb2_ant: 'org.jvnet.jaxb2_commons:jaxb2-basics-ant:0.6.0', + jaxb: 'com.sun.xml.bind:jaxb-xjc:2.2.5', + jaxb2_basics: 'org.jvnet.jaxb2_commons:jaxb2-basics:0.6.3', + jaxb2_ant: 'org.jvnet.jaxb2_commons:jaxb2-basics-ant:0.6.3', + jaxb2_jaxb: 'org.jvnet.jaxb2_commons:jaxb2-basics-jaxb:2.2.4-1', + jaxb2_jaxb_xjc: 'org.jvnet.jaxb2_commons:jaxb2-basics-jaxb-xjc:2.2.4-1', // Animal Sniffer Ant Task and Java 1.6 API signature file // not using 1.9 for the time being due to MANIMALSNIFFER-34