diff --git a/hibernate-models-common/src/main/java/org/hibernate/models/internal/CollectionHelper.java b/hibernate-models-common/src/main/java/org/hibernate/models/internal/CollectionHelper.java index e854dd7..20d3ec9 100644 --- a/hibernate-models-common/src/main/java/org/hibernate/models/internal/CollectionHelper.java +++ b/hibernate-models-common/src/main/java/org/hibernate/models/internal/CollectionHelper.java @@ -69,4 +69,36 @@ public static List join(List first, List second) { } return joined; } + + public static List join(Collection first, Collection second) { + final int totalCount = ( first == null ? 0 : first.size() ) + + ( second == null ? 0 : second.size() ); + if ( totalCount == 0 ) { + return Collections.emptyList(); + } + final ArrayList joined = new ArrayList<>( totalCount ); + if ( first != null ) { + joined.addAll( first ); + } + if ( second != null ) { + joined.addAll( second ); + } + return joined; + } + + public static List mutableJoin(Collection first, Collection second) { + final int totalCount = ( first == null ? 0 : first.size() ) + + ( second == null ? 0 : second.size() ); + if ( totalCount == 0 ) { + return new ArrayList<>(); + } + final ArrayList joined = new ArrayList<>( totalCount ); + if ( first != null ) { + joined.addAll( first ); + } + if ( second != null ) { + joined.addAll( second ); + } + return joined; + } } diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/internal/HierarchyAttributeProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/internal/HierarchyAttributeProcessor.java index 70d5238..cabf5e8 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/internal/HierarchyAttributeProcessor.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/internal/HierarchyAttributeProcessor.java @@ -17,7 +17,7 @@ import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; import org.hibernate.models.orm.spi.OrmModelBuildingContext; -import org.hibernate.models.orm.spi.ProcessResult; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.source.spi.AnnotationUsage; import org.hibernate.models.source.spi.MemberDetails; @@ -32,9 +32,9 @@ */ public class HierarchyAttributeProcessor { public static List preBindHierarchyAttributes( - ProcessResult processResult, + CategorizedDomainModel categorizedDomainModel, OrmModelBuildingContext modelBuildingContext) { - final Set entityHierarchies = processResult.getEntityHierarchies(); + final Set entityHierarchies = categorizedDomainModel.getEntityHierarchies(); final List hierarchyIdMembers = CollectionHelper.arrayList( entityHierarchies.size() ); for ( EntityHierarchy hierarchy : entityHierarchies ) { @@ -76,6 +76,9 @@ public static class HierarchyAttributeDescriptor { private AttributeMetadata versionAttribute; private AttributeMetadata tenantIdAttribute; + // todo : row-id? + // todo : others? + public HierarchyAttributeDescriptor(EntityHierarchy entityHierarchy) { this.entityHierarchy = entityHierarchy; } diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingContext.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingContext.java new file mode 100644 index 0000000..95456b8 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingContext.java @@ -0,0 +1,19 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.bind.spi; + +import org.hibernate.models.orm.spi.OrmModelBuildingContext; + +/** + * Contextual information used while {@linkplain BindingCoordinator binding} + * {@linkplain org.hibernate.boot.model.process.spi.ManagedResources managed-resources} into + * into Hibernate's {@linkplain org.hibernate.mapping boot-time model}. + * + * @author Steve Ebersole + */ +public interface BindingContext extends OrmModelBuildingContext { +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingCoordinator.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingCoordinator.java new file mode 100644 index 0000000..bd64440 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/bind/spi/BindingCoordinator.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.bind.spi; + +/** + * Responsible for processing {@linkplain org.hibernate.boot.model.process.spi.ManagedResources managed-resources} + * and binding them into Hibernate's {@linkplain org.hibernate.mapping boot-time model}. + * + * @author Steve Ebersole + */ +public class BindingCoordinator { +// /** +// * Main entry point into this binding coordination +// * +// * @param managedResources The managed-resources to be processed +// * @param options Options for the binding +// * @param bindingContext Access to needed information and delegates +// */ +// public static void coordinateBinding( +// ManagedResources managedResources, +// BindingOptions options, +// ClassInclusion classInclusions, +// PackageInclusion packageInclusions, +// BindingContext bindingContext) { +//// Processor.process( managedResources, bindingContext, options ); +// } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/CategorizedDomainModelImpl.java similarity index 61% rename from hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultImpl.java rename to hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/CategorizedDomainModelImpl.java index 2182415..e113c36 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultImpl.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/CategorizedDomainModelImpl.java @@ -11,29 +11,47 @@ import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.GlobalRegistrations; -import org.hibernate.models.orm.spi.ProcessResult; +import org.hibernate.models.orm.spi.CategorizedDomainModel; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsRegistry; /** * @author Steve Ebersole */ -public class ProcessResultImpl implements ProcessResult { +public class CategorizedDomainModelImpl implements CategorizedDomainModel { + private final ClassDetailsRegistry classDetailsRegistry; + private final AnnotationDescriptorRegistry annotationDescriptorRegistry; private final Set entityHierarchies; private final Map mappedSuperclasses; private final Map embeddables; private final GlobalRegistrations globalRegistrations; - public ProcessResultImpl( + public CategorizedDomainModelImpl( + ClassDetailsRegistry classDetailsRegistry, + AnnotationDescriptorRegistry annotationDescriptorRegistry, Set entityHierarchies, Map mappedSuperclasses, Map embeddables, GlobalRegistrations globalRegistrations) { + this.classDetailsRegistry = classDetailsRegistry; + this.annotationDescriptorRegistry = annotationDescriptorRegistry; this.entityHierarchies = entityHierarchies; this.mappedSuperclasses = mappedSuperclasses; this.embeddables = embeddables; this.globalRegistrations = globalRegistrations; } + @Override + public ClassDetailsRegistry getClassDetailsRegistry() { + return classDetailsRegistry; + } + + @Override + public AnnotationDescriptorRegistry getAnnotationDescriptorRegistry() { + return annotationDescriptorRegistry; + } + @Override public Set getEntityHierarchies() { return entityHierarchies; diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ClassLoaderServiceLoading.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ClassLoaderServiceLoading.java new file mode 100644 index 0000000..ff8c43e --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ClassLoaderServiceLoading.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.internal; + +import java.net.URL; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.models.spi.ClassLoading; + +/** + * Adapts {@linkplain ClassLoaderService} to the {@linkplain ClassLoading} contract + * + * @author Steve Ebersole + */ +public class ClassLoaderServiceLoading implements ClassLoading { + private final ClassLoaderService classLoaderService; + + public ClassLoaderServiceLoading(ClassLoaderService classLoaderService) { + this.classLoaderService = classLoaderService; + } + + @Override + public Class classForName(String name) { + return classLoaderService.classForName( name ); + } + + @Override + public Package packageForName(String name) { + return classLoaderService.packageForNameOrNull( name ); + } + + @Override + public URL locateResource(String resourceName) { + return classLoaderService.locateResource( resourceName ); + } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultCollector.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/DomainModelCategorizationCollector.java similarity index 62% rename from hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultCollector.java rename to hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/DomainModelCategorizationCollector.java index 6f06208..96cf986 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ProcessResultCollector.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/DomainModelCategorizationCollector.java @@ -6,6 +6,8 @@ */ package org.hibernate.models.orm.internal; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -13,28 +15,50 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistenceUnitDefaultsImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistenceUnitMetadataImpl; -import org.hibernate.models.orm.spi.ProcessResult; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.spi.BootstrapContext; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsRegistry; import org.hibernate.models.source.spi.PackageDetails; -import org.hibernate.models.source.spi.SourceModelBuildingContext; -import static java.util.Collections.emptyMap; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.MappedSuperclass; /** * In-flight holder for various types of "global" registrations. Also acts as the - * {@linkplain #createResult builder} for {@linkplain ProcessResult} as returned - * by {@linkplain org.hibernate.models.orm.spi.Processor#process} + * {@linkplain #createResult builder} for {@linkplain CategorizedDomainModel} as returned + * by {@linkplain org.hibernate.models.orm.spi.ManagedResourcesProcessor#processManagedResources} * * @author Steve Ebersole */ -public class ProcessResultCollector { - private final GlobalRegistrationsImpl globalRegistrations; + +public class DomainModelCategorizationCollector { private final boolean areIdGeneratorsGlobal; + private final Set rootEntities = new HashSet<>(); + private final Map mappedSuperclasses = new HashMap<>(); + private final Map embeddables = new HashMap<>(); + private final GlobalRegistrationsImpl globalRegistrations; - public ProcessResultCollector(boolean areIdGeneratorsGlobal, SourceModelBuildingContext sourceModelBuildingContext) { - this.globalRegistrations = new GlobalRegistrationsImpl( sourceModelBuildingContext ); + public DomainModelCategorizationCollector(boolean areIdGeneratorsGlobal, ClassDetailsRegistry classDetailsRegistry) { this.areIdGeneratorsGlobal = areIdGeneratorsGlobal; + this.globalRegistrations = new GlobalRegistrationsImpl( classDetailsRegistry ); + } + + public Set getRootEntities() { + return rootEntities; + } + + public Map getMappedSuperclasses() { + return mappedSuperclasses; + } + + public Map getEmbeddables() { + return embeddables; } public GlobalRegistrationsImpl getGlobalRegistrations() { @@ -83,6 +107,24 @@ public void apply(ClassDetails classDetails) { // todo : named queries // todo : named graphs + + if ( classDetails.getAnnotationUsage( MappedSuperclass.class ) != null ) { + if ( classDetails.getClassName() != null ) { + mappedSuperclasses.put( classDetails.getClassName(), classDetails ); + } + } + else if ( classDetails.getAnnotationUsage( Entity.class ) != null ) { + if ( EntityHierarchyBuilder.isRoot( classDetails ) ) { + rootEntities.add( classDetails ); + } + } + else if ( classDetails.getAnnotationUsage( Embeddable.class ) != null ) { + if ( classDetails.getClassName() != null ) { + embeddables.put( classDetails.getClassName(), classDetails ); + } + } + + // todo : converters? - @Converter / AttributeConverter, as opposed to @ConverterRegistration which is already collected } public void apply(PackageDetails packageDetails) { @@ -99,20 +141,21 @@ public void apply(PackageDetails packageDetails) { } /** - * Builder for {@linkplain ProcessResult} based on our internal state plus + * Builder for {@linkplain CategorizedDomainModel} based on our internal state plus * the incoming set of managed types. * - * @param entityHierarchies All entity hierarchies defined in the persistence-unit - * @param mappedSuperclasses All mapped-superclasses defined in the persistence-unit - * @param embeddables All embeddables defined in the persistence-unit + * @param entityHierarchies All entity hierarchies defined in the persistence-unit, built based + * on {@linkplain #getRootEntities()} * - * @see org.hibernate.models.orm.spi.Processor#process + * @see org.hibernate.models.orm.spi.ManagedResourcesProcessor#processManagedResources */ - public ProcessResult createResult( + public CategorizedDomainModel createResult( Set entityHierarchies, - Map mappedSuperclasses, - Map embeddables) { - return new ProcessResultImpl( + ClassDetailsRegistry classDetailsRegistry, + AnnotationDescriptorRegistry annotationDescriptorRegistry) { + return new CategorizedDomainModelImpl( + classDetailsRegistry, + annotationDescriptorRegistry, entityHierarchies, mappedSuperclasses, embeddables, diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/GlobalRegistrationsImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/GlobalRegistrationsImpl.java index a597eb2..8433d2c 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/GlobalRegistrationsImpl.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/GlobalRegistrationsImpl.java @@ -54,7 +54,7 @@ import org.hibernate.models.source.spi.AnnotationUsage; import org.hibernate.models.source.spi.ClassDetails; import org.hibernate.models.source.spi.ClassDetailsRegistry; -import org.hibernate.models.source.spi.SourceModelBuildingContext; +import org.hibernate.models.source.spi.SourceModelContext; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.TableGenerator; @@ -91,8 +91,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations { private Map tableGeneratorRegistrations; private Map genericGeneratorRegistrations; - public GlobalRegistrationsImpl(SourceModelBuildingContext sourceModelBuildingContext) { - this( sourceModelBuildingContext.getClassDetailsRegistry() ); + public GlobalRegistrationsImpl(SourceModelContext sourceModelContext) { + this( sourceModelContext.getClassDetailsRegistry() ); } public GlobalRegistrationsImpl(ClassDetailsRegistry classDetailsRegistry) { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ManagedResourcesImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ManagedResourcesImpl.java deleted file mode 100644 index d35c862..0000000 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/ManagedResourcesImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.orm.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.models.orm.spi.ManagedResources; - -/** - * @author Steve Ebersole - */ -public class ManagedResourcesImpl implements ManagedResources { - private final List packageNames; - private final List classNames; - private final List> loadedClasses; - private final List xmlMappings; - - public ManagedResourcesImpl( - List packageNames, - List classNames, - List> loadedClasses, - List xmlMappings) { - this.packageNames = packageNames; - this.classNames = classNames; - this.loadedClasses = loadedClasses; - this.xmlMappings = xmlMappings; - } - - @Override - public List getPackageNames() { - return packageNames; - } - - @Override - public List getClassNames() { - return classNames; - } - - @Override - public List> getLoadedClasses() { - return loadedClasses; - } - - @Override - public List getXmlMappings() { - return xmlMappings; - } - - - public static class Builder { - private List packageNames; - private List classNames; - private List> loadedClasses; - private List xmlMappings; - - public Builder addPackages(String... names) { - if ( packageNames == null ) { - packageNames = new ArrayList<>(); - } - Collections.addAll( packageNames, names ); - return this; - } - - public Builder addClassNames(String... names) { - if ( classNames == null ) { - classNames = new ArrayList<>(); - } - Collections.addAll( classNames, names ); - return this; - } - - public Builder addLoadedClasses(Class... classes) { - if ( loadedClasses == null ) { - loadedClasses = new ArrayList<>(); - } - Collections.addAll( loadedClasses, classes ); - return this; - } - - public Builder addXmlMappings(String... names) { - if ( xmlMappings == null ) { - xmlMappings = new ArrayList<>(); - } - Collections.addAll( xmlMappings, names ); - return this; - } - - public ManagedResources build() { - return new ManagedResourcesImpl( - packageNames == null ? Collections.emptyList() : packageNames, - classNames == null ? Collections.emptyList() : classNames, - loadedClasses == null ? Collections.emptyList() : loadedClasses, - xmlMappings == null ? Collections.emptyList() : xmlMappings - ); - } - } -} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/OrmModelBuildingContextImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/OrmModelBuildingContextImpl.java index c1aa430..7cd7555 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/OrmModelBuildingContextImpl.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/internal/OrmModelBuildingContextImpl.java @@ -10,10 +10,7 @@ import org.hibernate.models.orm.spi.OrmModelBuildingContext; import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; import org.hibernate.models.source.spi.ClassDetailsRegistry; -import org.hibernate.models.source.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ClassLoading; - -import org.jboss.jandex.IndexView; +import org.hibernate.models.source.spi.SourceModelContext; import jakarta.persistence.SharedCacheMode; @@ -23,35 +20,33 @@ public class OrmModelBuildingContextImpl implements OrmModelBuildingContext { private final ClassDetailsRegistry classDetailsRegistry; private final AnnotationDescriptorRegistry annotationDescriptorRegistry; - private final ClassLoading classLoading; - private final IndexView jandexIndex; private final ClassmateContext classmateContext; private final SharedCacheMode sharedCacheMode; public OrmModelBuildingContextImpl( - SourceModelBuildingContext sourceModelBuildingContext, + SourceModelContext sourceModelContext, ClassmateContext classmateContext) { this( - sourceModelBuildingContext.getClassDetailsRegistry(), - sourceModelBuildingContext.getAnnotationDescriptorRegistry(), - sourceModelBuildingContext.getClassLoading(), - sourceModelBuildingContext.getJandexIndex(), - classmateContext, - SharedCacheMode.UNSPECIFIED + sourceModelContext.getClassDetailsRegistry(), + sourceModelContext.getAnnotationDescriptorRegistry(), + classmateContext ); } public OrmModelBuildingContextImpl( ClassDetailsRegistry classDetailsRegistry, AnnotationDescriptorRegistry annotationDescriptorRegistry, - ClassLoading classLoading, - IndexView jandexIndex, + ClassmateContext classmateContext) { + this( classDetailsRegistry, annotationDescriptorRegistry, classmateContext, SharedCacheMode.UNSPECIFIED ); + } + + public OrmModelBuildingContextImpl( + ClassDetailsRegistry classDetailsRegistry, + AnnotationDescriptorRegistry annotationDescriptorRegistry, ClassmateContext classmateContext, SharedCacheMode sharedCacheMode) { this.classDetailsRegistry = classDetailsRegistry; this.annotationDescriptorRegistry = annotationDescriptorRegistry; - this.classLoading = classLoading; - this.jandexIndex = jandexIndex; this.classmateContext = classmateContext; this.sharedCacheMode = sharedCacheMode; } @@ -66,16 +61,6 @@ public AnnotationDescriptorRegistry getAnnotationDescriptorRegistry() { return annotationDescriptorRegistry; } - @Override - public ClassLoading getClassLoading() { - return classLoading; - } - - @Override - public IndexView getJandexIndex() { - return jandexIndex; - } - @Override public ClassmateContext getClassmateContext() { return classmateContext; diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/package-info.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/package-info.java new file mode 100644 index 0000000..dbf0577 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/package-info.java @@ -0,0 +1,15 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +/** + * Overall, this module is responsible for taking + * {@linkplain org.hibernate.boot.model.process.spi.ManagedResources managed-resources} and + * binding them into Hibernate's {@linkplain org.hibernate.mapping boot-time model}. + * + * @author Steve Ebersole + */ +package org.hibernate.models.orm; \ No newline at end of file diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ProcessResult.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CategorizedDomainModel.java similarity index 63% rename from hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ProcessResult.java rename to hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CategorizedDomainModel.java index 89117bb..633ebb7 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ProcessResult.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CategorizedDomainModel.java @@ -11,19 +11,39 @@ import org.hibernate.models.internal.IndexedConsumer; import org.hibernate.models.internal.KeyedConsumer; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsRegistry; /** - * The result of {@linkplain Processor#process processing} the domain model + * The application's domain model, understood at a very rudimentary level - we know + * a class is an entity, a mapped-superclass, ... And we know about persistent attributes, + * but again on a very rudimentary level. + *

+ * We also know about all {@linkplain #getGlobalRegistrations() global registrations} - + * sequence-generators, named-queries, ... * * @author Steve Ebersole */ -public interface ProcessResult { +public interface CategorizedDomainModel { + /** + * Registry of all known classes + */ + ClassDetailsRegistry getClassDetailsRegistry(); + + /** + * Registry of all known {@linkplain java.lang.annotation.Annotation} descriptors (classes) + */ + AnnotationDescriptorRegistry getAnnotationDescriptorRegistry(); + /** * All entity hierarchies defined in the persistence unit */ Set getEntityHierarchies(); + /** + * Iteration over the {@linkplain #getEntityHierarchies() entity hierarchies} + */ default void forEachEntityHierarchy(IndexedConsumer hierarchyConsumer) { final Set entityHierarchies = getEntityHierarchies(); if ( entityHierarchies.isEmpty() ) { @@ -42,6 +62,9 @@ default void forEachEntityHierarchy(IndexedConsumer hierarchyCo */ Map getMappedSuperclasses(); + /** + * Iteration over the {@linkplain #getMappedSuperclasses() mapped superclasses} + */ default void forEachMappedSuperclass(KeyedConsumer consumer) { final Map mappedSuperclasses = getMappedSuperclasses(); if ( mappedSuperclasses.isEmpty() ) { @@ -56,6 +79,10 @@ default void forEachMappedSuperclass(KeyedConsumer consume */ Map getEmbeddables(); + /** + * Iteration over the {@linkplain #getEmbeddables() embeddables} + */ + default void forEachEmbeddable(KeyedConsumer consumer) { final Map embeddables = getEmbeddables(); if ( embeddables.isEmpty() ) { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CollectionTypeRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CollectionTypeRegistration.java index 7c2b5ad..953ecd7 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CollectionTypeRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CollectionTypeRegistration.java @@ -12,6 +12,11 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * Registration for a {@linkplain org.hibernate.usertype.UserCollectionType} + * + * @see org.hibernate.annotations.CollectionTypeRegistration + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbCollectionUserTypeImpl + * * @author Steve Ebersole */ public class CollectionTypeRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CompositeUserTypeRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CompositeUserTypeRegistration.java index c13ec64..25b03f6 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CompositeUserTypeRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/CompositeUserTypeRegistration.java @@ -9,6 +9,11 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * Registration for a {@linkplain org.hibernate.usertype.CompositeUserType} + * + * @see org.hibernate.annotations.CompositeTypeRegistration + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbCompositeUserTypeRegistrationImpl + * * @author Steve Ebersole */ public class CompositeUserTypeRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EmbeddableInstantiatorRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EmbeddableInstantiatorRegistration.java index 5f97b7f..ab8885a 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EmbeddableInstantiatorRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EmbeddableInstantiatorRegistration.java @@ -9,7 +9,10 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * Registered {@linkplain org.hibernate.metamodel.spi.EmbeddableInstantiator} + * * @see org.hibernate.annotations.EmbeddableInstantiatorRegistration + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableInstantiatorRegistrationImpl * * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EntityListenerRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EntityListenerRegistration.java index 1222fc2..3a3cc0c 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EntityListenerRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/EntityListenerRegistration.java @@ -17,7 +17,7 @@ * Represents an entity listener defined in XML * ({@code entity-mappings/persistence-unit-metadata/persistence-unit-defaults/entity-listeners}). * - * @see jakarta.persistence.EntityListeners + * @see JaxbEntityListenerImpl * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/FilterDefRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/FilterDefRegistration.java index 8d33ca1..5960c8d 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/FilterDefRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/FilterDefRegistration.java @@ -13,6 +13,9 @@ /** * Global registration of a filter definition * + * @see org.hibernate.annotations.FilterDef + * @see org.hibernate.boot.jaxb.mapping.JaxbFilterDef + * * @author Marco Belladelli */ public class FilterDefRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GenericGeneratorRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GenericGeneratorRegistration.java index d8d029b..c0b6035 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GenericGeneratorRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GenericGeneratorRegistration.java @@ -12,7 +12,8 @@ /** * Global registration of a generic generator * - * @see org.hibernate.models.orm.spi.Processor.Options#areGeneratorsGlobal() + * @see GenericGenerator + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbGenericIdGeneratorImpl * * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GlobalRegistrations.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GlobalRegistrations.java index a5be042..e052058 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GlobalRegistrations.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/GlobalRegistrations.java @@ -11,6 +11,9 @@ /** + * Registrations which are considered global, collected across annotations + * and XML mappings. + * * @author Steve Ebersole */ public interface GlobalRegistrations { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JavaTypeRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JavaTypeRegistration.java index f78ba08..81266d3 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JavaTypeRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JavaTypeRegistration.java @@ -9,7 +9,10 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * {@linkplain org.hibernate.type.descriptor.java.JavaType} registration + * * @see org.hibernate.annotations.JavaTypeRegistration + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbJavaTypeRegistrationImpl * * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JdbcTypeRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JdbcTypeRegistration.java index cfb2d0e..c81fd7d 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JdbcTypeRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/JdbcTypeRegistration.java @@ -9,7 +9,10 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * {@linkplain org.hibernate.type.descriptor.jdbc.JdbcType} registration + * * @see org.hibernate.annotations.JdbcTypeRegistration + * @see org.hibernate.boot.jaxb.mapping.JaxbJdbcTypeRegistration * * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResources.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResources.java deleted file mode 100644 index a57c6b1..0000000 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResources.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.orm.spi; - -import java.util.List; - -import org.hibernate.models.Copied; - -/** - * @author Steve Ebersole - */ -@Copied(org.hibernate.boot.model.process.spi.ManagedResources.class) -public interface ManagedResources { - List getPackageNames(); - List getClassNames(); - List> getLoadedClasses(); - List getXmlMappings(); -} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResourcesProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResourcesProcessor.java new file mode 100644 index 0000000..9066664 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/ManagedResourcesProcessor.java @@ -0,0 +1,258 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.spi; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.BootstrapContext; +import org.hibernate.models.internal.CollectionHelper; +import org.hibernate.models.orm.internal.ClassLoaderServiceLoading; +import org.hibernate.models.orm.internal.DomainModelCategorizationCollector; +import org.hibernate.models.orm.internal.OrmModelBuildingContextImpl; +import org.hibernate.models.orm.internal.OrmModelLogging; +import org.hibernate.models.orm.xml.spi.XmlProcessingResult; +import org.hibernate.models.orm.xml.spi.XmlPreProcessingResult; +import org.hibernate.models.orm.xml.spi.XmlPreProcessor; +import org.hibernate.models.orm.xml.spi.XmlProcessor; +import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; +import org.hibernate.models.source.internal.jandex.JandexClassDetails; +import org.hibernate.models.source.internal.jandex.JandexIndexerHelper; +import org.hibernate.models.source.internal.jandex.JandexPackageDetails; +import org.hibernate.models.source.internal.jdk.JdkBuilders; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; +import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsRegistry; +import org.hibernate.models.source.spi.RegistryPrimer; +import org.hibernate.models.source.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.ClassLoading; + +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.CompositeIndex; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; + +import static org.hibernate.models.orm.internal.EntityHierarchyBuilder.createEntityHierarchies; + +/** + * Processes {@linkplain ManagedResources} references (classes, mapping, etc.) and + * produces a CategorizedDomainModel + * + * @author Steve Ebersole + */ +public class ManagedResourcesProcessor { + public static CategorizedDomainModel processManagedResources( + ManagedResources managedResources, + BootstrapContext bootstrapContext) { + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // - pre-process the XML + // - collect all known classes + // - resolve Jandex index + // - build the SourceModelBuildingContext + // + // INPUTS: + // - serviceRegistry + // - managedResources + // - bootstrapContext (supplied Jandex index, if one) + // + // OUTPUTS: + // - xmlPreProcessingResult + // - allKnownClassNames (technically could be included in xmlPreProcessingResult) + // - sourceModelBuildingContext + + final ClassLoaderService classLoaderService = bootstrapContext.getServiceRegistry().getService( ClassLoaderService.class ); + final ClassLoaderServiceLoading classLoading = new ClassLoaderServiceLoading( classLoaderService ); + + final XmlPreProcessingResult xmlPreProcessingResult = XmlPreProcessor.preProcessXmlResources( managedResources ); + + final List allKnownClassNames = CollectionHelper.mutableJoin( + managedResources.getAnnotatedClassNames(), + xmlPreProcessingResult.getMappedClasses() + ); + managedResources.getAnnotatedClassReferences().forEach( (clazz) -> allKnownClassNames.add( clazz.getName() ) ); + + // At this point we know all managed class names across all sources. + // Resolve the Jandex Index and build the SourceModelBuildingContext. + final IndexView jandexIndex = resolveJandexIndex( allKnownClassNames, bootstrapContext.getJandexView(), classLoading ); + final SourceModelBuildingContextImpl sourceModelBuildingContext = new SourceModelBuildingContextImpl( + classLoading, + jandexIndex, + ManagedResourcesProcessor::preFillRegistries + ); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // - process metadata-complete XML + // - collect overlay XML + // - process annotations (including those from metadata-complete XML) + // - apply overlay XML + // + // INPUTS: + // - "options" (areIdGeneratorsGlobal, etc) + // - xmlPreProcessingResult + // - sourceModelBuildingContext + // + // OUTPUTS + // - rootEntities + // - mappedSuperClasses + // - embeddables + + // JPA id generator global-ity thing + final boolean areIdGeneratorsGlobal = true; + final ClassDetailsRegistry mutableClassDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); + final DomainModelCategorizationCollector modelCategorizationCollector = new DomainModelCategorizationCollector( + areIdGeneratorsGlobal, + mutableClassDetailsRegistry + ); + final XmlProcessingResult xmlProcessingResult = XmlProcessor.processXml( xmlPreProcessingResult, modelCategorizationCollector, sourceModelBuildingContext ); + + allKnownClassNames.forEach( (className) -> { + final ClassDetails classDetails = mutableClassDetailsRegistry.resolveClassDetails( className ); + modelCategorizationCollector.apply( classDetails ); + } ); + xmlPreProcessingResult.getMappedNames().forEach( (className) -> { + final ClassDetails classDetails = mutableClassDetailsRegistry.resolveClassDetails( className ); + modelCategorizationCollector.apply( classDetails ); + } ); + + xmlProcessingResult.apply( xmlPreProcessingResult.getPersistenceUnitMetadata(), sourceModelBuildingContext ); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // - create entity-hierarchies + // - create the CategorizedDomainModel + // + // INPUTS: + // - rootEntities + // - mappedSuperClasses + // - embeddables + // + // OUTPUTS: + // - CategorizedDomainModel + + final ClassDetailsRegistry classDetailsRegistryImmutable = mutableClassDetailsRegistry + .makeImmutableCopy(); + + final AnnotationDescriptorRegistry annotationDescriptorRegistryImmutable = sourceModelBuildingContext + .getAnnotationDescriptorRegistry() + .makeImmutableCopy(); + + // Collect the entity hierarchies based on the set of `rootEntities` + final OrmModelBuildingContextImpl mappingBuildingContext = new OrmModelBuildingContextImpl( + classDetailsRegistryImmutable, + annotationDescriptorRegistryImmutable, + bootstrapContext.getClassmateContext() + ); + + final Set entityHierarchies; + if ( OrmModelLogging.ORM_MODEL_LOGGER.isDebugEnabled() ) { + final Map unusedMappedSuperClasses = new HashMap<>( modelCategorizationCollector.getMappedSuperclasses() ); + entityHierarchies = createEntityHierarchies( + modelCategorizationCollector.getRootEntities(), + (identifiableType) -> { + if ( identifiableType instanceof MappedSuperclassTypeMetadata ) { + unusedMappedSuperClasses.remove( identifiableType.getClassDetails().getClassName() ); + } + }, + mappingBuildingContext + ); + warnAboutUnusedMappedSuperclasses( unusedMappedSuperClasses ); + } + else { + entityHierarchies = createEntityHierarchies( + modelCategorizationCollector.getRootEntities(), + ManagedResourcesProcessor::ignore, + mappingBuildingContext + ); + } + + return modelCategorizationCollector.createResult( entityHierarchies, classDetailsRegistryImmutable, annotationDescriptorRegistryImmutable ); + } + + private static void ignore(IdentifiableTypeMetadata identifiableTypeMetadata) { + } + + private static void warnAboutUnusedMappedSuperclasses(Map mappedSuperClasses) { + assert OrmModelLogging.ORM_MODEL_LOGGER.isDebugEnabled(); + for ( Map.Entry entry : mappedSuperClasses.entrySet() ) { + OrmModelLogging.ORM_MODEL_LOGGER.debugf( + "Encountered MappedSuperclass [%s] which was unused in any entity hierarchies", + entry.getKey() + ); + } + } + + public static IndexView resolveJandexIndex( + List allKnownClassNames, + IndexView suppliedJandexIndex, + ClassLoading classLoading) { + // todo : we could build a new Jandex (Composite)Index that includes the `managedResources#getAnnotatedClassNames` + // and all classes from `managedResources#getXmlMappingBindings`. Only really worth it in the case + // of runtime enhancement. This would definitely need to be toggle-able. + // + + // For now, let's not as it does not matter for this smoke-test + if ( 1 == 1 ) { + return suppliedJandexIndex; + } + + final Indexer jandexIndexer = new Indexer(); + for ( String knownClassName : allKnownClassNames ) { + JandexIndexerHelper.apply( knownClassName, jandexIndexer, classLoading ); + } + + if ( suppliedJandexIndex == null ) { + return jandexIndexer.complete(); + } + + return CompositeIndex.create( suppliedJandexIndex, jandexIndexer.complete() ); + } + + public static void preFillRegistries(RegistryPrimer.Contributions contributions, SourceModelBuildingContext buildingContext) { + final IndexView jandexIndex = buildingContext.getJandexIndex(); + if ( jandexIndex == null ) { + return; + } + + final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); + final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); + + for ( ClassInfo knownClass : jandexIndex.getKnownClasses() ) { + final String className = knownClass.name().toString(); + if ( className.endsWith( "package-info" ) ) { + classDetailsRegistry.resolvePackageDetails( + className, + () -> new JandexPackageDetails( knownClass, buildingContext ) + ); + continue; + } + + if ( knownClass.isAnnotation() ) { + // it is always safe to load the annotation classes - we will never be enhancing them + //noinspection rawtypes + final Class annotationClass = buildingContext + .getClassLoading() + .classForName( className ); + //noinspection unchecked + annotationDescriptorRegistry.resolveDescriptor( + annotationClass, + (t) -> JdkBuilders.buildAnnotationDescriptor( annotationClass, buildingContext ) + ); + } + + classDetailsRegistry.resolveClassDetails( + className, + () -> new JandexClassDetails( knownClass, buildingContext ) + ); + } + } + +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/OrmModelBuildingContext.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/OrmModelBuildingContext.java index f76ac01..5785945 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/OrmModelBuildingContext.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/OrmModelBuildingContext.java @@ -26,10 +26,6 @@ public interface OrmModelBuildingContext { AnnotationDescriptorRegistry getAnnotationDescriptorRegistry(); - ClassLoading getClassLoading(); - - IndexView getJandexIndex(); - ClassmateContext getClassmateContext(); default PersistentAttributeMemberResolver getPersistentAttributeMemberResolver() { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/Processor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/Processor.java deleted file mode 100644 index 320c095..0000000 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/Processor.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.orm.spi; - -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.boot.internal.ClassmateContext; -import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbManagedType; -import org.hibernate.boot.jaxb.mapping.spi.JaxbMappedSuperclassImpl; -import org.hibernate.models.internal.CollectionHelper; -import org.hibernate.models.internal.StringHelper; -import org.hibernate.models.orm.JpaAnnotations; -import org.hibernate.models.orm.internal.EntityHierarchyBuilder; -import org.hibernate.models.orm.internal.OrmModelBuildingContextImpl; -import org.hibernate.models.orm.internal.OrmModelLogging; -import org.hibernate.models.orm.internal.ProcessResultCollector; -import org.hibernate.models.orm.xml.internal.ManagedTypeProcessor; -import org.hibernate.models.orm.xml.spi.XmlResources; -import org.hibernate.models.source.UnknownClassException; -import org.hibernate.models.source.internal.jandex.JandexClassDetails; -import org.hibernate.models.source.internal.jandex.JandexPackageDetails; -import org.hibernate.models.source.internal.jdk.JdkBuilders; -import org.hibernate.models.source.internal.jdk.JdkPackageDetailsImpl; -import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.source.spi.ClassDetails; -import org.hibernate.models.source.spi.ClassDetailsRegistry; -import org.hibernate.models.source.spi.PackageDetails; -import org.hibernate.models.source.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ClassLoading; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.IndexView; - -import jakarta.persistence.Embeddable; -import jakarta.persistence.SharedCacheMode; - -import static org.hibernate.models.orm.internal.EntityHierarchyBuilder.createEntityHierarchies; -import static org.hibernate.models.orm.xml.internal.ManagedTypeProcessor.processOverrideEmbeddable; -import static org.hibernate.models.orm.xml.internal.ManagedTypeProcessor.processOverrideEntity; -import static org.hibernate.models.orm.xml.internal.ManagedTypeProcessor.processOverrideMappedSuperclass; - -/** - * Processes {@linkplain ManagedResources managed resources} and produces a - * {@linkplain ProcessResult result} which collects broad categorizations of the - * classes defined by those resources based on annotations (and XML mappings). - * - * @author Steve Ebersole - */ -public class Processor { - public interface Options { - default boolean areGeneratorsGlobal() { - return false; - } - - default boolean shouldIgnoreUnlistedClasses() { - return false; - } - - default SharedCacheMode getSharedCacheMode() { - return SharedCacheMode.UNSPECIFIED; - } - } - - public static ProcessResult process( - ManagedResources managedResources, - List explicitlyListedClasses, - SourceModelBuildingContext sourceModelBuildingContext) { - return process( - managedResources, - explicitlyListedClasses, - new Options() { }, - sourceModelBuildingContext - ); - } - - public static ProcessResult process( - ManagedResources managedResources, - List explicitlyListedClasses, - Options options, - SourceModelBuildingContext sourceModelBuildingContext) { - fillRegistries( sourceModelBuildingContext ); - - final OrmModelBuildingContext ormModelBuildingContext = new OrmModelBuildingContextImpl( - sourceModelBuildingContext, - new ClassmateContext() - ); - - return process( managedResources, explicitlyListedClasses, options, sourceModelBuildingContext, ormModelBuildingContext ); - } - - public static class OverrideTuple { - private final JaxbEntityMappingsImpl jaxbRoot; - private final M managedType; - - public OverrideTuple(JaxbEntityMappingsImpl jaxbRoot, M managedType) { - this.jaxbRoot = jaxbRoot; - this.managedType = managedType; - } - - public JaxbEntityMappingsImpl getJaxbRoot() { - return jaxbRoot; - } - - public M getManagedType() { - return managedType; - } - } - - public static ProcessResult process( - ManagedResources managedResources, - List explicitlyListedClasses, - Options options, - SourceModelBuildingContext sourceModelBuildingContext, - OrmModelBuildingContext mappingBuildingContext) { - final ProcessResultCollector processResultCollector = new ProcessResultCollector( options.areGeneratorsGlobal(), sourceModelBuildingContext ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // process XML - // 1. Collect and aggregate information from all known XML mappings - // 2. Handle registrations (JavaType, etc.) and named references (named query, etc.) - // 3. Process managed types - - // a. create ClassDetails for all "complete" mappings - // b. collect "incomplete" (override) mappings - // 4. Apply XML overrides - - final XmlResources collectedXmlResources = XmlResources.collectXmlResources( managedResources, sourceModelBuildingContext ); - final boolean xmlMappingsGloballyComplete = collectedXmlResources.getPersistenceUnitMetadata().areXmlMappingsComplete(); - - final List> entityOverrides = new ArrayList<>(); - final List> mappedSuperclassesOverrides = new ArrayList<>(); - final List> embeddableOverrides = new ArrayList<>(); - - collectedXmlResources.getDocuments().forEach( (jaxbRoot) -> { - processResultCollector.apply( jaxbRoot ); - - jaxbRoot.getEmbeddables().forEach( (embeddable) -> { - if ( xmlMappingsGloballyComplete || embeddable.isMetadataComplete() == Boolean.TRUE ) { - // the XML mapping is complete, we can process it immediately - ManagedTypeProcessor.processCompleteEmbeddable( jaxbRoot, embeddable, collectedXmlResources.getPersistenceUnitMetadata(), sourceModelBuildingContext ); - } - else { - // otherwise, wait to process it until later - embeddableOverrides.add( new OverrideTuple<>( jaxbRoot, embeddable ) ); - } - } ); - - jaxbRoot.getMappedSuperclasses().forEach( (mappedSuperclass) -> { - if ( xmlMappingsGloballyComplete || mappedSuperclass.isMetadataComplete() == Boolean.TRUE ) { - // the XML mapping is complete, we can process it immediately - ManagedTypeProcessor.processCompleteMappedSuperclass( jaxbRoot, mappedSuperclass, collectedXmlResources.getPersistenceUnitMetadata(), sourceModelBuildingContext ); - } - else { - // otherwise, wait to process it until later - mappedSuperclassesOverrides.add( new OverrideTuple<>( jaxbRoot, mappedSuperclass ) ); - } - }); - - jaxbRoot.getEntities().forEach( (entity) -> { - if ( xmlMappingsGloballyComplete || entity.isMetadataComplete() == Boolean.TRUE ) { - // the XML mapping is complete, we can process it immediately - ManagedTypeProcessor.processCompleteEntity( jaxbRoot, entity, collectedXmlResources.getPersistenceUnitMetadata(), sourceModelBuildingContext ); - } - else { - // otherwise, wait to process it until later - entityOverrides.add( new OverrideTuple<>( jaxbRoot, entity ) ); - } - } ); - } ); - - // At this point, we know all classes in the persistence-unit - begin to process them. - // But we need to account for `` from `persistence.xml` - set up - // `classInclusions` and `packageInclusions` to handle `` - final ActiveClassInclusions classInclusions; - final ActivePackageInclusions packageInclusions; - if ( options.shouldIgnoreUnlistedClasses() ) { - classInclusions = new ActiveClassInclusions(); - packageInclusions = new ActivePackageInclusions(); - if ( CollectionHelper.isEmpty( explicitlyListedClasses ) ) { - OrmModelLogging.ORM_MODEL_LOGGER.debugf( "Ignore unlisted classes was requested, but no classes were listed" ); - } - else { - collectListedResources( explicitlyListedClasses, classInclusions, packageInclusions, sourceModelBuildingContext ); - } - } - else { - classInclusions = null; - packageInclusions = null; - } - - // Now inclusions/exclusions are set up, begin processing the classes in earnest. - // This includes a number of parts - - // 1. process "global" annotations - id generators, registrations, named references - // 2. collect the complete sets of - // a. root entities - // b. mapped-superclasses - // c. *explicit* embeddables[1] - // 3. apply mapping XML overrides - // - // [1] Hibernate supports implicit embeddables, where the class does not define `@Embeddable` but the persistent attribute defines `@Embedded` or `@EmbeddedId` - - final Set rootEntities = new HashSet<>(); - final Map mappedSuperClasses = new HashMap<>(); - final Map embeddables = new HashMap<>(); - - final Map unusedMappedSuperClasses = new HashMap<>(); - - processResources( - classInclusions, - packageInclusions, - processResultCollector, - rootEntities, - mappedSuperClasses, - embeddables, - unusedMappedSuperClasses, - mappingBuildingContext - ); - - processOverrideEntity( - entityOverrides, - collectedXmlResources.getPersistenceUnitMetadata(), - sourceModelBuildingContext - ); - - processOverrideMappedSuperclass( - mappedSuperclassesOverrides, - collectedXmlResources.getPersistenceUnitMetadata(), - sourceModelBuildingContext - ); - - processOverrideEmbeddable( - embeddableOverrides, - collectedXmlResources.getPersistenceUnitMetadata(), - sourceModelBuildingContext - ); - - // Collect the entity hierarchies based on the set of `rootEntities` - final Set entityHierarchies = createEntityHierarchies( - rootEntities, - (identifiableType) -> { - if ( identifiableType instanceof MappedSuperclassTypeMetadata ) { - unusedMappedSuperClasses.remove( identifiableType.getClassDetails().getClassName() ); - } - }, - mappingBuildingContext - ); - - if ( OrmModelLogging.ORM_MODEL_LOGGER.isDebugEnabled() ) { - warnAboutUnusedMappedSuperclasses( unusedMappedSuperClasses ); - } - - return processResultCollector.createResult( entityHierarchies, mappedSuperClasses, embeddables ); - } - - private static void warnAboutUnusedMappedSuperclasses(Map mappedSuperClasses) { - assert OrmModelLogging.ORM_MODEL_LOGGER.isDebugEnabled(); - for ( Map.Entry entry : mappedSuperClasses.entrySet() ) { - OrmModelLogging.ORM_MODEL_LOGGER.debugf( - "Encountered MappedSuperclass [%s] which was unused in any entity hierarchies", - entry.getKey() - ); - } - } - - private static void collectListedResources( - List explicitlyListedClasses, - ActiveClassInclusions classInclusions, - ActivePackageInclusions packageInclusions, - SourceModelBuildingContext sourceModelBuildingContext) { - final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); - final ClassLoading classLoading = sourceModelBuildingContext.getClassLoading(); - - explicitlyListedClasses.forEach( (listed) -> { - if ( listed.endsWith( "package-info" ) ) { - // we know it is a package - final String packageName = StringHelper.qualifier( listed ); - final Package packageForName = classLoading.packageForName( packageName ); - assert packageForName != null; - packageInclusions.addInclusion( classDetailsRegistry.resolvePackageDetails( - packageName, - () -> new JdkPackageDetailsImpl( packageForName, sourceModelBuildingContext ) - ) ); - } - else { - // could be a class or package - try { - final ClassDetails classDetails = classDetailsRegistry.resolveClassDetails( listed ); - if ( classDetails != null ) { - classInclusions.addInclusion( classDetails ); - } - } - catch (UnknownClassException e) { - // see if it is a package - final Package packageForName = classLoading.packageForName( listed ); - if ( packageForName == null ) { - // todo : what to do here? - } - else { - packageInclusions.addInclusion( classDetailsRegistry.resolvePackageDetails( - listed, - () -> new JdkPackageDetailsImpl( packageForName, sourceModelBuildingContext ) - ) ); - } - } - } - } ); - } - - private static void fillRegistries(SourceModelBuildingContext buildingContext) { - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); - final IndexView jandexIndex = buildingContext.getJandexIndex(); - - for ( ClassInfo knownClass : jandexIndex.getKnownClasses() ) { - final String className = knownClass.name().toString(); - if ( className.endsWith( "package-info" ) ) { - classDetailsRegistry.resolvePackageDetails( - className, - () -> new JandexPackageDetails( knownClass, buildingContext ) - ); - continue; - } - - if ( knownClass.isAnnotation() ) { - // it is always safe to load the annotation classes - we will never be enhancing them - //noinspection rawtypes - final Class annotationClass = buildingContext - .getClassLoading() - .classForName( className ); - //noinspection unchecked - annotationDescriptorRegistry.resolveDescriptor( - annotationClass, - (t) -> JdkBuilders.buildAnnotationDescriptor( annotationClass, buildingContext ) - ); - } - - classDetailsRegistry.resolveClassDetails( - className, - () -> new JandexClassDetails( knownClass, buildingContext ) - ); - } - } - - private static void processResources( - ClassInclusions classInclusions, - PackageInclusions packageInclusions, - ProcessResultCollector processResultCollector, - Set rootEntities, - Map mappedSuperClasses, - Map embeddables, - Map unusedMappedSuperClasses, - OrmModelBuildingContext mappingBuildingContext) { - final ClassDetailsRegistry classDetailsRegistry = mappingBuildingContext.getClassDetailsRegistry(); - classDetailsRegistry.forEachClassDetails( (classDetails) -> { - if ( classInclusions != null && !classInclusions.shouldInclude( classDetails ) ) { - // skip this class - return; - } - - processResultCollector.apply( classDetails ); - - if ( classDetails.getAnnotationUsage( JpaAnnotations.MAPPED_SUPERCLASS ) != null ) { - unusedMappedSuperClasses.put( classDetails.getName(), classDetails ); - if ( classDetails.getClassName() != null ) { - mappedSuperClasses.put( classDetails.getClassName(), classDetails ); - } - } - else if ( classDetails.getAnnotationUsage( JpaAnnotations.ENTITY ) != null ) { - if ( EntityHierarchyBuilder.isRoot( classDetails ) ) { - rootEntities.add( classDetails ); - } - } - else if ( classDetails.getAnnotationUsage( Embeddable.class ) != null ) { - if ( classDetails.getClassName() != null ) { - embeddables.put( classDetails.getClassName(), classDetails ); - } - } - } ); - - classDetailsRegistry.forEachPackageDetails( (packageDetails) -> { - if ( packageInclusions != null && !packageInclusions.shouldInclude( packageDetails ) ) { - // skip this class - return; - } - - processResultCollector.apply( packageDetails ); - } ); - } - - @FunctionalInterface - private interface ClassInclusions { - boolean shouldInclude(ClassDetails classDetails); - } - - private static class ActiveClassInclusions implements ClassInclusions { - private final Set inclusionList = new HashSet<>(); - - private void addInclusion(ClassDetails classDetails) { - inclusionList.add( classDetails ); - } - - @Override - public boolean shouldInclude(ClassDetails classDetails) { - return inclusionList.contains( classDetails ); - } - } - - @FunctionalInterface - private interface PackageInclusions { - boolean shouldInclude(PackageDetails packageDetails); - } - - private static class ActivePackageInclusions implements PackageInclusions { - private final Set inclusionList = new HashSet<>(); - - private void addInclusion(PackageDetails packageDetails) { - inclusionList.add( packageDetails ); - } - - @Override - public boolean shouldInclude(PackageDetails packageDetails) { - return inclusionList.contains( packageDetails ); - } - } -} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/SequenceGeneratorRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/SequenceGeneratorRegistration.java index c57094a..b0ec0c8 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/SequenceGeneratorRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/SequenceGeneratorRegistration.java @@ -13,8 +13,6 @@ /** * Global registration of a sequence generator * - * @see org.hibernate.models.orm.spi.Processor.Options#areGeneratorsGlobal() - * * @author Steve Ebersole */ public class SequenceGeneratorRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/TableGeneratorRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/TableGeneratorRegistration.java index 5763aff..0fab6de 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/TableGeneratorRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/TableGeneratorRegistration.java @@ -13,8 +13,6 @@ /** * Global registration of a table generator * - * @see org.hibernate.models.orm.spi.Processor.Options#areGeneratorsGlobal() - * * @author Steve Ebersole */ public class TableGeneratorRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/UserTypeRegistration.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/UserTypeRegistration.java index de11d8e..f6368c8 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/UserTypeRegistration.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/spi/UserTypeRegistration.java @@ -9,6 +9,10 @@ import org.hibernate.models.source.spi.ClassDetails; /** + * Registration for a {@linkplain org.hibernate.usertype.UserType} + * + * @see org.hibernate.annotations.TypeRegistration + * * @author Steve Ebersole */ public class UserTypeRegistration { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java index 5da987a..75d3cb0 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java @@ -32,8 +32,8 @@ import org.hibernate.models.ModelsException; import org.hibernate.models.internal.CollectionHelper; import org.hibernate.models.internal.StringHelper; -import org.hibernate.models.orm.spi.Processor; import org.hibernate.models.orm.xml.spi.PersistenceUnitMetadata; +import org.hibernate.models.orm.xml.spi.XmlProcessingResult; import org.hibernate.models.source.internal.MutableClassDetails; import org.hibernate.models.source.internal.MutableMemberDetails; import org.hibernate.models.source.internal.SourceModelLogging; @@ -473,7 +473,7 @@ private static void adjustNonDynamicTypeMember( } public static void processOverrideEntity( - List> entityOverrides, + List> entityOverrides, PersistenceUnitMetadata persistenceUnitMetadata, SourceModelBuildingContext sourceModelBuildingContext) { entityOverrides.forEach( (overrideTuple) -> { @@ -585,7 +585,7 @@ private static void processMappedSuperclassMetadata( } public static void processOverrideMappedSuperclass( - List> mappedSuperclassesOverrides, + List> mappedSuperclassesOverrides, PersistenceUnitMetadata persistenceUnitMetadata, SourceModelBuildingContext sourceModelBuildingContext) { mappedSuperclassesOverrides.forEach( (overrideTuple) -> { @@ -667,7 +667,7 @@ private static void processEmbeddableMetadata( } public static void processOverrideEmbeddable( - List> embeddableOverrides, + List> embeddableOverrides, PersistenceUnitMetadata persistenceUnitMetadata, SourceModelBuildingContext sourceModelBuildingContext) { embeddableOverrides.forEach( (overrideTuple) -> { diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlPreProcessingResultImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlPreProcessingResultImpl.java new file mode 100644 index 0000000..6e01c9e --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlPreProcessingResultImpl.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.models.orm.xml.spi.XmlPreProcessingResult; + +/** + * @author Steve Ebersole + */ +public class XmlPreProcessingResultImpl implements XmlPreProcessingResult { + private final PersistenceUnitMetadataImpl persistenceUnitMetadata = new PersistenceUnitMetadataImpl(); + private final List documents = new ArrayList<>(); + private final List managedClasses = new ArrayList<>(); + private final List managedNames = new ArrayList<>(); + + @Override + public PersistenceUnitMetadataImpl getPersistenceUnitMetadata() { + return persistenceUnitMetadata; + } + + @Override + public List getDocuments() { + return documents; + } + + @Override + public List getMappedClasses() { + return managedClasses; + } + + @Override + public List getMappedNames() { + return managedNames; + } + + public void addDocument(JaxbEntityMappingsImpl document) { + persistenceUnitMetadata.apply( document.getPersistenceUnitMetadata() ); + documents.add( document ); + document.getEmbeddables().forEach( (jaxbEmbeddable) -> { + if ( StringHelper.isNotEmpty( jaxbEmbeddable.getClazz() ) ) { + managedClasses.add( XmlProcessingHelper.determineClassName( document, jaxbEmbeddable ) ); + } + if ( StringHelper.isNotEmpty( jaxbEmbeddable.getName() ) ) { + managedNames.add( jaxbEmbeddable.getName() ); + } + } ); + document.getMappedSuperclasses().forEach( (jaxbMappedSuperclass) -> { + managedClasses.add( XmlProcessingHelper.determineClassName( document, jaxbMappedSuperclass ) ); + } ); + document.getEntities().forEach( (jaxbEntity) -> { + if ( StringHelper.isNotEmpty( jaxbEntity.getClazz() ) ) { + managedClasses.add( XmlProcessingHelper.determineClassName( document, jaxbEntity ) ); + } + if ( StringHelper.isNotEmpty( jaxbEntity.getName() ) ) { + managedNames.add( jaxbEntity.getName() ); + } + } ); + } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlProcessingResultImpl.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlProcessingResultImpl.java new file mode 100644 index 0000000..4fffdac --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlProcessingResultImpl.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbMappedSuperclassImpl; +import org.hibernate.models.orm.xml.spi.PersistenceUnitMetadata; +import org.hibernate.models.orm.xml.spi.XmlProcessingResult; +import org.hibernate.models.source.spi.SourceModelBuildingContext; + +/** + * @author Steve Ebersole + */ +public class XmlProcessingResultImpl implements XmlProcessingResult { + private final List> entityOverrides = new ArrayList<>(); + private final List> mappedSuperclassesOverrides = new ArrayList<>(); + private final List> embeddableOverrides = new ArrayList<>(); + + public void addEntityOverride(OverrideTuple overrideTuple) { + entityOverrides.add( overrideTuple ); + } + + public void addMappedSuperclassesOverride(OverrideTuple overrideTuple) { + mappedSuperclassesOverrides.add( overrideTuple ); + } + + public void addEmbeddableOverride(OverrideTuple overrideTuple) { + embeddableOverrides.add( overrideTuple ); + } + + @Override + public void apply(PersistenceUnitMetadata metadata, SourceModelBuildingContext buildingContext) { + ManagedTypeProcessor.processOverrideEmbeddable( getEmbeddableOverrides(), metadata, buildingContext ); + + ManagedTypeProcessor.processOverrideMappedSuperclass( getMappedSuperclassesOverrides(), metadata, buildingContext ); + + ManagedTypeProcessor.processOverrideEntity( getEntityOverrides(), metadata, buildingContext ); + } + + @Override + public List> getEntityOverrides() { + return entityOverrides; + } + + @Override + public List> getMappedSuperclassesOverrides() { + return mappedSuperclassesOverrides; + } + + @Override + public List> getEmbeddableOverrides() { + return embeddableOverrides; + } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/package-info.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/package-info.java index be7a9d4..617fff8 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/package-info.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/package-info.java @@ -9,7 +9,22 @@ * Support for processing mapping XML files, ultimately creating/updating * {@linkplain org.hibernate.models.source.spi.AnnotationUsage annotation} references * on the model's {@linkplain org.hibernate.models.source.spi.AnnotationTarget targets} - * based on the XML. + * based on the XML.

    + *
  1. + * First performs some {@linkplain org.hibernate.models.orm.xml.spi.XmlPreProcessor pre-processing} + * which aggregates information across all XML mappings + *
  2. + *
  3. + * Next performs XML {@linkplain org.hibernate.models.orm.xml.spi.XmlProcessor processing} which + * applies metadata-complete mappings and collects overlay/override XML for later application. + *
  4. + *
  5. + * Performs XML {@linkplain org.hibernate.models.orm.xml.spi.XmlProcessingResult post-processing} which + * applies overlay/override XML. + *
  6. + *
+ *

+ * First step is some {@linkplain } * * @author Steve Ebersole */ diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessingResult.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessingResult.java new file mode 100644 index 0000000..f58e3c9 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessingResult.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.spi; + +import java.util.List; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbManagedType; +import org.hibernate.models.orm.xml.internal.PersistenceUnitMetadataImpl; + +/** + * Result of {@linkplain XmlPreProcessor#preProcessXmlResources} + * + * @author Steve Ebersole + */ +public interface XmlPreProcessingResult { + /** + * Aggregated persistence unit defaults and metadata + */ + PersistenceUnitMetadataImpl getPersistenceUnitMetadata(); + + /** + * All XML documents (JAXB roots) + */ + List getDocuments(); + + /** + * All classes named across all XML mappings + * + * @see JaxbManagedType#getClazz() + */ + List getMappedClasses(); + + /** + * All "type names" named across all XML mappings. + * + * @apiNote This accounts for dynamic models + * + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl#getName() + * @see org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableImpl#getName() + */ + List getMappedNames(); +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessor.java new file mode 100644 index 0000000..5210731 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlPreProcessor.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.spi; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; +import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor; +import org.hibernate.boot.jaxb.spi.Binding; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.models.orm.xml.internal.XmlPreProcessingResultImpl; + +/** + * Performs pre-processing across XML mappings to collect data + * that makes additional steps easier and more efficient + * + * @author Steve Ebersole + */ +public class XmlPreProcessor { + + /** + * Build an XmlResources reference based on the given {@code managedResources} + */ + public static XmlPreProcessingResult preProcessXmlResources(ManagedResources managedResources) { + final XmlPreProcessingResultImpl collected = new XmlPreProcessingResultImpl(); + + for ( Binding mappingXmlBinding : managedResources.getXmlMappingBindings() ) { + collected.addDocument( (JaxbEntityMappingsImpl) mappingXmlBinding.getRoot() ); + } + + return collected; + } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessingResult.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessingResult.java new file mode 100644 index 0000000..731a117 --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessingResult.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.spi; + +import java.util.List; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbManagedType; +import org.hibernate.boot.jaxb.mapping.spi.JaxbMappedSuperclassImpl; +import org.hibernate.models.source.spi.SourceModelBuildingContext; + +/** + * Collected XML override mappings we can apply wholesale after + * processing metadata-complete mappings and annotations. + * + * @author Steve Ebersole + */ +public interface XmlProcessingResult { + /** + * Tuple of an override descriptor ({@code managedType}) along with the JAXB root it came from + */ + class OverrideTuple { + private final JaxbEntityMappingsImpl jaxbRoot; + private final M managedType; + + public OverrideTuple(JaxbEntityMappingsImpl jaxbRoot, M managedType) { + this.jaxbRoot = jaxbRoot; + this.managedType = managedType; + } + + public JaxbEntityMappingsImpl getJaxbRoot() { + return jaxbRoot; + } + + public M getManagedType() { + return managedType; + } + } + + void apply(PersistenceUnitMetadata metadata, SourceModelBuildingContext buildingContext); + + List> getEntityOverrides(); + List> getMappedSuperclassesOverrides(); + List> getEmbeddableOverrides(); +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessor.java new file mode 100644 index 0000000..df4095b --- /dev/null +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlProcessor.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.spi; + +import org.hibernate.models.orm.internal.DomainModelCategorizationCollector; +import org.hibernate.models.orm.xml.internal.ManagedTypeProcessor; +import org.hibernate.models.orm.xml.internal.XmlProcessingResultImpl; +import org.hibernate.models.source.spi.SourceModelBuildingContext; + +/** + * Processes XML mappings - applying metadata-complete mappings and collecting + * override mappings for later processing. + * + * @author Steve Ebersole + */ +public class XmlProcessor { + public static XmlProcessingResult processXml( + XmlPreProcessingResult xmlPreProcessingResult, + DomainModelCategorizationCollector modelCategorizationCollector, + SourceModelBuildingContext sourceModelBuildingContext) { + final boolean xmlMappingsGloballyComplete = xmlPreProcessingResult.getPersistenceUnitMetadata().areXmlMappingsComplete(); + final XmlProcessingResultImpl xmlOverlay = new XmlProcessingResultImpl(); + + xmlPreProcessingResult.getDocuments().forEach( (jaxbRoot) -> { + modelCategorizationCollector.apply( jaxbRoot ); + + jaxbRoot.getEmbeddables().forEach( (jaxbEmbeddable) -> { + if ( xmlMappingsGloballyComplete || jaxbEmbeddable.isMetadataComplete() == Boolean.TRUE ) { + // the XML mapping is complete, we can process it immediately + ManagedTypeProcessor.processCompleteEmbeddable( jaxbRoot, jaxbEmbeddable, xmlPreProcessingResult.getPersistenceUnitMetadata(), sourceModelBuildingContext ); + } + else { + // otherwise, wait to process it until later + xmlOverlay.addEmbeddableOverride( new XmlProcessingResult.OverrideTuple<>( jaxbRoot, jaxbEmbeddable ) ); + } + } ); + + jaxbRoot.getMappedSuperclasses().forEach( (jaxbMappedSuperclass) -> { + if ( xmlMappingsGloballyComplete || jaxbMappedSuperclass.isMetadataComplete() == Boolean.TRUE ) { + // the XML mapping is complete, we can process it immediately + ManagedTypeProcessor.processCompleteMappedSuperclass( jaxbRoot, jaxbMappedSuperclass, xmlPreProcessingResult.getPersistenceUnitMetadata(), sourceModelBuildingContext ); + } + else { + // otherwise, wait to process it until later + xmlOverlay.addMappedSuperclassesOverride( new XmlProcessingResult.OverrideTuple<>( jaxbRoot, jaxbMappedSuperclass ) ); + } + }); + + jaxbRoot.getEntities().forEach( (jaxbEntity) -> { + if ( xmlMappingsGloballyComplete || jaxbEntity.isMetadataComplete() == Boolean.TRUE ) { + // the XML mapping is complete, we can process it immediately + ManagedTypeProcessor.processCompleteEntity( jaxbRoot, jaxbEntity, xmlPreProcessingResult.getPersistenceUnitMetadata(), sourceModelBuildingContext ); + } + else { + // otherwise, wait to process it until later + xmlOverlay.addEntityOverride( new XmlProcessingResult.OverrideTuple<>( jaxbRoot, jaxbEntity ) ); + } + } ); + } ); + + return xmlOverlay; + } +} diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlResources.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlResources.java deleted file mode 100644 index 3bc1ebd..0000000 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/spi/XmlResources.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.orm.xml.spi; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.boot.jaxb.Origin; -import org.hibernate.boot.jaxb.SourceType; -import org.hibernate.boot.jaxb.internal.MappingBinder; -import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; -import org.hibernate.boot.jaxb.spi.Binding; -import org.hibernate.boot.jaxb.spi.JaxbBindableMappingDescriptor; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.xml.XmlResourceException; -import org.hibernate.models.orm.xml.internal.PersistenceUnitMetadataImpl; -import org.hibernate.models.orm.xml.internal.ResourceStreamLocatorImpl; -import org.hibernate.models.source.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ClassLoading; - -import static org.hibernate.boot.jaxb.internal.MappingBinder.NON_VALIDATING; - -/** - * Keeps track of collected/aggregated {@linkplain #getPersistenceUnitMetadata() metadata} - * across all {@linkplain #getDocuments() mapping documents} in the persistence-unit - * - * @author Steve Ebersole - */ -public class XmlResources { - private final PersistenceUnitMetadataImpl persistenceUnitMetadata = new PersistenceUnitMetadataImpl(); - private final List documents = new ArrayList<>(); - - public XmlResources() { - } - - /** - * Build an XmlResources reference based on the given {@code managedResources} - */ - public static XmlResources collectXmlResources( - ManagedResources managedResources, - SourceModelBuildingContext sourceModelBuildingContext) { - final ClassLoading classLoading = sourceModelBuildingContext.getClassLoading(); - final ResourceStreamLocatorImpl resourceStreamLocator = new ResourceStreamLocatorImpl( classLoading ); - final MappingBinder mappingBinder = new MappingBinder( resourceStreamLocator, NON_VALIDATING ); - final XmlResources collected = new XmlResources(); - - final List xmlMappings = managedResources.getXmlMappings(); - for ( int i = 0; i < xmlMappings.size(); i++ ) { - final String xmlMapping = xmlMappings.get( i ); - final URL resource = classLoading.locateResource( xmlMapping ); - if ( resource == null ) { - throw new XmlResourceException( "Unable to locate XML mapping - " + xmlMapping ); - } - try (InputStream inputStream = resource.openStream()) { - final Binding binding = mappingBinder.bind( - inputStream, - new Origin( SourceType.RESOURCE, xmlMapping ) - ); - collected.addDocument( (JaxbEntityMappingsImpl) binding.getRoot() ); - } - catch (IOException e) { - throw new XmlResourceException( "Unable to bind XML mapping - " + xmlMapping, e ); - } - } - - return collected; - } - - /** - * The metadata collected/aggregated across all of the {@linkplain #getDocuments() mapping documents} - * in the persistence-unit. - */ - public PersistenceUnitMetadata getPersistenceUnitMetadata() { - return persistenceUnitMetadata; - } - - /** - * All documents in the persistence-unit - */ - public List getDocuments() { - return documents; - } - - public void addDocument(JaxbEntityMappingsImpl document) { - persistenceUnitMetadata.apply( document.getPersistenceUnitMetadata() ); - documents.add( document ); - } -} diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/bind/HierarchyAttributeProcessorSmokeTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/bind/HierarchyAttributeProcessorSmokeTests.java index bb4751d..32e465b 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/bind/HierarchyAttributeProcessorSmokeTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/bind/HierarchyAttributeProcessorSmokeTests.java @@ -10,24 +10,25 @@ import java.util.Set; import org.hibernate.annotations.TenantId; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.model.process.spi.MetadataBuildingProcess; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.models.orm.bind.internal.HierarchyAttributeProcessor; import org.hibernate.models.orm.bind.internal.HierarchyAttributeProcessor.HierarchyAttributeDescriptor; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; -import org.hibernate.models.orm.process.MyStringConverter; -import org.hibernate.models.orm.process.MyUuidConverter; -import org.hibernate.models.orm.process.Person; -import org.hibernate.models.orm.process.Root; -import org.hibernate.models.orm.process.Sub; +import org.hibernate.models.orm.process.ManagedResourcesImpl; +import org.hibernate.models.orm.resources.ManagedResourcesSmokeTests; import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; +import org.hibernate.models.orm.spi.ManagedResourcesProcessor; import org.hibernate.models.orm.util.OrmModelBuildingContextTesting; import org.hibernate.models.source.SourceModelTestHelper; import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.source.spi.AnnotationUsage; -import org.hibernate.models.source.spi.MemberDetails; import org.junit.jupiter.api.Test; @@ -115,23 +116,27 @@ private static List buildHierarchyAttributes(Class SIMPLE_CLASS_LOADING ); - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { }, - buildingContext - ); - - final OrmModelBuildingContextTesting ormModelBuildingContext = new OrmModelBuildingContextTesting( buildingContext ); - final List hierarchyAttributeDescriptors = HierarchyAttributeProcessor.preBindHierarchyAttributes( - processResult, - ormModelBuildingContext - ); - - // at this point, `hierarchyAttributeDescriptors` contains one entry per hierarchy in the same iteration order - final Set entityHierarchies = processResult.getEntityHierarchies(); - assertThat( hierarchyAttributeDescriptors.size() ).isEqualTo( entityHierarchies.size() ); - return hierarchyAttributeDescriptors; + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final MetadataSources metadataSources = new MetadataSources( serviceRegistry ).addAnnotatedClass( ManagedResourcesSmokeTests.Person.class ); + final MetadataBuilderImpl.MetadataBuildingOptionsImpl metadataBuildingOptions = new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ); + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( serviceRegistry, metadataBuildingOptions ); + + final CategorizedDomainModel categorizedDomainModel = ManagedResourcesProcessor.processManagedResources( + managedResources, + bootstrapContext + ); + + final OrmModelBuildingContextTesting ormModelBuildingContext = new OrmModelBuildingContextTesting( buildingContext ); + final List hierarchyAttributeDescriptors = HierarchyAttributeProcessor.preBindHierarchyAttributes( + categorizedDomainModel, + ormModelBuildingContext + ); + + // at this point, `hierarchyAttributeDescriptors` contains one entry per hierarchy in the same iteration order + final Set entityHierarchies = categorizedDomainModel.getEntityHierarchies(); + assertThat( hierarchyAttributeDescriptors.size() ).isEqualTo( entityHierarchies.size() ); + return hierarchyAttributeDescriptors; + } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ManagedResourcesImpl.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ManagedResourcesImpl.java new file mode 100644 index 0000000..22d2c97 --- /dev/null +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ManagedResourcesImpl.java @@ -0,0 +1,132 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.process; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.boot.jaxb.Origin; +import org.hibernate.boot.jaxb.SourceType; +import org.hibernate.boot.jaxb.internal.MappingBinder; +import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor; +import org.hibernate.boot.jaxb.spi.Binding; +import org.hibernate.boot.jaxb.spi.JaxbBindableMappingDescriptor; +import org.hibernate.boot.model.convert.spi.ConverterDescriptor; +import org.hibernate.boot.model.process.spi.ManagedResources; + +/** + * @author Steve Ebersole + */ +public class ManagedResourcesImpl implements ManagedResources { + private final Collection> knownClasses; + private final Collection packageNames; + private final Collection> xmlMappings; + + public ManagedResourcesImpl( + Collection> knownClasses, + Collection packageNames, + Collection> xmlMappings) { + this.knownClasses = knownClasses; + this.packageNames = packageNames; + this.xmlMappings = xmlMappings; + } + + @Override + public Collection getAttributeConverterDescriptors() { + return Collections.emptyList(); + } + + @Override + public Collection> getAnnotatedClassReferences() { + return knownClasses == null ? Collections.emptyList() : knownClasses; + } + + @Override + public Collection getAnnotatedClassNames() { + return Collections.emptyList(); + } + + @Override + public Collection getAnnotatedPackageNames() { + return packageNames == null ? Collections.emptyList() : packageNames; + } + + @Override + public Collection> getXmlMappingBindings() { + if ( xmlMappings == null ) { + return Collections.emptyList(); + } + + //noinspection unchecked,rawtypes + return (Collection) xmlMappings; + } + + @Override + public Map> getExtraQueryImports() { + return Collections.emptyMap(); + } + + public static class Builder { + private final MappingBinder mappingBinder; + + private List> classes; + private List packageNames; + private Collection> xmlMappings; + + public Builder() { + mappingBinder = new MappingBinder( + (resourceName) -> Builder.class.getClassLoader().getResourceAsStream( resourceName ), + new MappingBinder.Options() { + @Override + public boolean validateMappings() { + return true; + } + + @Override + public boolean transformHbmMappings() { + return false; + } + } + ); + } + + public Builder addLoadedClasses(Class... classes) { + if ( this.classes == null ) { + this.classes = new ArrayList<>(); + } + Collections.addAll( this.classes, classes ); + return this; + } + + public Builder addPackages(String... packageNames) { + if ( this.packageNames == null ) { + this.packageNames = new ArrayList<>(); + } + Collections.addAll( this.packageNames, packageNames ); + return this; + } + + public ManagedResources build() { + return new ManagedResourcesImpl( classes, packageNames, xmlMappings ); + } + + public Builder addXmlMappings(String resourceName) { + final Binding binding = mappingBinder.bind( + Builder.class.getClassLoader().getResourceAsStream( resourceName ), + new Origin( SourceType.RESOURCE, resourceName ) + ); + if ( xmlMappings == null ) { + xmlMappings = new ArrayList<>(); + } + xmlMappings.add( binding ); + return this; + } + } +} diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ProcessorSmokeTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ProcessorSmokeTests.java index 090b371..4537374 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ProcessorSmokeTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/ProcessorSmokeTests.java @@ -6,8 +6,7 @@ */ package org.hibernate.models.orm.process; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; -import org.hibernate.models.orm.spi.ManagedResources; +import org.hibernate.boot.model.process.spi.ManagedResources; import org.hibernate.models.source.SourceModelTestHelper; import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.ClassDetails; @@ -35,6 +34,7 @@ void simpleTest() { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ManagedResources is built by scanning and from explicit resources // during ORM bootstrap + final ManagedResourcesImpl.Builder managedResourcesBuilder = new ManagedResourcesImpl.Builder(); managedResourcesBuilder .addLoadedClasses( Person.class, MyStringConverter.class ) diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/SimpleProcessorTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/SimpleProcessorTests.java index f497a50..ea800a6 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/SimpleProcessorTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/process/SimpleProcessorTests.java @@ -9,15 +9,17 @@ import java.util.Iterator; import java.util.Map; -import org.hibernate.models.orm.spi.FilterDefRegistration; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; +import org.hibernate.models.orm.spi.FilterDefRegistration; +import org.hibernate.models.orm.spi.ManagedResourcesProcessor; import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.ClassDetails; import org.hibernate.type.CharBooleanConverter; import org.hibernate.type.YesNoConverter; @@ -75,46 +77,30 @@ void testSimpleUsage() { // Below here is work done by hibernate-models. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); - - assertThat( processResult.getEntityHierarchies() ).hasSize( 2 ); - final Iterator hierarchies = processResult.getEntityHierarchies().iterator(); - final EntityHierarchy one = hierarchies.next(); - final EntityHierarchy two = hierarchies.next(); - - assertThat( one.getRoot() ).isNotNull(); - assertThat( one.getRoot().getClassDetails() ).isNotNull(); - assertThat( one.getRoot().getClassDetails().getClassName() ).isNotNull(); - if ( one.getRoot().getClassDetails().getClassName().endsWith( "Person" ) ) { - validatePersonHierarchy( one ); - validateJoinedHierarchy( two ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final MetadataBuilderImpl.MetadataBuildingOptionsImpl metadataBuildingOptions = new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ); + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( serviceRegistry, metadataBuildingOptions ); + final CategorizedDomainModel categorizedDomainModel = ManagedResourcesProcessor.processManagedResources( managedResources, bootstrapContext ); + + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 2 ); + final Iterator hierarchies = categorizedDomainModel.getEntityHierarchies().iterator(); + final EntityHierarchy one = hierarchies.next(); + final EntityHierarchy two = hierarchies.next(); + + assertThat( one.getRoot() ).isNotNull(); + assertThat( one.getRoot().getClassDetails() ).isNotNull(); + assertThat( one.getRoot().getClassDetails().getClassName() ).isNotNull(); + if ( one.getRoot().getClassDetails().getClassName().endsWith( "Person" ) ) { + validatePersonHierarchy( one ); + validateJoinedHierarchy( two ); + } + else { + validatePersonHierarchy( two ); + validateJoinedHierarchy( one ); + } + + validateFilterDefs( categorizedDomainModel.getGlobalRegistrations().getFilterDefRegistrations() ); } - else { - validatePersonHierarchy( two ); - validateJoinedHierarchy( one ); - } - - validateFilterDefs( processResult.getGlobalRegistrations().getFilterDefRegistrations() ); } private void validatePersonHierarchy(EntityHierarchy hierarchy) { diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/resources/ManagedResourcesSmokeTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/resources/ManagedResourcesSmokeTests.java new file mode 100644 index 0000000..3b53d0a --- /dev/null +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/resources/ManagedResourcesSmokeTests.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.resources; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.model.process.spi.MetadataBuildingProcess; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.bind.internal.HierarchyAttributeProcessor; +import org.hibernate.models.orm.internal.OrmModelBuildingContextImpl; +import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; +import org.hibernate.models.orm.spi.EntityHierarchy; +import org.hibernate.models.orm.spi.EntityTypeMetadata; +import org.hibernate.models.orm.spi.ManagedResourcesProcessor; +import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.FieldDetails; + +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.spi.PersistenceUnitInfo; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.models.orm.internal.EntityHierarchyBuilder.createEntityHierarchies; + +/** + * {@linkplain MetadataBuildingProcess#prepare} produces a {@linkplain ManagedResources} which + * represents the complete set of classes and xml mappings. + *

+ * The known XML mappings combine explicit mappings, plus any discovered during scanning. + *

+ * The known classes combine explicit values, plus any discovered during scanning. It also + * already excludes classes as per JPA's {@linkplain PersistenceUnitInfo#excludeUnlistedClasses()} + * handling. + *

+ * The "known classes" + all classes named in "known XML mappings" represents the complete + * set of "managed classes" (JPA's term) which Hibernate will process for annotations - + * {@code @Entity}, {@code @Converter}, ... + *

+ * And is the likely place that hibernate-models-source would hook in to. Let's see how that might work... + * + * @author Steve Ebersole + */ +public class ManagedResourcesSmokeTests { + @Test + void testProcessor() { + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final MetadataSources metadataSources = new MetadataSources( serviceRegistry ).addAnnotatedClass( Person.class ); + final MetadataBuilderImpl.MetadataBuildingOptionsImpl metadataBuildingOptions = new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ); + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( serviceRegistry, metadataBuildingOptions ); + final ManagedResources managedResources = MetadataBuildingProcess.prepare( metadataSources, bootstrapContext ); + + final CategorizedDomainModel categorizedDomainModel = ManagedResourcesProcessor.processManagedResources( + managedResources, + bootstrapContext + ); + + final Set entityHierarchies = categorizedDomainModel.getEntityHierarchies(); + assertThat( entityHierarchies ).hasSize( 1 ); + final EntityTypeMetadata entityDescriptor = entityHierarchies.iterator().next().getRoot(); + final ClassDetails entityClassDetails = entityDescriptor.getClassDetails(); + assertThat( entityClassDetails.getClassName() ).isEqualTo( Person.class.getName() ); + assertThat( entityDescriptor.getAttributes() ).hasSize( 2 ); + + final Iterator attributes = entityDescriptor.getAttributes().iterator(); + final AttributeMetadata firstAttribute = attributes.next(); + final AttributeMetadata secondAttribute = attributes.next(); + + assertThat( firstAttribute.getMember() ).isInstanceOf( FieldDetails.class ); + assertThat( secondAttribute.getMember() ).isInstanceOf( FieldDetails.class ); + + + + final OrmModelBuildingContextImpl mappingBuildingContext = new OrmModelBuildingContextImpl( + categorizedDomainModel.getClassDetailsRegistry(), + categorizedDomainModel.getAnnotationDescriptorRegistry(), + bootstrapContext.getClassmateContext() + ); + + final List hierarchyAttributeDescriptors = HierarchyAttributeProcessor.preBindHierarchyAttributes( + categorizedDomainModel, + mappingBuildingContext + ); + + assertThat( hierarchyAttributeDescriptors ).hasSize( 1 ); + assertThat( hierarchyAttributeDescriptors.get( 0 ).getCollectedIdAttributes() ).isInstanceOf( AttributeMetadata.class ); + final AttributeMetadata idAttr = (AttributeMetadata) hierarchyAttributeDescriptors.get( 0 ).getCollectedIdAttributes(); + assertThat( idAttr.getName() ).isEqualTo( "id" ); + assertThat( idAttr.getMember() ).isInstanceOf( FieldDetails.class ); + } + } + + @Entity(name="Person") + @Table(name="persons") + public static class Person { + @Id + private Integer id; + private String name; + } +} diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/util/OrmModelBuildingContextTesting.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/util/OrmModelBuildingContextTesting.java index 7674391..9051183 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/util/OrmModelBuildingContextTesting.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/util/OrmModelBuildingContextTesting.java @@ -11,9 +11,6 @@ import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; import org.hibernate.models.source.spi.ClassDetailsRegistry; import org.hibernate.models.source.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ClassLoading; - -import org.jboss.jandex.IndexView; import jakarta.persistence.SharedCacheMode; @@ -23,8 +20,6 @@ public class OrmModelBuildingContextTesting implements OrmModelBuildingContext { private final ClassDetailsRegistry classDetailsRegistry; private final AnnotationDescriptorRegistry annotationDescriptorRegistry; - private final ClassLoading classLoading; - private final IndexView jandexIndex; private final ClassmateContext classmateContext; private final SharedCacheMode sharedCacheMode; @@ -38,8 +33,6 @@ public OrmModelBuildingContextTesting( SharedCacheMode sharedCacheMode) { classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); annotationDescriptorRegistry = sourceModelBuildingContext.getAnnotationDescriptorRegistry(); - classLoading = sourceModelBuildingContext.getClassLoading(); - jandexIndex = sourceModelBuildingContext.getJandexIndex(); this.classmateContext = classmateContext; this.sharedCacheMode = sharedCacheMode; } @@ -54,16 +47,6 @@ public AnnotationDescriptorRegistry getAnnotationDescriptorRegistry() { return annotationDescriptorRegistry; } - @Override - public ClassLoading getClassLoading() { - return classLoading; - } - - @Override - public IndexView getJandexIndex() { - return jandexIndex; - } - @Override public ClassmateContext getClassmateContext() { return classmateContext; diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/XmlProcessingSmokeTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/XmlProcessingSmokeTests.java index eede74b..65ee199 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/XmlProcessingSmokeTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/XmlProcessingSmokeTests.java @@ -10,11 +10,11 @@ import java.util.Map; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; -import org.hibernate.models.orm.spi.FilterDefRegistration; +import org.hibernate.models.orm.internal.DomainModelCategorizationCollector; import org.hibernate.models.orm.internal.GlobalRegistrationsImpl; -import org.hibernate.models.orm.internal.ProcessResultCollector; +import org.hibernate.models.orm.spi.FilterDefRegistration; import org.hibernate.models.orm.xml.internal.XmlDocumentImpl; -import org.hibernate.models.orm.xml.spi.XmlResources; +import org.hibernate.models.orm.xml.internal.XmlPreProcessingResultImpl; import org.hibernate.models.orm.xml.spi.PersistenceUnitMetadata; import org.hibernate.models.source.SourceModelTestHelper; import org.hibernate.models.source.internal.StringTypeDescriptor; @@ -38,15 +38,13 @@ public class XmlProcessingSmokeTests { @Test void testGlobals() { - final XmlResources collector = new XmlResources(); + final XmlPreProcessingResultImpl collector = new XmlPreProcessingResultImpl(); collector.addDocument( loadMapping( "mappings/globals.xml", SIMPLE_CLASS_LOADING ) ); - - } @Test void testPersistenceUnitDefaults1() { - final XmlResources collector = new XmlResources(); + final XmlPreProcessingResultImpl collector = new XmlPreProcessingResultImpl(); final JaxbEntityMappingsImpl simple1 = loadMapping( "mappings/simple1.xml", SIMPLE_CLASS_LOADING ); final JaxbEntityMappingsImpl simple2 = loadMapping( "mappings/simple2.xml", SIMPLE_CLASS_LOADING ); @@ -71,7 +69,7 @@ void testPersistenceUnitDefaults1() { @Test void testPersistenceUnitDefaults2() { - final XmlResources collector = new XmlResources(); + final XmlPreProcessingResultImpl collector = new XmlPreProcessingResultImpl(); collector.addDocument( loadMapping( "mappings/simple2.xml", SIMPLE_CLASS_LOADING ) ); collector.addDocument( loadMapping( "mappings/simple1.xml", SIMPLE_CLASS_LOADING ) ); @@ -94,7 +92,7 @@ void testPersistenceUnitDefaults2() { @Test void testSimpleXmlDocumentBuilding() { - final XmlResources collector = new XmlResources(); + final XmlPreProcessingResultImpl collector = new XmlPreProcessingResultImpl(); final JaxbEntityMappingsImpl simple1 = loadMapping( "mappings/simple1.xml", SIMPLE_CLASS_LOADING ); final JaxbEntityMappingsImpl simple2 = loadMapping( "mappings/simple2.xml", SIMPLE_CLASS_LOADING ); @@ -121,15 +119,15 @@ void testSimpleXmlDocumentBuilding() { @Test void testSimpleGlobalXmlProcessing() { final SourceModelBuildingContext buildingContext = SourceModelTestHelper.createBuildingContext(); - final XmlResources collectedXmlResources = new XmlResources(); + final XmlPreProcessingResultImpl collectedXmlResources = new XmlPreProcessingResultImpl(); final JaxbEntityMappingsImpl xmlMapping = loadMapping( "mappings/globals.xml", SIMPLE_CLASS_LOADING ); collectedXmlResources.addDocument( xmlMapping ); - final ProcessResultCollector processResultCollector = new ProcessResultCollector( false, buildingContext ); - collectedXmlResources.getDocuments().forEach( processResultCollector::apply ); + final DomainModelCategorizationCollector collector = new DomainModelCategorizationCollector( false, buildingContext.getClassDetailsRegistry() ); + collectedXmlResources.getDocuments().forEach( collector::apply ); - final GlobalRegistrationsImpl globalRegistrations = processResultCollector.getGlobalRegistrations(); + final GlobalRegistrationsImpl globalRegistrations = collector.getGlobalRegistrations(); assertThat( globalRegistrations.getJavaTypeRegistrations() ).hasSize( 1 ); assertThat( globalRegistrations.getJavaTypeRegistrations().get(0).getDescriptor().getClassName() ) .isEqualTo( StringTypeDescriptor.class.getName() ); diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlInheritanceTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlInheritanceTests.java index 6e8197c..d49ccf6 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlInheritanceTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlInheritanceTests.java @@ -6,15 +6,19 @@ */ package org.hibernate.models.orm.xml.complete; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl.MetadataBuildingOptionsImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; +import org.hibernate.models.orm.spi.ManagedResourcesProcessor; import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.junit.jupiter.api.Test; @@ -25,6 +29,7 @@ import static jakarta.persistence.InheritanceType.JOINED; import static org.assertj.core.api.Assertions.assertThat; import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -42,35 +47,22 @@ void testIt() { Root.class, Sub.class ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( managedResources, bootstrapContext ); - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - assertThat( hierarchy.getInheritanceType() ).isEqualTo( JOINED ); + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + assertThat( hierarchy.getInheritanceType() ).isEqualTo( JOINED ); - final EntityTypeMetadata rootMetadata = hierarchy.getRoot(); - assertThat( rootMetadata.getClassDetails().getClassName() ).isEqualTo( Root.class.getName() ); - final AttributeMetadata idAttr = rootMetadata.findAttribute( "id" ); - assertThat( idAttr.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); + final EntityTypeMetadata rootMetadata = hierarchy.getRoot(); + assertThat( rootMetadata.getClassDetails().getClassName() ).isEqualTo( Root.class.getName() ); + final AttributeMetadata idAttr = rootMetadata.findAttribute( "id" ); + assertThat( idAttr.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); + } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlWithEmbeddableTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlWithEmbeddableTests.java index 9ca6150..86ca62e 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlWithEmbeddableTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/CompleteXmlWithEmbeddableTests.java @@ -6,30 +6,28 @@ */ package org.hibernate.models.orm.xml.complete; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; -import org.hibernate.models.orm.xml.SimpleEntity; -import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.junit.jupiter.api.Test; -import org.jboss.jandex.Index; - import jakarta.persistence.AccessType; import jakarta.persistence.Basic; import jakarta.persistence.Embedded; import jakarta.persistence.Id; import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; import static org.hibernate.models.orm.spi.AttributeMetadata.AttributeNature.BASIC; import static org.hibernate.models.orm.spi.AttributeMetadata.AttributeNature.EMBEDDED; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -41,48 +39,32 @@ void testIt() { managedResourcesBuilder.addXmlMappings( "mappings/complete/simple-person.xml" ); final ManagedResources managedResources = managedResourcesBuilder.build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( - SIMPLE_CLASS_LOADING, - SimplePerson.class, - Name.class - ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - final EntityTypeMetadata personMetadata = hierarchy.getRoot(); - assertThat( personMetadata.getAccessType() ).isEqualTo( AccessType.FIELD ); + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata personMetadata = hierarchy.getRoot(); + assertThat( personMetadata.getAccessType() ).isEqualTo( AccessType.FIELD ); - assertThat( personMetadata.getAttributes() ).hasSize( 2 ); + assertThat( personMetadata.getAttributes() ).hasSize( 2 ); - final AttributeMetadata idAttribute = personMetadata.findAttribute( "id" ); - assertThat( idAttribute.getNature() ).isEqualTo( BASIC ); - assertThat( idAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); - assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); + final AttributeMetadata idAttribute = personMetadata.findAttribute( "id" ); + assertThat( idAttribute.getNature() ).isEqualTo( BASIC ); + assertThat( idAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); + assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); - final AttributeMetadata nameAttribute = personMetadata.findAttribute( "name" ); - assertThat( nameAttribute.getNature() ).isEqualTo( EMBEDDED ); - assertThat( nameAttribute.getMember().getAnnotationUsage( Embedded.class ) ).isNotNull(); + final AttributeMetadata nameAttribute = personMetadata.findAttribute( "name" ); + assertThat( nameAttribute.getNature() ).isEqualTo( EMBEDDED ); + assertThat( nameAttribute.getMember().getAnnotationUsage( Embedded.class ) ).isNotNull(); + } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java index 98c2300..156e2ec 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java @@ -10,28 +10,27 @@ import org.hibernate.annotations.Filter; import org.hibernate.annotations.SqlFragmentAlias; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; import org.hibernate.models.orm.xml.SimpleEntity; -import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.AnnotationUsage; import org.junit.jupiter.api.Test; -import org.jboss.jandex.Index; - import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Id; import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -44,55 +43,40 @@ void testSimpleCompleteEntity() { managedResourcesBuilder.addXmlMappings( "mappings/complete/simple-complete.xml" ); final ManagedResources managedResources = managedResourcesBuilder.build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( - SIMPLE_CLASS_LOADING, - SimpleEntity.class - ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); - - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); - - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - final EntityTypeMetadata root = hierarchy.getRoot(); - assertThat( root.getClassDetails().getClassName() ).isEqualTo( SimpleEntity.class.getName() ); - assertThat( root.getNumberOfAttributes() ).isEqualTo( 2 ); - - final AttributeMetadata idAttribute = root.findAttribute( "id" ); - assertThat( idAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); - assertThat( idAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); - assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); - final AnnotationUsage idColumnAnn = idAttribute.getMember().getAnnotationUsage( Column.class ); - assertThat( idColumnAnn ).isNotNull(); - assertThat( idColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "pk" ); - - final AttributeMetadata nameAttribute = root.findAttribute( "name" ); - assertThat( nameAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); - assertThat( nameAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); - final AnnotationUsage nameColumnAnn = nameAttribute.getMember().getAnnotationUsage( Column.class ); - assertThat( nameColumnAnn ).isNotNull(); - assertThat( nameColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "description" ); - - validateFilterUsage( root.getClassDetails().getAnnotationUsage( Filter.class ) ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); + + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); + + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata root = hierarchy.getRoot(); + assertThat( root.getClassDetails().getClassName() ).isEqualTo( SimpleEntity.class.getName() ); + assertThat( root.getNumberOfAttributes() ).isEqualTo( 2 ); + + final AttributeMetadata idAttribute = root.findAttribute( "id" ); + assertThat( idAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); + assertThat( idAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); + assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); + final AnnotationUsage idColumnAnn = idAttribute.getMember().getAnnotationUsage( Column.class ); + assertThat( idColumnAnn ).isNotNull(); + assertThat( idColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "pk" ); + + final AttributeMetadata nameAttribute = root.findAttribute( "name" ); + assertThat( nameAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); + assertThat( nameAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); + final AnnotationUsage nameColumnAnn = nameAttribute.getMember().getAnnotationUsage( Column.class ); + assertThat( nameColumnAnn ).isNotNull(); + assertThat( nameColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "description" ); + + validateFilterUsage( root.getClassDetails().getAnnotationUsage( Filter.class ) ); + } } private void validateFilterUsage(AnnotationUsage filter) { diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java index 265045f..138edf9 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java @@ -9,24 +9,22 @@ import java.util.Set; import org.hibernate.annotations.JavaType; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; import org.hibernate.boot.internal.Target; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; -import org.hibernate.models.orm.xml.SimpleEntity; -import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.FieldDetails; import org.junit.jupiter.api.Test; -import org.jboss.jandex.Index; - import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -37,44 +35,32 @@ void testSimpleDynamicModel() { final ManagedResources managedResources = new ManagedResourcesImpl.Builder() .addXmlMappings( "mappings/dynamic/dynamic-simple.xml" ) .build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( SIMPLE_CLASS_LOADING ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); - - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - final EntityTypeMetadata rootEntity = hierarchy.getRoot(); - assertThat( rootEntity.getClassDetails().getClassName() ).isNull(); - assertThat( rootEntity.getClassDetails().getName() ).isEqualTo( "SimpleEntity" ); - - final FieldDetails idField = rootEntity.getClassDetails().findFieldByName( "id" ); - assertThat( idField.getType().getClassName() ).isEqualTo( Integer.class.getName() ); - - final FieldDetails nameField = rootEntity.getClassDetails().findFieldByName( "name" ); - assertThat( nameField.getType().getClassName() ).isEqualTo( Object.class.getName() ); - assertThat( nameField.getAnnotationUsage( JavaType.class ) ).isNotNull(); - - final FieldDetails qtyField = rootEntity.getClassDetails().findFieldByName( "quantity" ); - assertThat( qtyField.getType().getClassName() ).isEqualTo( int.class.getName() ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); + + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata rootEntity = hierarchy.getRoot(); + assertThat( rootEntity.getClassDetails().getClassName() ).isNull(); + assertThat( rootEntity.getClassDetails().getName() ).isEqualTo( "SimpleEntity" ); + + final FieldDetails idField = rootEntity.getClassDetails().findFieldByName( "id" ); + assertThat( idField.getType().getClassName() ).isEqualTo( Integer.class.getName() ); + + final FieldDetails nameField = rootEntity.getClassDetails().findFieldByName( "name" ); + assertThat( nameField.getType().getClassName() ).isEqualTo( Object.class.getName() ); + assertThat( nameField.getAnnotationUsage( JavaType.class ) ).isNotNull(); + + final FieldDetails qtyField = rootEntity.getClassDetails().findFieldByName( "quantity" ); + assertThat( qtyField.getType().getClassName() ).isEqualTo( int.class.getName() ); + } } @Test @@ -82,48 +68,36 @@ void testSemiSimpleDynamicModel() { final ManagedResources managedResources = new ManagedResourcesImpl.Builder() .addXmlMappings( "mappings/dynamic/dynamic-semi-simple.xml" ) .build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( SIMPLE_CLASS_LOADING ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); - - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - final EntityTypeMetadata rootEntity = hierarchy.getRoot(); - assertThat( rootEntity.getClassDetails().getClassName() ).isNull(); - assertThat( rootEntity.getClassDetails().getName() ).isEqualTo( "Contact" ); - - final FieldDetails idField = rootEntity.getClassDetails().findFieldByName( "id" ); - assertThat( idField.getType().getClassName() ).isEqualTo( Integer.class.getName() ); - - final FieldDetails nameField = rootEntity.getClassDetails().findFieldByName( "name" ); - assertThat( nameField.getType().getClassName() ).isNull(); - assertThat( nameField.getType().getName() ).isEqualTo( "Name" ); - assertThat( nameField.getAnnotationUsage( Target.class ) ).isNotNull(); - assertThat( nameField.getAnnotationUsage( Target.class ).getString( "value" ) ).isEqualTo( "Name" ); - - assertThat( nameField.getType().getFields() ).hasSize( 2 ); - - final FieldDetails labelsField = rootEntity.getClassDetails().findFieldByName( "labels" ); - assertThat( labelsField.getType().getClassName() ).isEqualTo( Set.class.getName() ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); + + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata rootEntity = hierarchy.getRoot(); + assertThat( rootEntity.getClassDetails().getClassName() ).isNull(); + assertThat( rootEntity.getClassDetails().getName() ).isEqualTo( "Contact" ); + + final FieldDetails idField = rootEntity.getClassDetails().findFieldByName( "id" ); + assertThat( idField.getType().getClassName() ).isEqualTo( Integer.class.getName() ); + + final FieldDetails nameField = rootEntity.getClassDetails().findFieldByName( "name" ); + assertThat( nameField.getType().getClassName() ).isNull(); + assertThat( nameField.getType().getName() ).isEqualTo( "Name" ); + assertThat( nameField.getAnnotationUsage( Target.class ) ).isNotNull(); + assertThat( nameField.getAnnotationUsage( Target.class ).getString( "value" ) ).isEqualTo( "Name" ); + + assertThat( nameField.getType().getFields() ).hasSize( 2 ); + + final FieldDetails labelsField = rootEntity.getClassDetails().findFieldByName( "labels" ); + assertThat( labelsField.getType().getClassName() ).isEqualTo( Set.class.getName() ); + } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/globals/EntityListenerTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/globals/EntityListenerTests.java index e1a8551..702a903 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/globals/EntityListenerTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/globals/EntityListenerTests.java @@ -8,22 +8,20 @@ import java.util.List; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityListenerRegistration; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; -import org.hibernate.models.orm.xml.SimpleEntity; -import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.MethodDetails; import org.junit.jupiter.api.Test; -import org.jboss.jandex.Index; - import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -35,41 +33,25 @@ void testGlobalRegistration() { .addXmlMappings( "mappings/globals.xml" ) .build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( - SIMPLE_CLASS_LOADING, - SimpleEntity.class - ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); - - final List registrations = processResult - .getGlobalRegistrations() - .getEntityListenerRegistrations(); - assertThat( registrations ).hasSize( 1 ); - final EntityListenerRegistration registration = registrations.get( 0 ); - final MethodDetails postPersistMethod = registration.getPostPersistMethod(); - assertThat( postPersistMethod ).isNotNull(); - assertThat( postPersistMethod.getReturnType() ).isNull(); - assertThat( postPersistMethod.getArgumentTypes() ).hasSize( 1 ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); + final List registrations = categorizedDomainModel + .getGlobalRegistrations() + .getEntityListenerRegistrations(); + assertThat( registrations ).hasSize( 1 ); + final EntityListenerRegistration registration = registrations.get( 0 ); + final MethodDetails postPersistMethod = registration.getPostPersistMethod(); + assertThat( postPersistMethod ).isNotNull(); + assertThat( postPersistMethod.getReturnType() ).isNull(); + assertThat( postPersistMethod.getArgumentTypes() ).hasSize( 1 ); + } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/override/SimpleOverrideXmlTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/override/SimpleOverrideXmlTests.java index 58fbe4a..010d2cf 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/override/SimpleOverrideXmlTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/override/SimpleOverrideXmlTests.java @@ -6,28 +6,27 @@ */ package org.hibernate.models.orm.xml.override; -import org.hibernate.models.orm.internal.ManagedResourcesImpl; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; import org.hibernate.models.orm.spi.AttributeMetadata; +import org.hibernate.models.orm.spi.CategorizedDomainModel; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; -import org.hibernate.models.orm.spi.ManagedResources; -import org.hibernate.models.orm.spi.ProcessResult; -import org.hibernate.models.orm.spi.Processor; import org.hibernate.models.orm.xml.SimpleEntity; -import org.hibernate.models.source.SourceModelTestHelper; -import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.AnnotationUsage; import org.junit.jupiter.api.Test; -import org.jboss.jandex.Index; - import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Id; import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; +import static org.hibernate.models.orm.spi.ManagedResourcesProcessor.processManagedResources; /** * @author Steve Ebersole @@ -40,49 +39,34 @@ void testSimpleCompleteEntity() { managedResourcesBuilder.addXmlMappings( "mappings/override/simple-override.xml" ); final ManagedResources managedResources = managedResourcesBuilder.build(); - final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( - SIMPLE_CLASS_LOADING, - SimpleEntity.class - ); - final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( - jandexIndex, - SIMPLE_CLASS_LOADING - ); - - final ProcessResult processResult = Processor.process( - managedResources, - null, - new Processor.Options() { - @Override - public boolean areGeneratorsGlobal() { - return false; - } - - @Override - public boolean shouldIgnoreUnlistedClasses() { - return false; - } - }, - buildingContext - ); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); - assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); + assertThat( categorizedDomainModel.getEntityHierarchies() ).hasSize( 1 ); - final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); - final EntityTypeMetadata root = hierarchy.getRoot(); - assertThat( root.getClassDetails().getClassName() ).isEqualTo( SimpleEntity.class.getName() ); - assertThat( root.getNumberOfAttributes() ).isEqualTo( 2 ); + final EntityHierarchy hierarchy = categorizedDomainModel.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata root = hierarchy.getRoot(); + assertThat( root.getClassDetails().getClassName() ).isEqualTo( SimpleEntity.class.getName() ); + assertThat( root.getNumberOfAttributes() ).isEqualTo( 2 ); - final AttributeMetadata idAttribute = root.findAttribute( "id" ); - assertThat( idAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); - assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); + final AttributeMetadata idAttribute = root.findAttribute( "id" ); + assertThat( idAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); + assertThat( idAttribute.getMember().getAnnotationUsage( Id.class ) ).isNotNull(); - final AttributeMetadata nameAttribute = root.findAttribute( "name" ); - assertThat( nameAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); - assertThat( nameAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); - final AnnotationUsage nameColumnAnn = nameAttribute.getMember().getAnnotationUsage( Column.class ); - assertThat( nameColumnAnn ).isNotNull(); - assertThat( nameColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "description" ); - assertThat( nameColumnAnn.getAttributeValue( "columnDefinition" ) ).isEqualTo( "nvarchar(512)" ); + final AttributeMetadata nameAttribute = root.findAttribute( "name" ); + assertThat( nameAttribute.getNature() ).isEqualTo( AttributeMetadata.AttributeNature.BASIC ); + assertThat( nameAttribute.getMember().getAnnotationUsage( Basic.class ) ).isNotNull(); + final AnnotationUsage nameColumnAnn = nameAttribute.getMember().getAnnotationUsage( Column.class ); + assertThat( nameColumnAnn ).isNotNull(); + assertThat( nameColumnAnn.getAttributeValue( "name" ) ).isEqualTo( "description" ); + assertThat( nameColumnAnn.getAttributeValue( "columnDefinition" ) ).isEqualTo( "nvarchar(512)" ); + } } } diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractAnnotationDescriptorRegistry.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractAnnotationDescriptorRegistry.java new file mode 100644 index 0000000..5a3c0ee --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractAnnotationDescriptorRegistry.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.internal; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Repeatable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.hibernate.models.ModelsException; +import org.hibernate.models.source.spi.AnnotationDescriptor; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractAnnotationDescriptorRegistry implements AnnotationDescriptorRegistry { + protected final Map, AnnotationDescriptor> descriptorMap; + protected final Map, AnnotationDescriptor> repeatableByContainerMap; + + public AbstractAnnotationDescriptorRegistry() { + this( new ConcurrentHashMap<>(), new ConcurrentHashMap<>() ); + } + + public AbstractAnnotationDescriptorRegistry( + Map, AnnotationDescriptor> descriptorMap, + Map, AnnotationDescriptor> repeatableByContainerMap) { + this.descriptorMap = descriptorMap; + this.repeatableByContainerMap = repeatableByContainerMap; + } + + /** + * Returns the descriptor of the {@linkplain Repeatable repeatable} annotation + * {@linkplain AnnotationDescriptor#getRepeatableContainer contained} by the given + * {@code containerDescriptor}. For example, calling this method with JPA's + * {@code NamedQueries} would return the descriptor for {@code NamedQuery}. + *

+ * It is the logical inverse of {@link AnnotationDescriptor#getRepeatableContainer}. + */ + @Override + public AnnotationDescriptor getContainedRepeatableDescriptor(AnnotationDescriptor containerDescriptor) { + //noinspection unchecked + return (AnnotationDescriptor) repeatableByContainerMap.get( containerDescriptor ); + } + + /** + * @see #getContainedRepeatableDescriptor + */ + @Override + public AnnotationDescriptor getContainedRepeatableDescriptor(Class containerJavaType) { + return getContainedRepeatableDescriptor( getDescriptor( containerJavaType ) ); + } +} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractClassDetailsRegistry.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractClassDetailsRegistry.java new file mode 100644 index 0000000..297e0cf --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AbstractClassDetailsRegistry.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.internal; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.hibernate.models.ModelsException; +import org.hibernate.models.source.UnknownClassException; +import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsBuilder; +import org.hibernate.models.source.spi.ClassDetailsRegistry; +import org.hibernate.models.source.spi.PackageDetails; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractClassDetailsRegistry implements ClassDetailsRegistry { + protected final Map classDetailsMap; + + // subtype per type + protected final Map> subTypeClassDetailsMap; + + // for packages containing a package-info.class file + protected final Map packageDetailsMap; + + + protected AbstractClassDetailsRegistry() { + this( new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>() ); + } + + protected AbstractClassDetailsRegistry( + Map classDetailsMap, + Map> subTypeClassDetailsMap, + Map packageDetailsMap) { + this.classDetailsMap = classDetailsMap; + this.subTypeClassDetailsMap = subTypeClassDetailsMap; + this.packageDetailsMap = packageDetailsMap; + } + + @Override + public List getDirectSubTypes(String superTypeName) { + return subTypeClassDetailsMap.get( superTypeName ); + } + + @Override + public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer consumer) { + final List directSubTypes = getDirectSubTypes( superTypeName ); + if ( directSubTypes == null ) { + return; + } + for ( int i = 0; i < directSubTypes.size(); i++ ) { + consumer.consume( directSubTypes.get( i ) ); + } + } + + @Override + public ClassDetails findClassDetails(String name) { + return classDetailsMap.get( name ); + } + + @Override + public ClassDetails getClassDetails(String name) { + final ClassDetails named = classDetailsMap.get( name ); + if ( named == null ) { + if ( "void".equals( name ) ) { + return null; + } + throw new UnknownClassException( "Unknown managed class - " + name ); + } + return named; + } + + @Override + public void forEachClassDetails(ClassDetailsConsumer consumer) { + for ( Map.Entry entry : classDetailsMap.entrySet() ) { + consumer.consume( entry.getValue() ); + } + } + + @Override + public ClassDetails resolveClassDetails(String name, ClassDetailsBuilder creator) { + assert name != null; + + if ( "void".equals( name ) ) { + return null; + } + + if ( name.endsWith( "package-info" ) ) { + throw new ModelsException( "Resolve " + name + " as a package, not a class" ); + } + + final ClassDetails existing = classDetailsMap.get( name ); + if ( existing != null ) { + return existing; + } + + return createClassDetails( name, creator ); + } + + protected abstract ClassDetails createClassDetails(String name, ClassDetailsBuilder creator); + + @Override public ClassDetails resolveClassDetails( + String name, + ClassDetailsCreator creator) { + assert name != null; + + if ( name.endsWith( "package-info" ) ) { + throw new ModelsException( "Resolve " + name + " as a package, not a class" ); + } + + final ClassDetails existing = classDetailsMap.get( name ); + if ( existing != null ) { + return existing; + } + + return createClassDetails( name, creator ); + } + + protected abstract ClassDetails createClassDetails(String name, ClassDetailsCreator creator); + + @Override + public PackageDetails findPackageDetails(String name) { + return packageDetailsMap.get( name ); + } + + @Override + public PackageDetails getPackageDetails(String name) { + final PackageDetails found = findPackageDetails( name ); + if ( found == null ) { + throw new ModelsException( "Could not locate PackageDetails - " + name ); + } + return found; + } + + @Override + public void forEachPackageDetails(PackageDetailsConsumer consumer) { + for ( Map.Entry entry : packageDetailsMap.entrySet() ) { + consumer.consume( entry.getValue() ); + } + } + + @Override + public PackageDetails resolvePackageDetails(String packageName, PackageDetailsCreator creator) { + final PackageDetails existing = packageDetailsMap.get( packageName ); + if ( existing != null ) { + return existing; + } + + return createPackageDetails( packageName, creator ); + } + + protected abstract PackageDetails createPackageDetails(String packageName, PackageDetailsCreator creator); +} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImmutable.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImmutable.java new file mode 100644 index 0000000..b446c64 --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImmutable.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.internal; + +import java.lang.annotation.Annotation; +import java.util.Map; + +import org.hibernate.models.ModelsException; +import org.hibernate.models.source.spi.AnnotationDescriptor; +import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; + +/** + * @author Steve Ebersole + */ +public class AnnotationDescriptorRegistryImmutable extends AbstractAnnotationDescriptorRegistry { + public AnnotationDescriptorRegistryImmutable( + Map, AnnotationDescriptor> descriptorMap, + Map, AnnotationDescriptor> repeatableByContainerMap) { + super( descriptorMap, repeatableByContainerMap ); + } + + @Override + public AnnotationDescriptor getDescriptor(Class javaType) { + return resolveDescriptor( javaType, null ); + } + + @Override + public AnnotationDescriptor resolveDescriptor( + Class javaType, + DescriptorCreator creator) { + //noinspection unchecked + final AnnotationDescriptor descriptor = (AnnotationDescriptor) descriptorMap.get( javaType ); + if ( descriptor == null ) { + throw new ModelsException( "AnnotationDescriptorRegistry is immutable - " + javaType.getName() ); + } + return descriptor; + } + + @Override + public AnnotationDescriptorRegistry makeImmutableCopy() { + return this; + } +} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImpl.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryStandard.java similarity index 60% rename from hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImpl.java rename to hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryStandard.java index b5fb61b..946f716 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryImpl.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/AnnotationDescriptorRegistryStandard.java @@ -8,24 +8,18 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.hibernate.models.source.internal.jdk.AnnotationDescriptorImpl; import org.hibernate.models.source.spi.AnnotationDescriptor; import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.source.spi.SourceModelBuildingContext; /** * Access to AnnotationDescriptor instances based on a number of look-ups * * @author Steve Ebersole */ -public class AnnotationDescriptorRegistryImpl implements AnnotationDescriptorRegistry { - private final Map, AnnotationDescriptor> descriptorMap = new ConcurrentHashMap<>(); - private final Map, AnnotationDescriptor> repeatableByContainerMap = new ConcurrentHashMap<>(); - - public AnnotationDescriptorRegistryImpl() { +public class AnnotationDescriptorRegistryStandard extends AbstractAnnotationDescriptorRegistry { + public AnnotationDescriptorRegistryStandard() { } public void register(AnnotationDescriptor descriptor) { @@ -72,25 +66,8 @@ private AnnotationDescriptor buildAdHocAnnotationDescr return descriptor; } - /** - * Returns the descriptor of the {@linkplain Repeatable repeatable} annotation - * {@linkplain AnnotationDescriptor#getRepeatableContainer contained} by the given - * {@code containerDescriptor}. For example, calling this method with JPA's - * {@code NamedQueries} would return the descriptor for {@code NamedQuery}. - *

- * It is the logical inverse of {@link AnnotationDescriptor#getRepeatableContainer}. - */ - @Override - public AnnotationDescriptor getContainedRepeatableDescriptor(AnnotationDescriptor containerDescriptor) { - //noinspection unchecked - return (AnnotationDescriptor) repeatableByContainerMap.get( containerDescriptor ); - } - - /** - * @see #getContainedRepeatableDescriptor - */ @Override - public AnnotationDescriptor getContainedRepeatableDescriptor(Class containerJavaType) { - return getContainedRepeatableDescriptor( getDescriptor( containerJavaType ) ); + public AnnotationDescriptorRegistry makeImmutableCopy() { + return new AnnotationDescriptorRegistryImmutable( descriptorMap, repeatableByContainerMap ); } } diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImmutable.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImmutable.java new file mode 100644 index 0000000..694dc1e --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImmutable.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.internal; + +import java.util.List; +import java.util.Map; + +import org.hibernate.models.ModelsException; +import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsBuilder; +import org.hibernate.models.source.spi.ClassDetailsRegistry; +import org.hibernate.models.source.spi.PackageDetails; + +/** + * @author Steve Ebersole + */ +public class ClassDetailsRegistryImmutable extends AbstractClassDetailsRegistry { + public ClassDetailsRegistryImmutable( + Map classDetailsMap, + Map> subTypeClassDetailsMap, + Map packageDetailsMap) { + super( classDetailsMap, subTypeClassDetailsMap, packageDetailsMap ); + } + + @Override + protected ClassDetails createClassDetails(String name, ClassDetailsBuilder creator) { + throw new ModelsException( "ClassDetailsRegistry is immutable" ); + } + + @Override + protected ClassDetails createClassDetails(String name, ClassDetailsCreator creator) { + throw new ModelsException( "ClassDetailsRegistry is immutable" ); + } + + @Override + protected PackageDetails createPackageDetails(String packageName, PackageDetailsCreator creator) { + throw new ModelsException( "ClassDetailsRegistry is immutable" ); + } + + @Override + public void addClassDetails(ClassDetails classDetails) { + throw new ModelsException( "ClassDetailsRegistry is immutable" ); + } + + @Override + public void addClassDetails(String name, ClassDetails classDetails) { + throw new ModelsException( "ClassDetailsRegistry is immutable" ); + } + + @Override + public ClassDetails resolveClassDetails(String name) { + return resolveClassDetails( name, (ClassDetailsCreator) null ); + } + + @Override + public ClassDetailsRegistry makeImmutableCopy() { + return this; + } +} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImpl.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImpl.java deleted file mode 100644 index bbde7be..0000000 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryImpl.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.source.internal; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.hibernate.models.ModelsException; -import org.hibernate.models.source.UnknownClassException; -import org.hibernate.models.source.internal.jandex.JandexBuilders; -import org.hibernate.models.source.internal.jdk.JdkBuilders; -import org.hibernate.models.source.spi.ClassDetails; -import org.hibernate.models.source.spi.ClassDetailsBuilder; -import org.hibernate.models.source.spi.ClassDetailsRegistry; -import org.hibernate.models.source.spi.PackageDetails; -import org.hibernate.models.source.spi.SourceModelBuildingContext; - -/** - * Standard ClassDetailsRegistry implementation. - * - * @author Steve Ebersole - */ -public class ClassDetailsRegistryImpl implements ClassDetailsRegistry { - private final StandardClassDetailsBuilder standardClassDetailsBuilder; - private final SourceModelBuildingContext context; - - private final Map classDetailsMap = new ConcurrentHashMap<>(); - // sub-type ClassDetails per super - private final Map> subTypeClassDetailsMap = new ConcurrentHashMap<>(); - // for packages containing a package-info.class file - private final Map packageDetailsMap = new ConcurrentHashMap<>(); - - public ClassDetailsRegistryImpl(SourceModelBuildingContext context) { - this( JdkBuilders.DEFAULT_BUILDER, context ); - } - - public ClassDetailsRegistryImpl(ClassDetailsBuilder fallbackClassDetailsBuilder, SourceModelBuildingContext context) { - this.context = context; - this.standardClassDetailsBuilder = new StandardClassDetailsBuilder( fallbackClassDetailsBuilder ); - } - - @Override public ClassDetails findClassDetails(String name) { - return classDetailsMap.get( name ); - } - - @Override public ClassDetails getClassDetails(String name) { - final ClassDetails named = classDetailsMap.get( name ); - if ( named == null ) { - if ( "void".equals( name ) ) { - return null; - } - throw new UnknownClassException( "Unknown managed class - " + name ); - } - return named; - } - - @Override public void forEachClassDetails(ClassDetailsConsumer consumer) { - for ( Map.Entry entry : classDetailsMap.entrySet() ) { - consumer.consume( entry.getValue() ); - } - } - - @Override public List getDirectSubTypes(String superTypeName) { - return subTypeClassDetailsMap.get( superTypeName ); - } - - @Override - public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer consumer) { - final List directSubTypes = getDirectSubTypes( superTypeName ); - if ( directSubTypes == null ) { - return; - } - for ( int i = 0; i < directSubTypes.size(); i++ ) { - consumer.consume( directSubTypes.get( i ) ); - } - } - - @Override public void addClassDetails(ClassDetails classDetails) { - addClassDetails( classDetails.getClassName(), classDetails ); - } - - @Override public void addClassDetails(String name, ClassDetails classDetails) { - classDetailsMap.put( name, classDetails ); - - if ( classDetails.getSuperType() != null ) { - List subTypes = subTypeClassDetailsMap.get( classDetails.getSuperType().getName() ); - if ( subTypes == null ) { - subTypes = new ArrayList<>(); - subTypeClassDetailsMap.put( classDetails.getSuperType().getName(), subTypes ); - } - subTypes.add( classDetails ); - } - } - - @Override public ClassDetails resolveClassDetails(String name) { - return resolveClassDetails( name, standardClassDetailsBuilder ); - } - - - @Override - public ClassDetails resolveClassDetails( - String name, - ClassDetailsBuilder creator) { - if ( "void".equals( name ) ) { - return null; - } - - final ClassDetails existing = classDetailsMap.get( name ); - if ( existing != null ) { - return existing; - } - - final ClassDetails created = creator.buildClassDetails( name, context ); - addClassDetails( name, created ); - return created; - } - - @Override public ClassDetails resolveClassDetails( - String name, - ClassDetailsCreator creator) { - final ClassDetails existing = classDetailsMap.get( name ); - if ( existing != null ) { - return existing; - } - - final ClassDetails created = creator.createClassDetails(); - addClassDetails( name, created ); - return created; - } - - @Override - public PackageDetails resolvePackageDetails(String packageName, PackageDetailsCreator creator) { - final PackageDetails existing = packageDetailsMap.get( packageName ); - if ( existing != null ) { - return existing; - } - - final PackageDetails created = creator.createPackageDetails(); - packageDetailsMap.put( packageName, created ); - return created; - } - - @Override - public PackageDetails findPackageDetails(String name) { - return packageDetailsMap.get( name ); - } - - @Override - public PackageDetails getPackageDetails(String name) { - final PackageDetails found = findPackageDetails( name ); - if ( found == null ) { - throw new ModelsException( "Could not locate PackageDetails - " + name ); - } - return found; - } - - @Override - public void forEachPackageDetails(PackageDetailsConsumer consumer) { - for ( Map.Entry entry : packageDetailsMap.entrySet() ) { - consumer.consume( entry.getValue() ); - } - } - - private static class StandardClassDetailsBuilder implements ClassDetailsBuilder { - private final ClassDetailsBuilder fallbackClassDetailsBuilder; - - public StandardClassDetailsBuilder(ClassDetailsBuilder fallbackClassDetailsBuilder) { - this.fallbackClassDetailsBuilder = fallbackClassDetailsBuilder; - } - - @Override - public ClassDetails buildClassDetails(String name, SourceModelBuildingContext buildingContext) { - try { - return JandexBuilders.buildClassDetailsStatic( name, buildingContext ); - } - catch (UnknownClassException e) { - // generally means the class is not in the Jandex index - try the fallback - return fallbackClassDetailsBuilder.buildClassDetails( name, buildingContext ); - } - } - } -} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryStandard.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryStandard.java new file mode 100644 index 0000000..220db7b --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/ClassDetailsRegistryStandard.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.models.ModelsException; +import org.hibernate.models.source.UnknownClassException; +import org.hibernate.models.source.internal.jandex.JandexBuilders; +import org.hibernate.models.source.internal.jdk.JdkBuilders; +import org.hibernate.models.source.spi.ClassDetails; +import org.hibernate.models.source.spi.ClassDetailsBuilder; +import org.hibernate.models.source.spi.ClassDetailsRegistry; +import org.hibernate.models.source.spi.PackageDetails; +import org.hibernate.models.source.spi.SourceModelBuildingContext; + +import org.jboss.jandex.IndexView; + +/** + * Standard ClassDetailsRegistry implementation. + * + * @author Steve Ebersole + */ +public class ClassDetailsRegistryStandard extends AbstractClassDetailsRegistry { + private final StandardClassDetailsBuilder standardClassDetailsBuilder; + private final SourceModelBuildingContext context; + + public ClassDetailsRegistryStandard(SourceModelBuildingContext context) { + this.context = context; + this.standardClassDetailsBuilder = new StandardClassDetailsBuilder( JdkBuilders.DEFAULT_BUILDER, context.getJandexIndex() ); + } + + @Override + public void addClassDetails(ClassDetails classDetails) { + addClassDetails( classDetails.getClassName(), classDetails ); + } + + @Override + public void addClassDetails(String name, ClassDetails classDetails) { + if ( name.endsWith( "package-info" ) ) { + throw new ModelsException( "Register " + name + " as a package, not a class" ); + } + classDetailsMap.put( name, classDetails ); + + if ( classDetails.getSuperType() != null ) { + List subTypes = subTypeClassDetailsMap.get( classDetails.getSuperType().getName() ); + if ( subTypes == null ) { + subTypes = new ArrayList<>(); + subTypeClassDetailsMap.put( classDetails.getSuperType().getName(), subTypes ); + } + subTypes.add( classDetails ); + } + } + + @Override + public ClassDetails resolveClassDetails(String name) { + return resolveClassDetails( name, standardClassDetailsBuilder ); + } + + @Override + protected ClassDetails createClassDetails(String name, ClassDetailsBuilder creator) { + final ClassDetails created = creator.buildClassDetails( name, context ); + addClassDetails( name, created ); + return created; + } + + @Override + protected ClassDetails createClassDetails(String name, ClassDetailsCreator creator) { + final ClassDetails created = creator.createClassDetails(); + addClassDetails( name, created ); + return created; + } + + @Override + protected PackageDetails createPackageDetails(String packageName, PackageDetailsCreator creator) { + final PackageDetails created = creator.createPackageDetails(); + packageDetailsMap.put( packageName, created ); + return created; + } + + private static class StandardClassDetailsBuilder implements ClassDetailsBuilder { + private final boolean tryJandex; + private final ClassDetailsBuilder fallbackClassDetailsBuilder; + + public StandardClassDetailsBuilder(ClassDetailsBuilder fallbackClassDetailsBuilder, IndexView jandexIndex) { + this.fallbackClassDetailsBuilder = fallbackClassDetailsBuilder; + this.tryJandex = jandexIndex != null; + } + + @Override + public ClassDetails buildClassDetails(String name, SourceModelBuildingContext buildingContext) { + if ( tryJandex ) { + try { + return JandexBuilders.buildClassDetailsStatic( name, buildingContext ); + } + catch (UnknownClassException e) { + // generally means the class is not in the Jandex index - try the fallback + } + } + + return fallbackClassDetailsBuilder.buildClassDetails( name, buildingContext ); + } + } + + @Override + public ClassDetailsRegistry makeImmutableCopy() { + return new ClassDetailsRegistryImmutable( classDetailsMap, subTypeClassDetailsMap, packageDetailsMap ); + } +} diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/SourceModelBuildingContextImpl.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/SourceModelBuildingContextImpl.java index 41e0108..7237bfe 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/SourceModelBuildingContextImpl.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/SourceModelBuildingContextImpl.java @@ -29,8 +29,8 @@ public class SourceModelBuildingContextImpl implements SourceModelBuildingContex private final ClassLoading classLoadingAccess; private final IndexView jandexIndex; - private final AnnotationDescriptorRegistryImpl descriptorRegistry; - private final ClassDetailsRegistryImpl classDetailsRegistry; + private final AnnotationDescriptorRegistryStandard descriptorRegistry; + private final ClassDetailsRegistryStandard classDetailsRegistry; public SourceModelBuildingContextImpl(ClassLoading classLoadingAccess, IndexView jandexIndex) { this( classLoadingAccess, jandexIndex, null ); @@ -43,8 +43,8 @@ public SourceModelBuildingContextImpl( this.classLoadingAccess = classLoadingAccess; this.jandexIndex = jandexIndex; - this.descriptorRegistry = new AnnotationDescriptorRegistryImpl(); - this.classDetailsRegistry = new ClassDetailsRegistryImpl( this ); + this.descriptorRegistry = new AnnotationDescriptorRegistryStandard(); + this.classDetailsRegistry = new ClassDetailsRegistryStandard( this ); primeRegistries( registryPrimer ); } diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkBuilders.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkBuilders.java index 910644f..d5a5925 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkBuilders.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkBuilders.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.List; -import org.hibernate.models.source.internal.AnnotationDescriptorRegistryImpl; +import org.hibernate.models.source.internal.AnnotationDescriptorRegistryStandard; import org.hibernate.models.source.internal.TypeDescriptors; import org.hibernate.models.source.spi.AnnotationDescriptor; import org.hibernate.models.source.spi.AnnotationDescriptorRegistry; @@ -39,6 +39,27 @@ public JdkClassDetails buildClassDetails(String name, SourceModelBuildingContext } public static JdkClassDetails buildClassDetailsStatic(String name, SourceModelBuildingContext buildingContext) { + if ( byte.class.getName().equals( name ) ) { + return buildClassDetailsStatic( byte.class, buildingContext ); + } + if ( boolean.class.getName().equals( name ) ) { + return buildClassDetailsStatic( boolean.class, buildingContext ); + } + if ( short.class.getName().equals( name ) ) { + return buildClassDetailsStatic( short.class, buildingContext ); + } + if ( int.class.getName().equals( name ) ) { + return buildClassDetailsStatic( int.class, buildingContext ); + } + if ( long.class.getName().equals( name ) ) { + return buildClassDetailsStatic( long.class, buildingContext ); + } + if ( float.class.getName().equals( name ) ) { + return buildClassDetailsStatic( float.class, buildingContext ); + } + if ( double.class.getName().equals( name ) ) { + return buildClassDetailsStatic( double.class, buildingContext ); + } return buildClassDetailsStatic( buildingContext.getClassLoading().classForName( name ), buildingContext @@ -127,7 +148,7 @@ public static AnnotationDescriptor< } //noinspection unchecked final AnnotationDescriptor containerDescriptor = (AnnotationDescriptor) descriptorRegistry.getDescriptor( repeatableAnnotation.value() ); - ( (AnnotationDescriptorRegistryImpl) descriptorRegistry ).register( containerDescriptor ); + ( (AnnotationDescriptorRegistryStandard) descriptorRegistry ).register( containerDescriptor ); return containerDescriptor; } diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkClassDetails.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkClassDetails.java index 2a8adbf..0bd16c0 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkClassDetails.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkClassDetails.java @@ -137,7 +137,7 @@ public boolean isImplementor(ClassDetails checkType) { @Override public List getFields() { if ( fields == null ) { - final Field[] reflectionFields = managedClass.getFields(); + final Field[] reflectionFields = managedClass.getDeclaredFields(); this.fields = CollectionHelper.arrayList( reflectionFields.length ); for ( int i = 0; i < reflectionFields.length; i++ ) { final Field reflectionField = reflectionFields[i]; @@ -155,7 +155,7 @@ public void addField(FieldDetails fieldDetails) { @Override public List getMethods() { if ( methods == null ) { - final Method[] reflectionMethods = managedClass.getMethods(); + final Method[] reflectionMethods = managedClass.getDeclaredMethods(); this.methods = CollectionHelper.arrayList( reflectionMethods.length ); for ( int i = 0; i < reflectionMethods.length; i++ ) { this.methods.add( buildMethodDetails( reflectionMethods[i], getBuildingContext() ) ); diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkMethodDetails.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkMethodDetails.java index fea375f..1396953 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkMethodDetails.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/jdk/JdkMethodDetails.java @@ -45,7 +45,7 @@ public JdkMethodDetails( returnType = null; } else { - returnType = classDetailsRegistry.getClassDetails( method.getReturnType().getName() ); + returnType = classDetailsRegistry.resolveClassDetails( method.getReturnType().getName() ); } this.argumentTypes = new ArrayList<>( method.getParameterCount() ); diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/AnnotationDescriptorRegistry.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/AnnotationDescriptorRegistry.java index 7b57191..473653e 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/AnnotationDescriptorRegistry.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/AnnotationDescriptorRegistry.java @@ -34,6 +34,8 @@ public interface AnnotationDescriptorRegistry { */ AnnotationDescriptor getContainedRepeatableDescriptor(Class javaType); + AnnotationDescriptorRegistry makeImmutableCopy(); + @FunctionalInterface interface DescriptorCreator { AnnotationDescriptor createDescriptor(Class annotationType); diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/ClassDetailsRegistry.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/ClassDetailsRegistry.java index 56ae506..9889828 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/ClassDetailsRegistry.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/ClassDetailsRegistry.java @@ -120,4 +120,6 @@ interface ClassDetailsConsumer { interface PackageDetailsCreator { PackageDetails createPackageDetails(); } + + ClassDetailsRegistry makeImmutableCopy(); } diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelBuildingContext.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelBuildingContext.java index f490fe1..aa0f50b 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelBuildingContext.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelBuildingContext.java @@ -18,17 +18,7 @@ * * @author Steve Ebersole */ -public interface SourceModelBuildingContext extends SharedNamedAnnotationScope { - /** - * The registry of annotation descriptors - */ - AnnotationDescriptorRegistry getAnnotationDescriptorRegistry(); - - /** - * Registry of managed-classes - */ - ClassDetailsRegistry getClassDetailsRegistry(); - +public interface SourceModelBuildingContext extends SourceModelContext, SharedNamedAnnotationScope { /** * If model processing code needs to load things from the class-loader, they should * really use this access. At this level, accessing the class-loader at all diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelContext.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelContext.java new file mode 100644 index 0000000..0813e09 --- /dev/null +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/spi/SourceModelContext.java @@ -0,0 +1,22 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.source.spi; + +/** + * @author Steve Ebersole + */ +public interface SourceModelContext { + /** + * The registry of annotation descriptors + */ + AnnotationDescriptorRegistry getAnnotationDescriptorRegistry(); + + /** + * Registry of managed-classes + */ + ClassDetailsRegistry getClassDetailsRegistry(); +} diff --git a/hibernate-models-testing/src/main/java/org/hibernate/models/source/SourceModelTestHelper.java b/hibernate-models-testing/src/main/java/org/hibernate/models/source/SourceModelTestHelper.java index 327b048..3095c60 100644 --- a/hibernate-models-testing/src/main/java/org/hibernate/models/source/SourceModelTestHelper.java +++ b/hibernate-models-testing/src/main/java/org/hibernate/models/source/SourceModelTestHelper.java @@ -12,7 +12,7 @@ import org.hibernate.models.orm.internal.OrmAnnotationHelper; import org.hibernate.models.orm.HibernateAnnotations; import org.hibernate.models.orm.JpaAnnotations; -import org.hibernate.models.source.internal.AnnotationDescriptorRegistryImpl; +import org.hibernate.models.source.internal.AnnotationDescriptorRegistryStandard; import org.hibernate.models.source.internal.BaseLineJavaTypes; import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.internal.jandex.JandexBuilders; @@ -58,7 +58,7 @@ public static SourceModelBuildingContextImpl createBuildingContext( } ); final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - final AnnotationDescriptorRegistryImpl annotationDescriptorRegistry = (AnnotationDescriptorRegistryImpl) buildingContext.getAnnotationDescriptorRegistry(); + final AnnotationDescriptorRegistryStandard annotationDescriptorRegistry = (AnnotationDescriptorRegistryStandard) buildingContext.getAnnotationDescriptorRegistry(); for ( ClassInfo knownClass : jandexIndex.getKnownClasses() ) { // if ( knownClass.simpleName().endsWith( "package-info" ) ) { diff --git a/hibernate-orm/hibernate-orm.gradle b/hibernate-orm/hibernate-orm.gradle index 8acc074..27d6df2 100644 --- a/hibernate-orm/hibernate-orm.gradle +++ b/hibernate-orm/hibernate-orm.gradle @@ -8,9 +8,12 @@ dependencies { api platform( libs.hibernatePlatform ) api libs.hibernateCore + implementation project( ":hibernate-models-source" ) + implementation project( ":hibernate-models-common" ) implementation jakartaLibs.jaxbApi implementation jakartaLibs.jaxb implementation jakartaLibs.inject + implementation libs.jandex implementation libs.logging xjc jakartaLibs.xjc