HHH-8956 - TLC for annotation pre-processor

This commit is contained in:
Steve Ebersole 2014-02-12 08:53:00 -06:00
parent bd17dab1b0
commit 2807578a7c
19 changed files with 407 additions and 198 deletions

View File

@ -23,19 +23,9 @@
*/
package org.hibernate.metamodel;
import java.util.List;
import java.util.Map;
import javax.persistence.SharedCacheMode;
import org.jboss.jandex.IndexView;
import org.xml.sax.EntityResolver;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.CacheRegionDefinition;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.spi.FilterDefinition;
@ -47,39 +37,12 @@ import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.SecondaryTable;
import org.hibernate.metamodel.spi.binding.TypeDefinition;
import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.type.BasicType;
/**
* @author Steve Ebersole
*/
public interface Metadata {
/**
* Exposes the options used to produce a {@link Metadata} instance.
*/
public static interface Options extends Database.Defaults {
StandardServiceRegistry getServiceRegistry();
MetadataSourceProcessingOrder getMetadataSourceProcessingOrder();
NamingStrategy getNamingStrategy();
EntityResolver getEntityResolver();
SharedCacheMode getSharedCacheMode();
AccessType getDefaultAccessType();
boolean useNewIdentifierGenerators();
MultiTenancyStrategy getMultiTenancyStrategy();
IndexView getJandexView();
List<BasicType> getBasicTypeRegistrations();
List<CacheRegionDefinition> getCacheRegionDefinitions();
}
/**
* Retrieve the options used to build this {@link Metadata} instance.
*
* @return The options.
*/
Options getOptions();
/**
* Get the builder for {@link SessionFactory} instances based on this metamodel,
*

View File

@ -165,7 +165,22 @@ public interface MetadataBuilder {
*
* @param cacheRegionDefinition The cache region definition to apply
*/
public void with(CacheRegionDefinition cacheRegionDefinition);
public MetadataBuilder with(CacheRegionDefinition cacheRegionDefinition);
/**
* Apply a ClassLoader for use while building the Metadata.
* <p/>
* Ideally we should avoid accessing ClassLoaders when perform 1st phase of bootstrap. This
* is a ClassLoader that can be used in cases when we have to. IN EE managed environments, this
* is the ClassLoader mandated by
* {@link javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader()}. This ClassLoader
* is thrown away by the container afterwards. The idea being that the Class can still be enhanced
* in the application ClassLoader. In other environments, pass a ClassLoader that performs the
* same function if desired.
*
* @param tempClassLoader ClassLoader for use during building the Metadata
*/
public MetadataBuilder with(ClassLoader tempClassLoader);
/**
* Actually build the metamodel

View File

@ -726,7 +726,7 @@ public class Binder implements HelperContext {
// if (1) the strategy is discriminator based and (2) the entity is not shared, we need to either (a) extract
// the user supplied tenant discriminator value mapping or (b) generate an implicit one
final boolean needsTenantIdentifierValueMapping =
MultiTenancyStrategy.DISCRIMINATOR == metadata.getOptions().getMultiTenancyStrategy()
MultiTenancyStrategy.DISCRIMINATOR == bindingContext().getBuildingOptions().getMultiTenancyStrategy()
&& !multiTenancySource.isShared();
if ( needsTenantIdentifierValueMapping ) {

View File

@ -52,6 +52,7 @@ import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.spi.MetadataSourcesContributor;
import org.hibernate.metamodel.spi.TypeContributions;
import org.hibernate.metamodel.spi.TypeContributor;
import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BasicType;
import org.hibernate.type.CompositeCustomType;
@ -68,7 +69,7 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
private static final Logger log = Logger.getLogger( MetadataBuilderImpl.class );
private final MetadataSources sources;
private final OptionsImpl options;
private final Options options;
public MetadataBuilderImpl(MetadataSources sources) {
this(
@ -110,7 +111,7 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
.loadJavaServices( MetadataSourcesContributor.class ) ) {
contributor.contribute( sources, null );
}
this.options = new OptionsImpl( serviceRegistry );
this.options = new Options( serviceRegistry );
}
@Override
@ -195,41 +196,93 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
}
@Override
public void with(CacheRegionDefinition cacheRegionDefinition) {
public MetadataBuilder with(CacheRegionDefinition cacheRegionDefinition) {
if ( options.cacheRegionDefinitions == null ) {
options.cacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
}
options.cacheRegionDefinitions.add( cacheRegionDefinition );
return this;
}
@Override
public MetadataBuilder with(ClassLoader tempClassLoader) {
options.tempClassLoader = tempClassLoader;
return this;
}
@Override
public Metadata build() {
return new MetadataImpl( sources, options );
return MetadataImpl.build( sources, options );
}
public static class OptionsImpl implements Metadata.Options {
private final StandardServiceRegistry serviceRegistry;
private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST;
private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE;
// todo : entity-resolver maybe needed for ServiceRegistry building also
// maybe move there and default to looking up that value somehow?
private EntityResolver entityResolver = EJB3DTDEntityResolver.INSTANCE;
private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE;
private AccessType defaultCacheAccessType;
private boolean useNewIdentifierGenerators;
private boolean globallyQuotedIdentifiers;
/**
* Implementation of the Database.Defaults contract
*/
public static class DatabaseDefaults implements Database.Defaults {
private boolean globallyQuotedIdentifiers;
private String defaultSchemaName;
private String defaultCatalogName;
private MultiTenancyStrategy multiTenancyStrategy;
private IndexView jandexView;
public DatabaseDefaults(ConfigurationService configurationService) {
defaultSchemaName = configurationService.getSetting(
AvailableSettings.DEFAULT_SCHEMA,
StandardConverters.STRING,
null
);
defaultCatalogName = configurationService.getSetting(
AvailableSettings.DEFAULT_CATALOG,
StandardConverters.STRING,
null
);
globallyQuotedIdentifiers = configurationService.getSetting(
AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS,
StandardConverters.BOOLEAN,
false
);
}
@Override
public String getDefaultSchemaName() {
return defaultSchemaName;
}
@Override
public String getDefaultCatalogName() {
return defaultCatalogName;
}
@Override
public boolean isGloballyQuotedIdentifiers() {
return globallyQuotedIdentifiers;
}
}
public static class Options implements org.hibernate.metamodel.spi.MetadataBuildingOptions {
private final StandardServiceRegistry serviceRegistry;
private final DatabaseDefaults databaseDefaults;
private List<BasicType> basicTypeRegistrations = new ArrayList<BasicType>();
private IndexView jandexView;
private ClassLoader tempClassLoader;
private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE;
private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE;
private AccessType defaultCacheAccessType;
private boolean useNewIdentifierGenerators;
private MultiTenancyStrategy multiTenancyStrategy;
private List<CacheRegionDefinition> cacheRegionDefinitions;
public OptionsImpl(StandardServiceRegistry serviceRegistry) {
// todo : go away
private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST;
private EntityResolver entityResolver = EJB3DTDEntityResolver.INSTANCE;
public Options(StandardServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
this.databaseDefaults = new DatabaseDefaults( configService );
// cache access type
defaultCacheAccessType = configService.getSetting(
@ -248,24 +301,6 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
false
);
defaultSchemaName = configService.getSetting(
AvailableSettings.DEFAULT_SCHEMA,
StandardConverters.STRING,
null
);
defaultCatalogName = configService.getSetting(
AvailableSettings.DEFAULT_CATALOG,
StandardConverters.STRING,
null
);
globallyQuotedIdentifiers = configService.getSetting(
AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS,
StandardConverters.BOOLEAN,
false
);
multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() );
}
@ -275,58 +310,8 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
}
@Override
public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder() {
return metadataSourceProcessingOrder;
}
@Override
public NamingStrategy getNamingStrategy() {
return namingStrategy;
}
@Override
public EntityResolver getEntityResolver() {
return entityResolver;
}
@Override
public AccessType getDefaultAccessType() {
return defaultCacheAccessType;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return sharedCacheMode;
}
@Override
public boolean useNewIdentifierGenerators() {
return useNewIdentifierGenerators;
}
@Override
public boolean isGloballyQuotedIdentifiers() {
return globallyQuotedIdentifiers;
}
@Override
public String getDefaultSchemaName() {
return defaultSchemaName;
}
@Override
public String getDefaultCatalogName() {
return defaultCatalogName;
}
@Override
public MultiTenancyStrategy getMultiTenancyStrategy() {
return multiTenancyStrategy;
}
@Override
public IndexView getJandexView() {
return jandexView;
public DatabaseDefaults getDatabaseDefaults() {
return databaseDefaults;
}
@Override
@ -334,9 +319,55 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
return basicTypeRegistrations;
}
@Override
public IndexView getJandexView() {
return jandexView;
}
@Override
public ClassLoader getTempClassLoader() {
return tempClassLoader;
}
@Override
public NamingStrategy getNamingStrategy() {
return namingStrategy;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return sharedCacheMode;
}
@Override
public AccessType getDefaultCacheAccessType() {
return defaultCacheAccessType;
}
@Override
public boolean isUseNewIdentifierGenerators() {
return useNewIdentifierGenerators;
}
@Override
public MultiTenancyStrategy getMultiTenancyStrategy() {
return multiTenancyStrategy;
}
@Override
public List<CacheRegionDefinition> getCacheRegionDefinitions() {
return cacheRegionDefinitions;
}
@Override
public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder() {
return metadataSourceProcessingOrder;
}
@Override
public EntityResolver getEntityResolver() {
return entityResolver;
}
}
}

View File

@ -67,6 +67,7 @@ import org.hibernate.metamodel.internal.source.hbm.HbmMetadataSourceProcessorImp
import org.hibernate.metamodel.source.internal.jandex.Unifier;
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings;
import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer;
import org.hibernate.metamodel.spi.MetadataBuildingOptions;
import org.hibernate.metamodel.spi.MetadataContributor;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.MetadataSourceProcessor;
@ -126,7 +127,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
);
private final ServiceRegistry serviceRegistry;
private final Options options;
private final MetadataBuildingOptions options;
private final ClassLoaderService classLoaderService;
// private final transient ValueHolder<PersisterClassResolver> persisterClassResolverService;
@ -156,12 +157,15 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
private boolean globallyQuotedIdentifiers = false;
public MetadataImpl(MetadataSources metadataSources, Options options) {
public MetadataImpl(MetadataSources metadataSources, MetadataBuildingOptions options) {
this.serviceRegistry = options.getServiceRegistry();
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
this.options = options;
this.identifierGeneratorFactory = serviceRegistry.getService( MutableIdentifierGeneratorFactory.class );
this.database = new Database( options, serviceRegistry.getService( JdbcServices.class ).getJdbcEnvironment() );
this.database = new Database(
options.getDatabaseDefaults(),
serviceRegistry.getService( JdbcServices.class ).getJdbcEnvironment()
);
this.mappingDefaults = new MappingDefaultsImpl();
this.nameNormalizer = new ObjectNameNormalizer() {
@ -691,11 +695,6 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
// return persisterClassResolverService.getValue();
// }
@Override
public Options getOptions() {
return options;
}
@Override
public ServiceRegistry getServiceRegistry() {
return serviceRegistry;
@ -881,7 +880,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
@Override
public SessionFactoryBuilder getSessionFactoryBuilder() {
return new SessionFactoryBuilderImpl( this );
return new SessionFactoryBuilderImpl( this, options.getServiceRegistry() );
}
@Override
@ -896,7 +895,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
@Override
public boolean isGloballyQuotedIdentifiers() {
return globallyQuotedIdentifiers || getOptions().isGloballyQuotedIdentifiers();
return globallyQuotedIdentifiers || options.getDatabaseDefaults().isGloballyQuotedIdentifiers();
}
public void setGloballyQuotedIdentifiers(boolean globallyQuotedIdentifiers){
@ -908,6 +907,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return mappingDefaults;
}
@Override
public MetadataBuildingOptions getBuildingOptions() {
return options;
}
private final MetaAttributeContext globalMetaAttributeContext = new MetaAttributeContext();
@Override
@ -965,6 +969,10 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
}
public static MetadataImpl build(MetadataSources sources, MetadataBuildingOptions options) {
return new MetadataImpl( sources, options );
}
private class MappingDefaultsImpl implements MappingDefaults {
@Override
@ -974,12 +982,12 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
@Override
public String getSchemaName() {
return options.getDefaultSchemaName();
return options.getDatabaseDefaults().getDefaultSchemaName();
}
@Override
public String getCatalogName() {
return options.getDefaultCatalogName();
return options.getDatabaseDefaults().getDefaultCatalogName();
}
@Override
@ -1014,7 +1022,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
@Override
public AccessType getCacheAccessType() {
return options.getDefaultAccessType();
return options.getDefaultCacheAccessType();
}
}
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.metamodel.internal;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -35,7 +34,6 @@ import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver;
import org.hibernate.Interceptor;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.registry.StandardServiceRegistry;
@ -51,7 +49,6 @@ import org.hibernate.internal.StandardEntityNotFoundDelegate;
import org.hibernate.metamodel.SessionFactoryBuilder;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.spi.JaccPermissionDeclarations;
import org.hibernate.tuple.entity.EntityTuplizer;
/**
@ -62,9 +59,9 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilder {
private final MetadataImplementor metadata;
private final SessionFactoryOptionsImpl options;
SessionFactoryBuilderImpl(MetadataImplementor metadata) {
SessionFactoryBuilderImpl(MetadataImplementor metadata, StandardServiceRegistry serviceRegistry) {
this.metadata = metadata;
options = new SessionFactoryOptionsImpl( metadata.getOptions().getServiceRegistry() );
options = new SessionFactoryOptionsImpl( serviceRegistry );
}
@Override

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.internal.source.annotations;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.spi.MetadataBuildingOptions;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.domain.JavaClassReference;
@ -109,6 +110,11 @@ public class AnnotationBindingContextImpl implements AnnotationBindingContext {
return metadata;
}
@Override
public MetadataBuildingOptions getBuildingOptions() {
return metadata.getBuildingOptions();
}
@Override
public <T> Class<T> locateClassByName(String name) {
return classLoaderService.classForName( name );

View File

@ -59,7 +59,7 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity
switch ( idType ) {
case SIMPLE: {
MappedAttribute attribute = getEntityClass().getIdAttributes().values().iterator().next();
return new SimpleIdentifierSourceImpl( this, (BasicAttribute) attribute);
return new SimpleIdentifierSourceImpl( this, (BasicAttribute) attribute );
}
case COMPOSED: {
return new NonAggregatedCompositeIdentifierSourceImpl( this );

View File

@ -338,7 +338,7 @@ public class BasicAttribute extends MappedAttribute {
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
genType,
getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators()
getContext().getBuildingOptions().isUseNewIdentifierGenerators()
);
generator = new IdentifierGeneratorDefinition( null, strategy, null );
}

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.internal.source.annotations.entity;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.spi.MetadataBuildingOptions;
import org.hibernate.metamodel.spi.domain.JavaClassReference;
import org.hibernate.xml.spi.Origin;
import org.hibernate.xml.spi.SourceType;
@ -85,6 +86,11 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind
return contextDelegate.getMappingDefaults();
}
@Override
public MetadataBuildingOptions getBuildingOptions() {
return contextDelegate.getBuildingOptions();
}
@Override
public MetadataImplementor getMetadataImplementor() {
return contextDelegate.getMetadataImplementor();

View File

@ -497,7 +497,7 @@ public class EntityClass extends ConfiguredClass {
);
final boolean doCaching;
switch ( getLocalBindingContext().getMetadataImplementor().getOptions().getSharedCacheMode() ) {
switch ( getLocalBindingContext().getBuildingOptions().getSharedCacheMode() ) {
case ALL: {
doCaching = true;
break;

View File

@ -151,7 +151,7 @@ public class IdGeneratorProcessor {
final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class );
final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService );
final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
final boolean useNewIdentifierGenerators = bindingContext.getBuildingOptions().isUseNewIdentifierGenerators();
final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.SEQUENCE,
useNewIdentifierGenerators
@ -196,7 +196,7 @@ public class IdGeneratorProcessor {
final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class );
final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService );
final boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators();
final boolean useNewIdentifierGenerators = bindingContext.getBuildingOptions().isUseNewIdentifierGenerators();
final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
GenerationType.TABLE,
useNewIdentifierGenerators

View File

@ -58,16 +58,21 @@ import org.hibernate.metamodel.spi.source.EntitySource;
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
/**
* Given a (jandex) annotation index build processes all classes with JPA relevant annotations and pre-orders
* Given a (jandex) annotation index, processes all classes with JPA relevant annotations and pre-orders
* JPA entities respectively their inheritance hierarchy.
*
* @author Hardy Ferentschik
* @author Strong Liu
* @author Steve Ebersole
*/
public class EntityHierarchyBuilder {
private static final Logger LOG = Logger.getLogger(
EntityHierarchyBuilder.class);
private static final Logger LOG = Logger.getLogger( EntityHierarchyBuilder.class );
private final AnnotationBindingContext bindingContext;
private final Set<EntityHierarchy> hierarchies = new HashSet<EntityHierarchy>();
private final Map<DotName,DotName> processedEntities = new HashMap<DotName, DotName>();
private final Map<DotName, List<ClassInfo>> classToDirectSubclassMap = new HashMap<DotName, List<ClassInfo>>();
/**
* Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound
@ -78,10 +83,28 @@ public class EntityHierarchyBuilder {
* @return a set of {@code EntityHierarchy} instances.
*/
public static Set<EntityHierarchy> createEntityHierarchies(AnnotationBindingContext bindingContext) {
Set<EntityHierarchy> hierarchies = new HashSet<EntityHierarchy>();
Map<DotName,DotName> processedEntities = new HashMap<DotName, DotName>( );
Map<DotName, List<ClassInfo>> classToDirectSubClassMap = new HashMap<DotName, List<ClassInfo>>();
IndexView index = bindingContext.getIndex();
return new EntityHierarchyBuilder( bindingContext ).process();
}
/**
* Constructs a EntityHierarchyBuilder. While all calls flow into this class statically via
* {@link #createEntityHierarchies}, internally each call to that method creates an instance
* used to hold instance state representing that parse.
*
* @param bindingContext Access to needed services and information
*/
private EntityHierarchyBuilder(AnnotationBindingContext bindingContext) {
this.bindingContext = bindingContext;
}
/**
* Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound
* to the metamodel.
*
* @return a set of {@code EntityHierarchy} instances.
*/
public Set<EntityHierarchy> process() {
final IndexView index = bindingContext.getIndex();
for ( ClassInfo classInfo : index.getKnownClasses() ) {
if ( processedEntities.containsKey( classInfo.name() ) ) {
continue;
@ -91,22 +114,15 @@ public class EntityHierarchyBuilder {
}
ClassInfo rootClassInfo = findRootEntityClassInfo( index, classInfo, bindingContext );
ClassInfo rootClassInfo = findRootEntityClassInfo( classInfo );
List<ClassInfo> rootClassWithAllSubclasses = new ArrayList<ClassInfo>();
// collect the current root entity and all its subclasses
processHierarchy(
bindingContext,
rootClassInfo,
rootClassWithAllSubclasses,
processedEntities,
classToDirectSubClassMap
);
processHierarchy( rootClassInfo, rootClassWithAllSubclasses );
boolean hasSubclasses = rootClassWithAllSubclasses.size() > 1;
// using the root entity, resolve generic parameters in the whole class hierarchy
final Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers = resolveGenerics(
rootClassInfo.toString(),
bindingContext
rootClassInfo.toString()
);
List<ClassInfo> mappedSuperclasses = findMappedSuperclasses( index, rootClassInfo );
@ -133,8 +149,6 @@ public class EntityHierarchyBuilder {
RootEntitySourceImpl rootSource = new RootEntitySourceImpl( rootEntityClass );
addSubclassEntitySources(
bindingContext,
classToDirectSubClassMap,
resolvedTypeWithMembers,
defaultAccessType,
hierarchyInheritanceType,
@ -147,20 +161,18 @@ public class EntityHierarchyBuilder {
return hierarchies;
}
private static void addSubclassEntitySources(
AnnotationBindingContext bindingContext,
Map<DotName, List<ClassInfo>> classToDirectSubClassMap,
private void addSubclassEntitySources(
Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers,
AccessType defaultAccessType,
InheritanceType hierarchyInheritanceType,
EntityClass entityClass,
EntitySource entitySource) {
List<ClassInfo> subClassInfoList = classToDirectSubClassMap.get( DotName.createSimple( entitySource.getClassName() ) );
List<ClassInfo> subClassInfoList = classToDirectSubclassMap.get( DotName.createSimple( entitySource.getClassName() ) );
if ( subClassInfoList == null ) {
return;
}
for ( ClassInfo subClassInfo : subClassInfoList ) {
resolvedTypeWithMembers.putAll( resolveGenerics( subClassInfo.name().toString(), bindingContext ) );
resolvedTypeWithMembers.putAll( resolveGenerics( subClassInfo.name().toString() ) );
ResolvedTypeWithMembers typeWithMembers = resolvedTypeWithMembers.get( subClassInfo.toString() );
if ( typeWithMembers == null ) {
throw new AssertionFailure( "Missing generic information for " + subClassInfo.toString() );
@ -178,8 +190,6 @@ public class EntityHierarchyBuilder {
: new SubclassEntitySourceImpl( subclassEntityClass, entitySource );
entitySource.add( subclassEntitySource );
addSubclassEntitySources(
bindingContext,
classToDirectSubClassMap,
resolvedTypeWithMembers,
defaultAccessType,
hierarchyInheritanceType,
@ -193,19 +203,18 @@ public class EntityHierarchyBuilder {
* Finds the root entity starting at the entity given by {@code info}. The root entity is not the highest superclass
* in a java type sense, but the highest superclass which is also an entity (annotated w/ {@code @Entity}.
*
* @param index the annotation repository
* @param info the class info representing an entity
*
* @return Finds the root entity starting at the entity given by {@code info}
*/
private static ClassInfo findRootEntityClassInfo(IndexView index, ClassInfo info, AnnotationBindingContext bindingContext) {
private ClassInfo findRootEntityClassInfo(ClassInfo info) {
ClassInfo rootEntity = info;
DotName superName = info.superName();
ClassInfo tmpInfo;
// walk up the hierarchy until java.lang.Object
while ( !JandexHelper.OBJECT.equals( superName ) ) {
tmpInfo = index.getClassByName( superName );
tmpInfo = bindingContext.getIndex().getClassByName( superName );
if ( tmpInfo == null && superName != null ) {
Class clazz = bindingContext.locateClassByName( superName.toString() );
if ( clazz != null ) {
@ -250,17 +259,12 @@ public class EntityHierarchyBuilder {
* <li>Building up a map of class to direct subclass list</li>
* </ul>
*
* @param bindingContext the binding context
* @param classInfo the current class info
* @param rootClassWithAllSubclasses used to collect all classes in the hierarchy starting at {@code classInfo}
* @param processedEntities Used to keep track of all processed entities
* @param classToDirectSubclassMap Create a map of class to direct subclass
*/
private static void processHierarchy(AnnotationBindingContext bindingContext,
ClassInfo classInfo,
List<ClassInfo> rootClassWithAllSubclasses,
Map<DotName,DotName> processedEntities,
Map<DotName, List<ClassInfo>> classToDirectSubclassMap) {
private void processHierarchy(
ClassInfo classInfo,
List<ClassInfo> rootClassWithAllSubclasses) {
processedEntities.put( classInfo.name(), classInfo.name() );
rootClassWithAllSubclasses.add( classInfo );
Collection<ClassInfo> subClasses = bindingContext.getIndex().getKnownDirectSubclasses( classInfo.name() );
@ -271,13 +275,7 @@ public class EntityHierarchyBuilder {
continue;
}
addSubClassToSubclassMap( classInfo.name(), subClassInfo, classToDirectSubclassMap );
processHierarchy(
bindingContext,
subClassInfo,
rootClassWithAllSubclasses,
processedEntities,
classToDirectSubclassMap
);
processHierarchy( subClassInfo, rootClassWithAllSubclasses );
}
}
@ -477,7 +475,7 @@ public class EntityHierarchyBuilder {
* TODO this is incorrect, we should do it from bottom to top, not inverse, since the actual type info should be dedined in the sub class.
* we need this info to resolve super class type.
*/
private static Map<String, ResolvedTypeWithMembers> resolveGenerics(String className, AnnotationBindingContext bindingContext) {
private Map<String, ResolvedTypeWithMembers> resolveGenerics(String className) {
final Map<String, ResolvedTypeWithMembers> resolvedTypes = new HashMap<String, ResolvedTypeWithMembers>();
final Class<?> clazz = bindingContext.locateClassByName( className );
ResolvedType resolvedType = bindingContext.getTypeResolver().resolve( clazz );

View File

@ -27,6 +27,7 @@ import java.util.List;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.spi.MetadataBuildingOptions;
import org.hibernate.metamodel.spi.domain.JavaClassReference;
import org.hibernate.xml.spi.BindResult;
import org.hibernate.xml.spi.Origin;
@ -118,6 +119,11 @@ public class MappingDocument {
return localMappingDefaults;
}
@Override
public MetadataBuildingOptions getBuildingOptions() {
return metadata.getBuildingOptions();
}
@Override
public MetadataImplementor getMetadataImplementor() {
return metadata;

View File

@ -0,0 +1,142 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.spi;
import java.util.List;
import javax.persistence.SharedCacheMode;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.CacheRegionDefinition;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.MetadataSourceProcessingOrder;
import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.type.BasicType;
import org.jboss.jandex.IndexView;
import org.xml.sax.EntityResolver;
/**
* Describes the options used while building the Metadata object (during
* {@link org.hibernate.metamodel.MetadataBuilder#build()} processing).
*
* @author Steve Ebersole
*/
public interface MetadataBuildingOptions {
/**
* Access to the service registry.
*
* @return The service registry
*/
StandardServiceRegistry getServiceRegistry();
/**
* Access to the database defaults.
*
* @return The database defaults
*/
Database.Defaults getDatabaseDefaults();
/**
* Access the list of BasicType registrations. These are the BasicTypes explicitly
* registered via calls to:<ul>
* <li>{@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.type.BasicType)}</li>
* <li>{@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.usertype.UserType, java.lang.String[])}</li>
* <li>{@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.usertype.CompositeUserType, java.lang.String[])}</li>
* </ul>
*
* @return The BasicType registrations
*/
List<BasicType> getBasicTypeRegistrations();
/**
* Access to the Jandex index passed by call to
* {@link org.hibernate.metamodel.MetadataBuilder#with(org.jboss.jandex.IndexView)}, if any.
*
* @return The Jandex index
*/
IndexView getJandexView();
/**
* Access the temporary ClassLoader passed to us as defined by
* {@link javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader()}, if any.
*
* @return The tempo ClassLoader
*/
ClassLoader getTempClassLoader();
/**
* Access to the NamingStrategy which should be used.
*
* @return The NamingStrategy
*/
NamingStrategy getNamingStrategy();
/**
* Access to the SharedCacheMode for determining whether we should perform second level
* caching or not.
*
* @return The SharedCacheMode
*/
SharedCacheMode getSharedCacheMode();
/**
* Access to the default second level cache AccessType to use if not specified.
*
* @return The default AccessType
*/
AccessType getDefaultCacheAccessType();
/**
* Access to whether we should be using the new identifier generator scheme.
* {@code true} indicates to use the new schema, {@code false} indicates to use the
* legacy scheme.
*
* @return Whether to use the new identifier generator scheme
*/
boolean isUseNewIdentifierGenerators();
/**
* Access to the MultiTenancyStrategy for this environment.
*
* @return The MultiTenancyStrategy
*/
MultiTenancyStrategy getMultiTenancyStrategy();
/**
* Access to all explicit cache region mappings.
*
* @return Explicit cache region mappings.
*/
List<CacheRegionDefinition> getCacheRegionDefinitions();
// todo : these 2 will go away...
MetadataSourceProcessingOrder getMetadataSourceProcessingOrder();
EntityResolver getEntityResolver();
}

View File

@ -79,6 +79,7 @@ public interface MetadataImplementor extends Metadata, BindingContext, Mapping {
void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition);
@Deprecated
void setGloballyQuotedIdentifiers(boolean b);
MetaAttributeContext getGlobalMetaAttributeContext();

View File

@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.spi.binding;
/**
* Represents an Entity or MappedSuperclass in the binding model
*
* @author Steve Ebersole
*/
public interface EntityHierarchyBindingNode {
}

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.spi.source;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.spi.MetadataBuildingOptions;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.domain.JavaClassReference;
import org.hibernate.metamodel.spi.domain.Type;
@ -39,6 +40,8 @@ public interface BindingContext {
public MappingDefaults getMappingDefaults();
public MetadataBuildingOptions getBuildingOptions();
public MetadataImplementor getMetadataImplementor();
public <T> Class<T> locateClassByName(String name);

View File

@ -80,7 +80,7 @@ public class AssertSourcesTest extends BaseUnitTestCase {
}
private MetadataImpl buildMetadata(MetadataSources sources) {
return new MetadataImpl( sources, new MetadataBuilderImpl.OptionsImpl( serviceRegistry ) );
return new MetadataImpl( sources, new MetadataBuilderImpl.Options( serviceRegistry ) );
}
private void testUserEntitySources(MetadataSourceProcessor processor) {