HHH-8966 - Redo the MetadataBuilder process;
HHH-8956 - TLC for annotation pre-processor; HHH-8962 - Create a set of light reflection classes; HHH-8932 - Need to integrate JPA 2.1 AttributeConverters into new metamodel binding
This commit is contained in:
parent
0329f37d99
commit
c06a45a636
|
@ -23,14 +23,16 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import org.hibernate.xml.spi.Origin;
|
||||
import org.hibernate.xml.spi.SourceType;
|
||||
|
||||
/**
|
||||
* Annotation related exception.
|
||||
*
|
||||
* The EJB3 EG will probably set a generic exception. I'll then use this one.
|
||||
*
|
||||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AnnotationException extends MappingException {
|
||||
public class AnnotationException extends org.hibernate.metamodel.source.spi.MappingException {
|
||||
/**
|
||||
* Constructs an AnnotationException using the given message and cause.
|
||||
*
|
||||
|
@ -38,7 +40,7 @@ public class AnnotationException extends MappingException {
|
|||
* @param cause The underlying cause.
|
||||
*/
|
||||
public AnnotationException(String msg, Throwable cause) {
|
||||
super( msg, cause );
|
||||
this( msg, cause, new Origin( SourceType.ANNOTATION, "unknown" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,6 +49,14 @@ public class AnnotationException extends MappingException {
|
|||
* @param msg The message explaining the reason for the exception.
|
||||
*/
|
||||
public AnnotationException(String msg) {
|
||||
super( msg );
|
||||
this( msg, new Origin( SourceType.ANNOTATION, "unknown" ) );
|
||||
}
|
||||
|
||||
public AnnotationException(String msg, Throwable cause, Origin origin) {
|
||||
super( msg, cause, origin );
|
||||
}
|
||||
|
||||
public AnnotationException(String msg, Origin origin) {
|
||||
super( msg, origin );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ package org.hibernate;
|
|||
/**
|
||||
* An enumeration of truth values.
|
||||
* <p/>
|
||||
* Yes this *could* be handled with Boolean, but then you run into potential problems with premature
|
||||
* auto-unboxing.
|
||||
* Yes this *could* be handled with Boolean, but then you run into potential
|
||||
* problems with unwanted auto-unboxing.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -36,6 +36,7 @@ public enum TruthValue {
|
|||
FALSE,
|
||||
UNKNOWN;
|
||||
|
||||
@SuppressWarnings("SimplifiableIfStatement")
|
||||
public static boolean toBoolean(TruthValue value, boolean defaultValue) {
|
||||
if ( value == TruthValue.TRUE ) {
|
||||
return true;
|
||||
|
|
|
@ -30,11 +30,15 @@ import static java.lang.annotation.ElementType.METHOD;
|
|||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Names a custom collection type for a persistent collection. The collection can also name a @Type, which defines
|
||||
* the Hibernate Type of the collection elements.
|
||||
* Names a custom collection type for a persistent collection. The collection
|
||||
* can also name a @Type, which defines the Hibernate Type of the collection
|
||||
* elements. If the collection is a Map, can als use @MapKeyType to define the
|
||||
* Hibernate Type of the map key.
|
||||
*
|
||||
* @see org.hibernate.type.CollectionType
|
||||
* @see org.hibernate.usertype.UserCollectionType
|
||||
* @see org.hibernate.annotations.Type
|
||||
* @see org.hibernate.annotations.MapKeyType
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -42,18 +46,21 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||
@Retention(RUNTIME)
|
||||
public @interface CollectionType {
|
||||
/**
|
||||
* Names the type.
|
||||
* Name of the collection type to use.
|
||||
*
|
||||
* Could name the implementation class (an implementation of {@link org.hibernate.type.CollectionType} or
|
||||
* {@link org.hibernate.usertype.UserCollectionType}). Could also name a custom type defined via a
|
||||
* {@link TypeDef @TypeDef}
|
||||
* Could name either:<ul>
|
||||
* <li>the implementation class (an implementation of {@link org.hibernate.type.CollectionType}</li>
|
||||
* <li>the implementation class (an implementation of {@link org.hibernate.usertype.UserCollectionType}</li>
|
||||
* <li>a type defined via a {@link TypeDef @TypeDef}</li>
|
||||
* </ul>
|
||||
*/
|
||||
String type();
|
||||
|
||||
/**
|
||||
* Specifies configuration information for the type. Note that if the named type is a
|
||||
* {@link org.hibernate.usertype.UserCollectionType}, it must also implement
|
||||
* {@link org.hibernate.usertype.ParameterizedType} in order to receive these values.
|
||||
* Specifies configuration information for the type. Note that if the named
|
||||
* type is a {@link org.hibernate.usertype.UserCollectionType}, it must also
|
||||
* implement {@link org.hibernate.usertype.ParameterizedType} in order to
|
||||
* receive these values.
|
||||
*/
|
||||
Parameter[] parameters() default {};
|
||||
}
|
||||
|
|
|
@ -23,15 +23,15 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
|
||||
/**
|
||||
* Define a tuplizer for an entity or a component.
|
||||
*
|
||||
|
@ -47,6 +47,10 @@ public @interface Tuplizer {
|
|||
|
||||
/**
|
||||
* The entity mode.
|
||||
*
|
||||
* @deprecated Specifying multiple entity modes and/or tuplizers for a thing
|
||||
* is no longer supported
|
||||
*/
|
||||
@Deprecated
|
||||
EntityMode entityModeType() default EntityMode.POJO;
|
||||
}
|
||||
|
|
|
@ -31,9 +31,13 @@ import java.lang.annotation.RetentionPolicy;
|
|||
* Grouping of tuplizers.
|
||||
*
|
||||
* @author Emmanuel Bernard
|
||||
*
|
||||
* @deprecated Specifying multiple entity modes and/or tuplizers for a thing
|
||||
* is no longer supported
|
||||
*/
|
||||
@java.lang.annotation.Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
|
||||
@Retention( RetentionPolicy.RUNTIME )
|
||||
@Deprecated
|
||||
public @interface Tuplizers {
|
||||
/**
|
||||
* The grouping of tuplizers.
|
||||
|
|
|
@ -96,7 +96,11 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(EntityBinding model) {
|
||||
return new CacheDataDescriptionImpl( model.isMutable(), model.isVersioned(), getVersionComparator( model ) );
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.getHierarchyDetails().isMutable(),
|
||||
model.getHierarchyDetails().isVersioned(),
|
||||
getVersionComparator( model )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,13 +130,13 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
public static CacheDataDescriptionImpl decode(PluralAttributeBinding model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.getContainer().seekEntityBinding().isVersioned(),
|
||||
model.getContainer().seekEntityBinding().getHierarchyDetails().isVersioned(),
|
||||
getVersionComparator( model.getContainer().seekEntityBinding() )
|
||||
);
|
||||
}
|
||||
|
||||
private static Comparator getVersionComparator(EntityBinding model ) {
|
||||
if ( model.isVersioned() ) {
|
||||
if ( model.getHierarchyDetails().isVersioned() ) {
|
||||
final VersionType versionType = (VersionType) model.getHierarchyDetails()
|
||||
.getEntityVersion().getVersioningAttributeBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
import org.hibernate.metamodel.internal.binder.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* The default <tt>NamingStrategy</tt>
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
import org.hibernate.metamodel.internal.binder.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* Naming strategy implementing the EJB3 standards
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
import org.hibernate.metamodel.internal.binder.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* An improved naming strategy that prefers embedded
|
||||
|
|
|
@ -41,14 +41,13 @@ import javax.validation.metadata.BeanDescriptor;
|
|||
import javax.validation.metadata.ConstraintDescriptor;
|
||||
import javax.validation.metadata.PropertyDescriptor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
@ -70,11 +69,7 @@ import org.hibernate.metamodel.spi.relational.Column;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
class TypeSafeActivator {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
TypeSafeActivator.class.getName()
|
||||
);
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( TypeSafeActivator.class );
|
||||
|
||||
/**
|
||||
* Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory.
|
||||
|
@ -169,7 +164,7 @@ class TypeSafeActivator {
|
|||
Set<Class<?>> groups = new HashSet<Class<?>>( Arrays.asList( groupsArray ) );
|
||||
|
||||
for ( EntityBinding entityBinding : activationContext.getMetadata().getEntityBindings() ) {
|
||||
final String className = entityBinding.getEntity().getDescriptor().getName().fullName();
|
||||
final String className = entityBinding.getEntity().getDescriptor().getName().toString();
|
||||
|
||||
if ( className == null || className.length() == 0 ) {
|
||||
continue;
|
||||
|
@ -224,7 +219,7 @@ class TypeSafeActivator {
|
|||
final SingularAttribute singularAttribute = (SingularAttribute) attribute;
|
||||
if ( singularAttribute.getSingularAttributeType().isAggregate() ) {
|
||||
final Class<?> componentClass = classLoaderService.classForName(
|
||||
singularAttribute.getSingularAttributeType().getDescriptor().getName().fullName()
|
||||
singularAttribute.getSingularAttributeType().getDescriptor().getName().toString()
|
||||
);
|
||||
final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull;
|
||||
applyDDL(
|
||||
|
|
|
@ -92,45 +92,58 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
|
|||
Object[] current,
|
||||
Object[] loaded,
|
||||
SessionImplementor session) {
|
||||
if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) {
|
||||
if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) {
|
||||
// SHORT-CUT: if the natural id is mutable (!immutable), no need to do the below checks
|
||||
// EARLY EXIT!!!
|
||||
return;
|
||||
// series of short-cut checks
|
||||
if ( !persister.hasNaturalIdentifier() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( entry.getStatus() == Status.READ_ONLY ) {
|
||||
// this is a performance opt-out, but not sure this is entirely correct. What
|
||||
// can happen is a situation where we have a immutable natural id that is changed
|
||||
// but we do not check here.
|
||||
//
|
||||
// it comes down to the same old question.. is specifying a natural-id is immutable:
|
||||
// a) a mandate to make sure its value is not changed by the app, or
|
||||
// b) a optimization hint
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// now get to the checks
|
||||
final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties();
|
||||
final Type[] propertyTypes = persister.getPropertyTypes();
|
||||
final boolean[] propertyUpdateability = persister.getPropertyUpdateability();
|
||||
|
||||
final Object[] snapshot = loaded == null
|
||||
? session.getPersistenceContext().getNaturalIdSnapshot( entry.getId(), persister )
|
||||
: session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( loaded, persister );
|
||||
|
||||
for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) {
|
||||
final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i];
|
||||
if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) {
|
||||
// if the given natural id property is updatable (mutable), there is nothing to check
|
||||
continue;
|
||||
}
|
||||
|
||||
final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties();
|
||||
final Type[] propertyTypes = persister.getPropertyTypes();
|
||||
final boolean[] propertyUpdateability = persister.getPropertyUpdateability();
|
||||
|
||||
final Object[] snapshot = loaded == null
|
||||
? session.getPersistenceContext().getNaturalIdSnapshot( entry.getId(), persister )
|
||||
: session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( loaded, persister );
|
||||
|
||||
for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) {
|
||||
final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i];
|
||||
if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) {
|
||||
// if the given natural id property is updatable (mutable), there is nothing to check
|
||||
continue;
|
||||
}
|
||||
|
||||
final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex];
|
||||
if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"An immutable natural identifier of entity %s was altered from %s to %s",
|
||||
persister.getEntityName(),
|
||||
propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
|
||||
snapshot[i],
|
||||
session.getFactory()
|
||||
),
|
||||
propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
|
||||
current[naturalIdentifierPropertyIndex],
|
||||
session.getFactory()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex];
|
||||
if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"An immutable natural identifier of entity %s was altered from %s to %s",
|
||||
persister.getEntityName(),
|
||||
propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
|
||||
snapshot[i],
|
||||
session.getFactory()
|
||||
),
|
||||
propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
|
||||
current[naturalIdentifierPropertyIndex],
|
||||
session.getFactory()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ import java.util.Map;
|
|||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.StringRefAddr;
|
||||
|
||||
|
@ -61,8 +60,8 @@ import org.hibernate.SessionFactory;
|
|||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.StatelessSessionBuilder;
|
||||
import org.hibernate.TruthValue;
|
||||
import org.hibernate.TypeHelper;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
|
@ -120,6 +119,7 @@ import org.hibernate.id.UUIDGenerator;
|
|||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.metadata.CollectionMetadata;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
|
@ -143,6 +143,7 @@ import org.hibernate.tuple.entity.EntityTuplizer;
|
|||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeResolver;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
||||
|
@ -762,7 +763,7 @@ public final class SessionFactoryImpl
|
|||
for ( EntityBinding entityBinding : metadata.getEntityBindings() ) {
|
||||
if ( entityBinding.isRoot() ) {
|
||||
identifierGenerators.put(
|
||||
entityBinding.getEntity().getName(),
|
||||
entityBinding.getEntityName(),
|
||||
entityBinding.getHierarchyDetails().getEntityIdentifier().getIdentifierGenerator()
|
||||
);
|
||||
}
|
||||
|
@ -772,84 +773,93 @@ public final class SessionFactoryImpl
|
|||
// Prepare persisters and link them up with their cache
|
||||
// region/access-strategy
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if ( settings.getCacheRegionPrefix() != null) {
|
||||
stringBuilder
|
||||
.append( settings.getCacheRegionPrefix() )
|
||||
.append( '.' );
|
||||
}
|
||||
RegionFactory regionFactory = cacheAccess.getRegionFactory();
|
||||
final String cacheRegionPrefix = stringBuilder.toString();
|
||||
entityPersisters = new HashMap<String,EntityPersister>();
|
||||
Map<String, RegionAccessStrategy> entityAccessStrategies = new HashMap<String, RegionAccessStrategy>();
|
||||
Map<String,ClassMetadata> classMeta = new HashMap<String,ClassMetadata>();
|
||||
|
||||
final RegionFactory regionFactory = cacheAccess.getRegionFactory();
|
||||
for ( EntityBinding model : metadata.getEntityBindings() ) {
|
||||
// TODO: should temp table prep happen when metadata is being built?
|
||||
//model.prepareTemporaryTables( metadata, getDialect() );
|
||||
// cache region is defined by the root-class in the hierarchy...
|
||||
EntityBinding rootEntityBinding = metadata.getRootEntityBinding( model.getEntity().getName() );
|
||||
|
||||
EntityRegionAccessStrategy accessStrategy = null;
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
rootEntityBinding.getHierarchyDetails().getCaching() != null &&
|
||||
model.getHierarchyDetails().getCaching() != null ) {
|
||||
final String cacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails().getCaching().getRegion();
|
||||
accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) );
|
||||
if ( accessStrategy == null ) {
|
||||
AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType();
|
||||
if ( accessType == null ) {
|
||||
accessType = regionFactory.getDefaultAccessType();
|
||||
}
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for entity data [{0}]", model.getEntity().getName() );
|
||||
}
|
||||
EntityRegion entityRegion = regionFactory.buildEntityRegion(
|
||||
cacheRegionName, properties, CacheDataDescriptionImpl.decode( model )
|
||||
);
|
||||
accessStrategy = entityRegion.buildAccessStrategy( accessType );
|
||||
entityAccessStrategies.put( cacheRegionName, accessStrategy );
|
||||
cacheAccess.addCacheRegion( cacheRegionName, entityRegion );
|
||||
}
|
||||
}
|
||||
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null;
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
rootEntityBinding.getHierarchyDetails().getNaturalIdCaching() != null &&
|
||||
model.getHierarchyDetails().getNaturalIdCaching() != null ) {
|
||||
final String naturalIdCacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails()
|
||||
.getNaturalIdCaching()
|
||||
.getRegion();
|
||||
naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get(
|
||||
naturalIdCacheRegionName
|
||||
);
|
||||
if ( naturalIdAccessStrategy == null ) {
|
||||
final CacheDataDescriptionImpl naturaIdCacheDataDescription = CacheDataDescriptionImpl.decode( model );
|
||||
NaturalIdRegion naturalIdRegion = null;
|
||||
try {
|
||||
naturalIdRegion = regionFactory.buildNaturalIdRegion(
|
||||
|
||||
if ( settings.isSecondLevelCacheEnabled() ) {
|
||||
// caching is defined per hierarchy.. so only do this for the root of the hierarchy
|
||||
if ( model.getSuperEntityBinding() == null ) {
|
||||
if ( model.getHierarchyDetails().getCaching().getRequested() == TruthValue.TRUE ) {
|
||||
String baseRegionName = model.getHierarchyDetails().getCaching().getRegion();
|
||||
if ( baseRegionName == null ) {
|
||||
baseRegionName = model.getEntityName();
|
||||
}
|
||||
final String cacheRegionName = StringHelper.makePath(
|
||||
settings.getCacheRegionPrefix(),
|
||||
baseRegionName
|
||||
);
|
||||
accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) );
|
||||
if ( accessStrategy == null ) {
|
||||
AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType();
|
||||
if ( accessType == null ) {
|
||||
accessType = regionFactory.getDefaultAccessType();
|
||||
}
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for entity data [{0}]", model.getEntityName() );
|
||||
}
|
||||
EntityRegion entityRegion = regionFactory.buildEntityRegion(
|
||||
cacheRegionName, properties, CacheDataDescriptionImpl.decode( model )
|
||||
);
|
||||
accessStrategy = entityRegion.buildAccessStrategy( accessType );
|
||||
entityAccessStrategies.put( cacheRegionName, accessStrategy );
|
||||
cacheAccess.addCacheRegion( cacheRegionName, entityRegion );
|
||||
}
|
||||
}
|
||||
|
||||
if ( model.getHierarchyDetails().getNaturalIdCaching().getRequested() == TruthValue.TRUE ) {
|
||||
String baseRegionName = model.getHierarchyDetails().getNaturalIdCaching().getRegion();
|
||||
if ( StringHelper.isEmpty( baseRegionName ) ) {
|
||||
baseRegionName = model.getEntityName() + "##NaturalId";
|
||||
}
|
||||
final String naturalIdCacheRegionName = StringHelper.makePath(
|
||||
settings.getCacheRegionPrefix(),
|
||||
baseRegionName
|
||||
);
|
||||
naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get(
|
||||
naturalIdCacheRegionName
|
||||
);
|
||||
if ( naturalIdAccessStrategy == null ) {
|
||||
final CacheDataDescriptionImpl naturalIdCacheDataDescription = CacheDataDescriptionImpl.decode( model );
|
||||
NaturalIdRegion naturalIdRegion = null;
|
||||
try {
|
||||
naturalIdRegion = regionFactory.buildNaturalIdRegion(
|
||||
naturalIdCacheRegionName,
|
||||
properties,
|
||||
naturaIdCacheDataDescription
|
||||
naturalIdCacheDataDescription
|
||||
);
|
||||
}
|
||||
catch ( UnsupportedOperationException e ) {
|
||||
LOG.warnf(
|
||||
"Shared cache region factory [%s] does not support natural id caching; " +
|
||||
"shared NaturalId caching will be disabled for not be enabled for %s",
|
||||
regionFactory.getClass().getName(),
|
||||
model.getEntity().getName()
|
||||
);
|
||||
}
|
||||
if ( naturalIdRegion != null ) {
|
||||
naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() );
|
||||
entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
|
||||
cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion );
|
||||
}
|
||||
catch ( UnsupportedOperationException e ) {
|
||||
LOG.warnf(
|
||||
"Shared cache region factory [%s] does not support natural id caching; " +
|
||||
"shared NaturalId caching will be disabled for not be enabled for %s",
|
||||
regionFactory.getClass().getName(),
|
||||
model.getEntityName()
|
||||
);
|
||||
}
|
||||
if ( naturalIdRegion != null ) {
|
||||
naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() );
|
||||
entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
|
||||
cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
|
||||
model, accessStrategy, naturalIdAccessStrategy, this, metadata
|
||||
);
|
||||
entityPersisters.put( model.getEntity().getName(), cp );
|
||||
classMeta.put( model.getEntity().getName(), cp.getClassMetadata() );
|
||||
entityPersisters.put( model.getEntityName(), cp );
|
||||
classMeta.put( model.getEntityName(), cp.getClassMetadata() );
|
||||
}
|
||||
this.classMetadata = Collections.unmodifiableMap(classMeta);
|
||||
|
||||
|
@ -866,15 +876,21 @@ public final class SessionFactoryImpl
|
|||
);
|
||||
}
|
||||
CollectionRegionAccessStrategy accessStrategy = null;
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
model.getCaching() != null ) {
|
||||
|
||||
final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion();
|
||||
if ( settings.isSecondLevelCacheEnabled()
|
||||
&& model.getCaching().getRequested() == TruthValue.TRUE ) {
|
||||
String baseRegionName = model.getCaching().getRegion();
|
||||
if ( baseRegionName == null ) {
|
||||
baseRegionName = model.getAttributePath();
|
||||
}
|
||||
final String cacheRegionName = StringHelper.makePath(
|
||||
settings.getCacheRegionPrefix(),
|
||||
baseRegionName
|
||||
);
|
||||
AccessType accessType = model.getCaching().getAccessType();
|
||||
if( accessType == null ){
|
||||
if ( accessType == null ) {
|
||||
accessType = regionFactory.getDefaultAccessType();
|
||||
}
|
||||
if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
|
||||
if ( accessType != null ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() );
|
||||
}
|
||||
|
|
|
@ -33,14 +33,6 @@ import java.lang.reflect.Modifier;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.classmate.MemberResolver;
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
import com.fasterxml.classmate.types.ResolvedArrayType;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
|
@ -51,6 +43,14 @@ import org.hibernate.property.PropertyAccessor;
|
|||
import org.hibernate.type.PrimitiveType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import com.fasterxml.classmate.MemberResolver;
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
import com.fasterxml.classmate.types.ResolvedArrayType;
|
||||
|
||||
/**
|
||||
* Utility class for various reflection operations.
|
||||
*
|
||||
|
@ -409,20 +409,25 @@ public final class ReflectHelper {
|
|||
}
|
||||
|
||||
if ( member instanceof Method ) {
|
||||
String methodName = member.getName();
|
||||
if ( methodName.startsWith( "is" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 2 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "has" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "get" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
name = getPropertyNameFromGetterMethod( member.getName() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getPropertyNameFromGetterMethod(String methodName) {
|
||||
if ( methodName.startsWith( "is" ) ) {
|
||||
return Introspector.decapitalize( methodName.substring( 2 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "has" ) ) {
|
||||
return Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "get" ) ) {
|
||||
return Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isProperty(Member m) {
|
||||
if ( m instanceof Method ) {
|
||||
Method method = (Method) m;
|
||||
|
|
|
@ -783,4 +783,16 @@ public final class StringHelper {
|
|||
public static String[] toArrayElement(String s) {
|
||||
return ( s == null || s.length() == 0 ) ? new String[0] : new String[] { s };
|
||||
}
|
||||
|
||||
public static String makePath(String base, String name) {
|
||||
if ( isEmpty( name ) ) {
|
||||
throw new IllegalArgumentException( "Name used to make path cannot be empty" );
|
||||
}
|
||||
|
||||
return isEmpty( base ) ? name : base + '.' + name;
|
||||
}
|
||||
|
||||
public static String nullIfEmpty(String value) {
|
||||
return isEmpty( value ) ? null : value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,13 +30,36 @@ import org.hibernate.internal.util.StringHelper;
|
|||
*/
|
||||
public class PropertyPath {
|
||||
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";
|
||||
|
||||
private final char delimiter;
|
||||
private final PropertyPath parent;
|
||||
private final String property;
|
||||
private final String fullPath;
|
||||
|
||||
public PropertyPath(PropertyPath parent, String property) {
|
||||
public PropertyPath() {
|
||||
this( null, "", '.' );
|
||||
}
|
||||
|
||||
public PropertyPath(char delimiter) {
|
||||
this( null, "", delimiter );
|
||||
}
|
||||
|
||||
public PropertyPath(String base) {
|
||||
this( null, base, '.' );
|
||||
}
|
||||
|
||||
public PropertyPath(String base, char delimiter) {
|
||||
this( null, base, delimiter );
|
||||
}
|
||||
|
||||
private PropertyPath(PropertyPath parent, String property) {
|
||||
this( parent, property, parent.delimiter );
|
||||
}
|
||||
|
||||
private PropertyPath(PropertyPath parent, String property, char delimiter) {
|
||||
this.parent = parent;
|
||||
this.property = property;
|
||||
this.delimiter = delimiter;
|
||||
|
||||
// the _identifierMapper is a "hidden" property on entities with composite keys.
|
||||
// concatenating it will prevent the path from correctly being used to look up
|
||||
|
@ -52,7 +75,7 @@ public class PropertyPath {
|
|||
prefix = "";
|
||||
}
|
||||
else {
|
||||
prefix = resolvedParent + '.';
|
||||
prefix = resolvedParent + delimiter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -63,14 +86,6 @@ public class PropertyPath {
|
|||
}
|
||||
}
|
||||
|
||||
public PropertyPath(String property) {
|
||||
this( null, property );
|
||||
}
|
||||
|
||||
public PropertyPath() {
|
||||
this( "" );
|
||||
}
|
||||
|
||||
public PropertyPath append(String property) {
|
||||
return new PropertyPath( this, property );
|
||||
}
|
||||
|
@ -87,8 +102,12 @@ public class PropertyPath {
|
|||
return fullPath;
|
||||
}
|
||||
|
||||
public char getDelimiter() {
|
||||
return delimiter;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null && StringHelper.isEmpty( property );
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,9 +25,6 @@ package org.hibernate.metamodel;
|
|||
|
||||
import javax.persistence.SharedCacheMode;
|
||||
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.xml.sax.EntityResolver;
|
||||
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
|
@ -36,6 +33,10 @@ import org.hibernate.type.BasicType;
|
|||
import org.hibernate.usertype.CompositeUserType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import org.jboss.jandex.IndexView;
|
||||
|
||||
import org.xml.sax.EntityResolver;
|
||||
|
||||
/**
|
||||
* Contract for specifying various overrides to be used in metamodel building.
|
||||
*
|
||||
|
@ -121,6 +122,15 @@ public interface MetadataBuilder {
|
|||
*/
|
||||
public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param enabled
|
||||
* @return
|
||||
*/
|
||||
public MetadataBuilder withExplicitDiscriminatorsForJoinedSubclassSupport(boolean enabled);
|
||||
|
||||
public MetadataBuilder withImplicitDiscriminatorsForJoinedSubclassSupport(boolean enabled);
|
||||
|
||||
/**
|
||||
* Specify an additional or overridden basic type mapping.
|
||||
*
|
||||
|
|
|
@ -51,23 +51,27 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.SerializationHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.MetadataBuilderImpl;
|
||||
import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbConverter;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddable;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListener;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbUnionSubclassElement;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbConverter;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddable;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass;
|
||||
import org.hibernate.metamodel.internal.MetadataBuilderImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.source.InvalidMappingException;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.MappingNotFoundException;
|
||||
import org.hibernate.metamodel.source.spi.InvalidMappingException;
|
||||
import org.hibernate.metamodel.source.spi.MappingException;
|
||||
import org.hibernate.metamodel.source.spi.MappingNotFoundException;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.SerializationException;
|
||||
import org.hibernate.xml.internal.jaxb.MappingXmlBinder;
|
||||
|
@ -826,6 +830,14 @@ public class MetadataSources {
|
|||
private void indexOrmXmlReferences(JaxbEntityMappings ormXmlRoot) {
|
||||
final String packageName = ormXmlRoot.getPackage();
|
||||
|
||||
final JaxbPersistenceUnitMetadata puMetadata = ormXmlRoot.getPersistenceUnitMetadata();
|
||||
if ( puMetadata != null ) {
|
||||
final JaxbPersistenceUnitDefaults puDefaults = puMetadata.getPersistenceUnitDefaults();
|
||||
if ( puDefaults != null ) {
|
||||
indexEntityListeners( puDefaults.getEntityListeners(), packageName );
|
||||
}
|
||||
}
|
||||
|
||||
for ( JaxbConverter jaxbConverter : ormXmlRoot.getConverter() ) {
|
||||
indexClassName( toDotName( jaxbConverter.getClazz(), packageName ) );
|
||||
}
|
||||
|
@ -840,6 +852,19 @@ public class MetadataSources {
|
|||
|
||||
for ( JaxbEntity jaxbEntity : ormXmlRoot.getEntity() ) {
|
||||
indexClassName( toDotName( jaxbEntity.getClazz(), packageName ) );
|
||||
indexEntityListeners( jaxbEntity.getEntityListeners(), packageName );
|
||||
}
|
||||
}
|
||||
|
||||
private void indexEntityListeners(JaxbEntityListeners listeners, String packageName) {
|
||||
if ( listeners == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( JaxbEntityListener listener : listeners.getEntityListener() ) {
|
||||
if ( StringHelper.isNotEmpty( listener.getClazz() ) ) {
|
||||
indexClassName( toDotName( listener.getClazz(), packageName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityHierarchyHelper {
|
||||
|
||||
public interface LocalBindingContextExecutor {
|
||||
void execute(LocalBindingContextExecutionContext bindingContextContext);
|
||||
}
|
||||
|
||||
public interface LocalBindingContextExecutionContext {
|
||||
RootEntitySource getRootEntitySource();
|
||||
EntitySource getEntitySource();
|
||||
EntityBinding getEntityBinding();
|
||||
EntityBinding getSuperEntityBinding();
|
||||
InheritanceType getInheritanceType();
|
||||
EntityMode getEntityMode();
|
||||
}
|
||||
|
||||
public static interface LocalBindingContextManager extends LocalBindingContextExecutionContext {
|
||||
LocalBindingContext localBindingContext();
|
||||
void cleanupLocalBindingContexts();
|
||||
void setupLocalBindingContexts(final EntityHierarchy entityHierarchy);
|
||||
void pushSubEntitySource(EntitySource entitySource);
|
||||
void popSubEntitySource();
|
||||
}
|
||||
|
||||
private LocalBindingContextManager localBindingContextManager;
|
||||
|
||||
EntityHierarchyHelper(final LocalBindingContextManager localBindingContextManager) {
|
||||
this.localBindingContextManager = localBindingContextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply executors to all entity hierarchies.
|
||||
*/
|
||||
public void applyToAllEntityHierarchies(
|
||||
final Iterable<EntityHierarchy> entityHierarchies,
|
||||
final LocalBindingContextExecutor rootEntityExecutor,
|
||||
final LocalBindingContextExecutor subEntityExecutor) {
|
||||
for ( final EntityHierarchy entityHierarchy : entityHierarchies ) {
|
||||
applyToEntityHierarchy( entityHierarchy, rootEntityExecutor, subEntityExecutor );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply executors to a single entity hierarchy.
|
||||
*
|
||||
* @param entityHierarchy The entity hierarchy to be binded.
|
||||
* @param rootEntityExecutor The executor to be applied to the root {@link EntitySource}
|
||||
* in the entity hierarchy.
|
||||
* @param subEntityExecutor The executer to be applied to each {@link SubclassEntitySource}
|
||||
* in the entity hierarchy.
|
||||
*/
|
||||
public void applyToEntityHierarchy(
|
||||
final EntityHierarchy entityHierarchy,
|
||||
final LocalBindingContextExecutor rootEntityExecutor,
|
||||
final LocalBindingContextExecutor subEntityExecutor) {
|
||||
localBindingContextManager.cleanupLocalBindingContexts();
|
||||
localBindingContextManager.setupLocalBindingContexts( entityHierarchy );
|
||||
try {
|
||||
rootEntityExecutor.execute( localBindingContextManager );
|
||||
if ( entityHierarchy.getHierarchyInheritanceType() != InheritanceType.NO_INHERITANCE ) {
|
||||
applyToSubEntities( subEntityExecutor );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
localBindingContextManager.cleanupLocalBindingContexts();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyToSubEntities(final LocalBindingContextExecutor subEntityExecutor) {
|
||||
for ( final SubclassEntitySource subEntitySource : localBindingContextManager.getEntitySource().subclassEntitySources() ) {
|
||||
applyToSubEntity( subEntitySource, subEntityExecutor );
|
||||
}
|
||||
}
|
||||
|
||||
private void applyToSubEntity(final EntitySource entitySource, final LocalBindingContextExecutor subEntityExecutor) {
|
||||
localBindingContextManager.pushSubEntitySource( entitySource );
|
||||
try {
|
||||
subEntityExecutor.execute( localBindingContextManager );
|
||||
applyToSubEntities( subEntityExecutor );
|
||||
}
|
||||
finally {
|
||||
localBindingContextManager.popSubEntitySource();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class LocalBindingContextManagerImpl implements EntityHierarchyHelper.LocalBindingContextManager {
|
||||
private final LocalBindingContextsImpl localBindingContexts = new LocalBindingContextsImpl();
|
||||
|
||||
@Override
|
||||
public void cleanupLocalBindingContexts() {
|
||||
localBindingContexts.cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupLocalBindingContexts(final EntityHierarchy entityHierarchy) {
|
||||
localBindingContexts.setup( entityHierarchy );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushSubEntitySource(EntitySource entitySource) {
|
||||
localBindingContexts.pushEntitySource( entitySource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popSubEntitySource() {
|
||||
localBindingContexts.popEntitySource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMode getEntityMode() {
|
||||
return entityHierarchy().getRootEntitySource().getEntityMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InheritanceType getInheritanceType() {
|
||||
return entityHierarchy().getHierarchyInheritanceType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootEntitySource getRootEntitySource() {
|
||||
return entityHierarchy().getRootEntitySource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntitySource getEntitySource() {
|
||||
if ( localBindingContexts.isEmpty() ) {
|
||||
throw new IllegalStateException( "No LocalBindingContext defined." );
|
||||
}
|
||||
return localBindingContexts.entitySource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding getEntityBinding() {
|
||||
return getMetadataCollector().getEntityBinding( getEntitySource().getEntityName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding getSuperEntityBinding() {
|
||||
final EntitySource superEntitySource = getSuperEntitySource();
|
||||
return superEntitySource == null ?
|
||||
null :
|
||||
getMetadataCollector().getEntityBinding( superEntitySource.getEntityName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalBindingContext localBindingContext() {
|
||||
return getEntitySource().getLocalBindingContext();
|
||||
}
|
||||
|
||||
private InFlightMetadataCollector getMetadataCollector() {
|
||||
return localBindingContext().getMetadataCollector();
|
||||
}
|
||||
|
||||
private EntitySource getSuperEntitySource() {
|
||||
if ( localBindingContexts.isEmpty() ) {
|
||||
throw new IllegalStateException( "No LocalBindingContext defined." );
|
||||
}
|
||||
return localBindingContexts.superEntitySource();
|
||||
}
|
||||
|
||||
private EntityHierarchy entityHierarchy() {
|
||||
if ( localBindingContexts.isEmpty() ) {
|
||||
throw new IllegalStateException( "No LocalBindingContext defined." );
|
||||
}
|
||||
return localBindingContexts.entityHierarchy();
|
||||
}
|
||||
|
||||
// Each EntitySource contains its LocalBindingContext.
|
||||
private class LocalBindingContextsImpl {
|
||||
private EntityHierarchy entityHierarchy;
|
||||
private final LinkedList<EntitySource> entitySources = new LinkedList<EntitySource>( );
|
||||
|
||||
private boolean isEmpty() {
|
||||
return entityHierarchy == null;
|
||||
}
|
||||
|
||||
private void setup(final EntityHierarchy entityHierarchy) {
|
||||
// Inheritance type and entity mode applies to entire hierarchy
|
||||
if ( entityHierarchy == null || entityHierarchy.getRootEntitySource() == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
"entityHierarchy and entityHierarchy.getRootEntitySource() must be non-null."
|
||||
);
|
||||
}
|
||||
if ( this.entityHierarchy != null ) {
|
||||
throw new IllegalStateException( "Attempt to initialize entityHierarchy when it is already initialized." );
|
||||
}
|
||||
this.entityHierarchy = entityHierarchy;
|
||||
this.entitySources.push( entityHierarchy.getRootEntitySource() );
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
entityHierarchy = null;
|
||||
entitySources.clear();
|
||||
}
|
||||
|
||||
private void pushEntitySource(EntitySource entitySource) {
|
||||
entitySources.push( entitySource );
|
||||
}
|
||||
|
||||
private void popEntitySource() {
|
||||
entitySources.pop();
|
||||
}
|
||||
|
||||
private EntityHierarchy entityHierarchy() {
|
||||
return entityHierarchy;
|
||||
}
|
||||
|
||||
private EntitySource entitySource() {
|
||||
return entitySources.peek();
|
||||
}
|
||||
|
||||
private EntitySource superEntitySource() {
|
||||
if ( entitySources.size() == 1 ) {
|
||||
return null;
|
||||
}
|
||||
final EntitySource currentEntitySource = entitySources.pop();
|
||||
final EntitySource superEntitySource = entitySources.peek();
|
||||
entitySources.push( currentEntitySource );
|
||||
return superEntitySource;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -156,6 +156,18 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataBuilder withExplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) {
|
||||
options.explicitDiscriminatorsForJoinedInheritanceSupported = supported;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataBuilder withImplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) {
|
||||
options.implicitDiscriminatorsForJoinedInheritanceSupported = supported;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataBuilder with(BasicType type) {
|
||||
options.basicTypeRegistrations.add( type );
|
||||
|
@ -273,6 +285,8 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
|
|||
private boolean useNewIdentifierGenerators;
|
||||
private MultiTenancyStrategy multiTenancyStrategy;
|
||||
private List<CacheRegionDefinition> cacheRegionDefinitions;
|
||||
private boolean explicitDiscriminatorsForJoinedInheritanceSupported;
|
||||
private boolean implicitDiscriminatorsForJoinedInheritanceSupported;
|
||||
|
||||
// todo : go away
|
||||
private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST;
|
||||
|
@ -302,6 +316,18 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
|
|||
);
|
||||
|
||||
multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() );
|
||||
|
||||
implicitDiscriminatorsForJoinedInheritanceSupported = configService.getSetting(
|
||||
AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
|
||||
explicitDiscriminatorsForJoinedInheritanceSupported = !configService.getSetting(
|
||||
AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -359,6 +385,16 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
|
|||
return cacheRegionDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreExplicitDiscriminatorsForJoinedInheritance() {
|
||||
return !explicitDiscriminatorsForJoinedInheritanceSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createImplicitDiscriminatorsForJoinedInheritance() {
|
||||
return implicitDiscriminatorsForJoinedInheritanceSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder() {
|
||||
return metadataSourceProcessingOrder;
|
||||
|
|
|
@ -58,14 +58,20 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.metamodel.MetadataSourceProcessingOrder;
|
||||
import org.hibernate.metamodel.MetadataSources;
|
||||
import org.hibernate.metamodel.SessionFactoryBuilder;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationMetadataSourceProcessorImpl;
|
||||
import org.hibernate.metamodel.internal.source.hbm.HbmMetadataSourceProcessorImpl;
|
||||
import org.hibernate.metamodel.internal.binder.Binder;
|
||||
import org.hibernate.metamodel.reflite.internal.JavaTypeDescriptorRepositoryImpl;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository;
|
||||
import org.hibernate.metamodel.source.internal.annotations.AnnotationMetadataSourceProcessorImpl;
|
||||
import org.hibernate.metamodel.source.internal.hbm.HbmMetadataSourceProcessorImpl;
|
||||
import org.hibernate.metamodel.source.internal.jandex.Unifier;
|
||||
import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings;
|
||||
import org.hibernate.metamodel.source.spi.FilterDefinitionSource;
|
||||
import org.hibernate.metamodel.source.spi.FilterParameterSource;
|
||||
import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource;
|
||||
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
||||
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
||||
import org.hibernate.metamodel.source.spi.TypeDescriptorSource;
|
||||
import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer;
|
||||
import org.hibernate.metamodel.spi.BindingContext;
|
||||
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
|
||||
|
@ -74,10 +80,8 @@ import org.hibernate.metamodel.spi.MetadataContributor;
|
|||
import org.hibernate.metamodel.spi.MetadataSourceProcessor;
|
||||
import org.hibernate.metamodel.spi.TypeContributions;
|
||||
import org.hibernate.metamodel.spi.TypeContributor;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.FetchProfile;
|
||||
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
|
||||
|
@ -98,12 +102,6 @@ import org.hibernate.metamodel.spi.relational.Database;
|
|||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.source.FilterDefinitionSource;
|
||||
import org.hibernate.metamodel.spi.source.FilterParameterSource;
|
||||
import org.hibernate.metamodel.spi.source.IdentifierGeneratorSource;
|
||||
import org.hibernate.metamodel.spi.source.MappingDefaults;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
import org.hibernate.metamodel.spi.source.TypeDescriptorSource;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
|
@ -112,6 +110,7 @@ import org.hibernate.usertype.CompositeUserType;
|
|||
import org.hibernate.usertype.UserType;
|
||||
import org.hibernate.xml.spi.BindResult;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -453,37 +452,29 @@ public class MetadataBuildingProcess {
|
|||
return;
|
||||
}
|
||||
|
||||
for ( CacheRegionDefinition cacheRegionDefinition : bindingContext.getBuildingOptions().getCacheRegionDefinitions() ) {
|
||||
final String role = cacheRegionDefinition.getRole();
|
||||
if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
final EntityBinding entityBinding = bindingContext.getMetadataCollector().getEntityBinding( role );
|
||||
if ( entityBinding != null ) {
|
||||
entityBinding.getHierarchyDetails().setCaching(
|
||||
new Caching(
|
||||
cacheRegionDefinition.getRegion(),
|
||||
AccessType.fromExternalName( cacheRegionDefinition.getUsage() ),
|
||||
cacheRegionDefinition.isCacheLazy()
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
//logging?
|
||||
throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" );
|
||||
}
|
||||
for ( CacheRegionDefinition override : bindingContext.getBuildingOptions().getCacheRegionDefinitions() ) {
|
||||
final String role = override.getRole();
|
||||
|
||||
// NOTE : entity region overrides are already handled when building the
|
||||
if ( override.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
// final EntityBinding entityBinding = bindingContext.getMetadataCollector().getEntityBinding( role );
|
||||
// if ( entityBinding != null ) {
|
||||
// entityBinding.getHierarchyDetails().getCaching().setRegion( override.getRegion() );
|
||||
// entityBinding.getHierarchyDetails().getCaching().setAccessType( AccessType.fromExternalName( override.getUsage() ) );
|
||||
// entityBinding.getHierarchyDetails().getCaching().setCacheLazyProperties( override.isCacheLazy() );
|
||||
// }
|
||||
// else {
|
||||
// //logging?
|
||||
// throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" );
|
||||
// }
|
||||
|
||||
}
|
||||
else if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.COLLECTION ) {
|
||||
else if ( override.getRegionType() == CacheRegionDefinition.CacheRegionType.COLLECTION ) {
|
||||
final PluralAttributeBinding pluralAttributeBinding = bindingContext.getMetadataCollector().getCollection(
|
||||
role
|
||||
);
|
||||
if ( pluralAttributeBinding != null ) {
|
||||
AbstractPluralAttributeBinding.class.cast( pluralAttributeBinding ).setCaching(
|
||||
new Caching(
|
||||
cacheRegionDefinition.getRegion(),
|
||||
AccessType.fromExternalName( cacheRegionDefinition.getUsage() ),
|
||||
cacheRegionDefinition.isCacheLazy()
|
||||
)
|
||||
);
|
||||
pluralAttributeBinding.getCaching().overlay( override );
|
||||
}
|
||||
else {
|
||||
//logging?
|
||||
|
@ -531,7 +522,7 @@ public class MetadataBuildingProcess {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptorRepository getRefliteRepository() {
|
||||
public JavaTypeDescriptorRepository getJavaTypeDescriptorRepository() {
|
||||
return javaTypeDescriptorRepository;
|
||||
}
|
||||
|
||||
|
@ -581,10 +572,10 @@ public class MetadataBuildingProcess {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Type makeDomainType(Name typeName) {
|
||||
public Type makeDomainType(DotName typeName) {
|
||||
return new BasicType(
|
||||
typeName.fullName(),
|
||||
typeDescriptor( typeName.fullName() )
|
||||
typeName.toString(),
|
||||
typeDescriptor( typeName.toString() )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1067,13 +1058,13 @@ public class MetadataBuildingProcess {
|
|||
|
||||
@Override
|
||||
public void addEntity(EntityBinding entityBinding) {
|
||||
final String entityName = entityBinding.getEntity().getName();
|
||||
final String entityName = entityBinding.getEntityName();
|
||||
if ( entityBindingMap.containsKey( entityName ) ) {
|
||||
throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName );
|
||||
}
|
||||
entityBindingMap.put( entityName, entityBinding );
|
||||
final boolean isPOJO = entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO;
|
||||
final String className = isPOJO ? entityBinding.getEntity().getDescriptor().getName().fullName() : null;
|
||||
final String className = isPOJO ? entityBinding.getEntity().getDescriptor().getName().toString() : null;
|
||||
if ( isPOJO && StringHelper.isEmpty( className ) ) {
|
||||
throw new MappingException( "Entity[" + entityName + "] is mapped as pojo but don't have a class name" );
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
|
||||
|
||||
/**
|
||||
* The processes performed by Binder are done as a series of steps, where each
|
||||
* step performs a iteration on an entity hierarchy and visits the hierarchy and
|
||||
* its entities.
|
||||
* <p/>
|
||||
* This contract representations access to "context information" relating to the
|
||||
* visitation and is presented to the visitation strategies.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface BinderLocalBindingContext extends BinderRootContext, LocalBindingContext {
|
||||
/**
|
||||
* Locate the binding representation of the hierarchy for the given source
|
||||
* representation.
|
||||
*
|
||||
* @param source The source representation
|
||||
*
|
||||
* @return The binding representation
|
||||
*/
|
||||
public HierarchyDetails locateBinding(EntityHierarchySource source);
|
||||
|
||||
/**
|
||||
* Locate the binding representation of the entity for the given source
|
||||
* representation.
|
||||
*
|
||||
* @param source The source representation
|
||||
*
|
||||
* @return The binding representation
|
||||
*/
|
||||
public EntityBinding locateBinding(EntitySource source);
|
||||
|
||||
HibernateTypeHelper typeHelper();
|
||||
RelationalIdentifierHelper relationalIdentifierHelper();
|
||||
TableHelper tableHelper();
|
||||
ForeignKeyHelper foreignKeyHelper();
|
||||
RelationalValueBindingHelper relationalValueBindingHelper();
|
||||
NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper();
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BinderLocalBindingContextSelector {
|
||||
BinderLocalBindingContext getCurrentBinderLocalBindingContext();
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
||||
import org.hibernate.metamodel.source.spi.MappingException;
|
||||
import org.hibernate.metamodel.spi.BaseDelegatingBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
|
||||
import org.hibernate.xml.spi.Origin;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BinderLocalBindingContextSelectorImpl implements BinderLocalBindingContextSelector {
|
||||
private final BinderRootContext rootContext;
|
||||
private BinderLocalBindingContextImpl current;
|
||||
|
||||
public BinderLocalBindingContextSelectorImpl(BinderRootContext rootContext) {
|
||||
this.rootContext = rootContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinderLocalBindingContext getCurrentBinderLocalBindingContext() {
|
||||
if ( current == null ) {
|
||||
throw new AssertionFailure( "No BinderLocalBindingContextImpl currently set" );
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
public BinderLocalBindingContext setCurrent(EntitySource entitySource) {
|
||||
current = new BinderLocalBindingContextImpl( rootContext, entitySource );
|
||||
return current;
|
||||
}
|
||||
|
||||
public void unsetCurrent() {
|
||||
current = null;
|
||||
}
|
||||
|
||||
private static class BinderLocalBindingContextImpl
|
||||
extends BaseDelegatingBindingContext
|
||||
implements BinderLocalBindingContext {
|
||||
|
||||
private final EntitySource source;
|
||||
|
||||
private BinderLocalBindingContextImpl(BinderRootContext parent, EntitySource source) {
|
||||
super( parent );
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinderRootContext parent() {
|
||||
return (BinderRootContext) super.parent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HierarchyDetails locateBinding(EntityHierarchySource source) {
|
||||
return parent().locateBinding( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding locateBinding(EntitySource source) {
|
||||
return parent().locateBinding( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinderLocalBindingContextSelector getLocalBindingContextSelector() {
|
||||
return parent().getLocalBindingContextSelector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeHelper typeHelper() {
|
||||
return parent().typeHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationalIdentifierHelper relationalIdentifierHelper() {
|
||||
return parent().relationalIdentifierHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableHelper tableHelper() {
|
||||
return parent().tableHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyHelper foreignKeyHelper() {
|
||||
return parent().foreignKeyHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationalValueBindingHelper relationalValueBindingHelper() {
|
||||
return parent().relationalValueBindingHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() {
|
||||
return parent().naturalIdUniqueKeyHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean quoteIdentifiersInContext() {
|
||||
// NOTE : for now source.quoteIdentifiersLocalToEntity() only ever returns
|
||||
// TRUE/UNKNOWN. The logic here accounts for possible future
|
||||
// allowance of selectively disabling global-identifier-quoting.
|
||||
switch ( source.quoteIdentifiersLocalToEntity() ) {
|
||||
case TRUE: {
|
||||
return true;
|
||||
}
|
||||
case FALSE: {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
return super.quoteIdentifiersInContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String qualifyClassName(String name) {
|
||||
return source.getLocalBindingContext().qualifyClassName( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor typeDescriptor(String name) {
|
||||
return source.getLocalBindingContext().typeDescriptor( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingDefaults getMappingDefaults() {
|
||||
return source.getLocalBindingContext().getMappingDefaults();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin() {
|
||||
return source.getLocalBindingContext().getOrigin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingException makeMappingException(String message) {
|
||||
return source.getLocalBindingContext().makeMappingException( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingException makeMappingException(String message, Exception cause) {
|
||||
return source.getLocalBindingContext().makeMappingException( message, cause );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.source.spi.IdentifiableTypeSource;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
|
||||
/**
|
||||
* The processes performed by Binder are done as a series of steps, where each
|
||||
* step performs a iteration on an entity hierarchy and visits the hierarchy and
|
||||
* its entities.
|
||||
* <p/>
|
||||
* This class is the visitation process. In many ways its a simple iterator over the
|
||||
* EntitySource structure skipping MapperSuperclassSource types.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BinderProcessHelper {
|
||||
private final BinderRootContext context;
|
||||
|
||||
public static final BinderStepHierarchyStrategy NOOP_HIERARCHY_STRATEGY = new BinderStepHierarchyStrategy() {
|
||||
@Override
|
||||
public void visit(EntityHierarchySource source, BinderLocalBindingContext context) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
public static final BinderStepEntityStrategy NOOP_ENTITY_STRATEGY = new BinderStepEntityStrategy() {
|
||||
@Override
|
||||
public boolean applyToRootEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(EntitySource source, BinderLocalBindingContext context) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
public BinderProcessHelper(BinderRootContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void apply(
|
||||
Collection<EntityHierarchySource> hierarchySources,
|
||||
BinderStepHierarchyStrategy hierarchyStrategy) {
|
||||
for ( EntityHierarchySource hierarchySource : hierarchySources ) {
|
||||
apply( hierarchySource, hierarchyStrategy );
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(EntityHierarchySource hierarchySource, BinderStepHierarchyStrategy hierarchyStrategy) {
|
||||
apply( hierarchySource, hierarchyStrategy, NOOP_ENTITY_STRATEGY );
|
||||
}
|
||||
|
||||
public void apply(
|
||||
Collection<EntityHierarchySource> hierarchySources,
|
||||
BinderStepCombinedStrategy strategy) {
|
||||
for ( EntityHierarchySource hierarchySource : hierarchySources ) {
|
||||
apply( hierarchySource, strategy );
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(EntityHierarchySource hierarchySource, BinderStepCombinedStrategy strategy) {
|
||||
apply( hierarchySource, strategy, strategy );
|
||||
}
|
||||
|
||||
public void apply(
|
||||
Collection<EntityHierarchySource> hierarchySources,
|
||||
BinderStepEntityStrategy entityStrategy) {
|
||||
for ( EntityHierarchySource hierarchySource: hierarchySources ) {
|
||||
apply( hierarchySource, entityStrategy );
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(EntityHierarchySource hierarchySource, BinderStepEntityStrategy strategy) {
|
||||
apply( hierarchySource, NOOP_HIERARCHY_STRATEGY, strategy );
|
||||
}
|
||||
|
||||
public void apply(
|
||||
Collection<EntityHierarchySource> hierarchySources,
|
||||
BinderStepHierarchyStrategy hierarchyStrategy,
|
||||
BinderStepEntityStrategy entityStrategy) {
|
||||
for ( EntityHierarchySource hierarchySource: hierarchySources ) {
|
||||
apply( hierarchySource, hierarchyStrategy, entityStrategy );
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(
|
||||
EntityHierarchySource hierarchySource,
|
||||
BinderStepHierarchyStrategy hierarchyStrategy,
|
||||
BinderStepEntityStrategy entityStrategy) {
|
||||
final BinderLocalBindingContextSelectorImpl selector
|
||||
= (BinderLocalBindingContextSelectorImpl) context.getLocalBindingContextSelector();
|
||||
|
||||
BinderLocalBindingContext localContext = selector.setCurrent( hierarchySource.getRoot() );
|
||||
hierarchyStrategy.visit( hierarchySource, localContext );
|
||||
|
||||
final EntitySource rootEntitySource = hierarchySource.getRoot();
|
||||
if ( entityStrategy.applyToRootEntity() ) {
|
||||
entityStrategy.visit( rootEntitySource, localContext );
|
||||
}
|
||||
|
||||
if ( hierarchySource.getHierarchyInheritanceType() != InheritanceType.NO_INHERITANCE ) {
|
||||
visitSubclasses( rootEntitySource, entityStrategy, localContext );
|
||||
}
|
||||
}
|
||||
|
||||
private void visitSubclasses(
|
||||
IdentifiableTypeSource source,
|
||||
BinderStepEntityStrategy entityStrategy,
|
||||
BinderLocalBindingContext localContext) {
|
||||
for ( IdentifiableTypeSource subType : source.getSubTypes() ) {
|
||||
if ( EntitySource.class.isInstance( subType ) ) {
|
||||
entityStrategy.visit( (EntitySource) subType, localContext );
|
||||
}
|
||||
visitSubclasses( subType, entityStrategy, localContext );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* 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.
|
||||
|
@ -21,19 +21,44 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.spi.BindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface HelperContext {
|
||||
public interface BinderRootContext extends BindingContext {
|
||||
/**
|
||||
* Locate the binding representation of the hierarchy for the given source
|
||||
* representation.
|
||||
*
|
||||
* @param source The source representation
|
||||
*
|
||||
* @return The binding representation
|
||||
*/
|
||||
public HierarchyDetails locateBinding(EntityHierarchySource source);
|
||||
|
||||
/**
|
||||
* Locate the binding representation of the entity for the given source
|
||||
* representation.
|
||||
*
|
||||
* @param source The source representation
|
||||
*
|
||||
* @return The binding representation
|
||||
*/
|
||||
public EntityBinding locateBinding(EntitySource source);
|
||||
|
||||
public BinderLocalBindingContextSelector getLocalBindingContextSelector();
|
||||
|
||||
HibernateTypeHelper typeHelper();
|
||||
RelationalIdentifierHelper relationalIdentifierHelper();
|
||||
TableHelper tableHelper();
|
||||
ForeignKeyHelper foreignKeyHelper();
|
||||
RelationalValueBindingHelper relationalValueBindingHelper();
|
||||
NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper();
|
||||
LocalBindingContext bindingContext();
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.spi.BaseDelegatingBindingContext;
|
||||
import org.hibernate.metamodel.spi.BindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BinderRootContextImpl extends BaseDelegatingBindingContext implements BinderRootContext {
|
||||
private Map<EntityHierarchySource,HierarchyDetails> hierarchySourceToBindingMap
|
||||
= new HashMap<EntityHierarchySource, HierarchyDetails>();
|
||||
private Map<EntitySource,EntityBinding> entitySourceToBindingMap
|
||||
= new HashMap<EntitySource, EntityBinding>();
|
||||
|
||||
private final HibernateTypeHelper typeHelper; // todo: refactor helper and remove redundant methods in this class
|
||||
private final RelationalIdentifierHelper relationalIdentifierHelper;
|
||||
private final TableHelper tableHelper;
|
||||
private final ForeignKeyHelper foreignKeyHelper;
|
||||
private final RelationalValueBindingHelper relationalValueBindingHelper;
|
||||
private final NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper;
|
||||
|
||||
private final BinderLocalBindingContextSelector localBindingContextSelector;
|
||||
|
||||
public BinderRootContextImpl(BindingContext parent) {
|
||||
super( parent );
|
||||
|
||||
this.typeHelper = new HibernateTypeHelper( this );
|
||||
this.relationalIdentifierHelper = new RelationalIdentifierHelper( this );
|
||||
this.tableHelper = new TableHelper( this );
|
||||
this.foreignKeyHelper = new ForeignKeyHelper( this );
|
||||
this.relationalValueBindingHelper = new RelationalValueBindingHelper( this );
|
||||
this.naturalIdUniqueKeyHelper = new NaturalIdUniqueKeyHelper( this );
|
||||
this.localBindingContextSelector = new BinderLocalBindingContextSelectorImpl( this );
|
||||
}
|
||||
|
||||
public void addMapping(EntityHierarchySource source, HierarchyDetails binding) {
|
||||
hierarchySourceToBindingMap.put( source, binding );
|
||||
}
|
||||
|
||||
public void addMapping(EntitySource source, EntityBinding binding) {
|
||||
entitySourceToBindingMap.put( source, binding );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HierarchyDetails locateBinding(EntityHierarchySource source) {
|
||||
// todo : add missing checks
|
||||
return hierarchySourceToBindingMap.get( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding locateBinding(EntitySource source) {
|
||||
// todo : add missing checks
|
||||
return entitySourceToBindingMap.get( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinderLocalBindingContextSelector getLocalBindingContextSelector() {
|
||||
return localBindingContextSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeHelper typeHelper() {
|
||||
return typeHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationalIdentifierHelper relationalIdentifierHelper() {
|
||||
return relationalIdentifierHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableHelper tableHelper() {
|
||||
return tableHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyHelper foreignKeyHelper() {
|
||||
return foreignKeyHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationalValueBindingHelper relationalValueBindingHelper() {
|
||||
return relationalValueBindingHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() {
|
||||
return naturalIdUniqueKeyHelper;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,13 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.spi.binding;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
/**
|
||||
* Represents an Entity or MappedSuperclass in the binding model
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EntityHierarchyBindingNode {
|
||||
|
||||
public interface BinderStepCombinedStrategy extends BinderStepHierarchyStrategy, BinderStepEntityStrategy {
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
|
||||
/**
|
||||
* The work performed by Binder is done as a series of steps, where each
|
||||
* step performs a iteration on an entity hierarchy and visits the hierarchy and
|
||||
* its entities.
|
||||
* <p/>
|
||||
* This contract defines the visitation of entity objects.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface BinderStepEntityStrategy {
|
||||
public boolean applyToRootEntity();
|
||||
|
||||
public void visit(EntitySource source, BinderLocalBindingContext context);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.internal.binder;
|
||||
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
|
||||
/**
|
||||
* The processes performed by Binder are done as a series of steps, where each
|
||||
* step performs a iteration on an entity hierarchy and visits the hierarchy and
|
||||
* its entities.
|
||||
* <p/>
|
||||
* This contract defines the visitation of the hierarchy object
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface BinderStepHierarchyStrategy {
|
||||
public void visit(EntityHierarchySource source, BinderLocalBindingContext context);
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
|
||||
|
@ -48,7 +48,7 @@ public class CollectionTableNamingStrategyHelper extends TableNamingStrategyHelp
|
|||
|
||||
|
||||
return strategy.collectionTableName(
|
||||
entityBinding.getEntity().getName(),
|
||||
entityBinding.getEntityName(),
|
||||
ownerTableLogicalName,
|
||||
null,
|
||||
null,
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
|
@ -21,15 +21,15 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
|
@ -40,23 +40,15 @@ import org.hibernate.metamodel.spi.relational.Identifier;
|
|||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class ForeignKeyHelper {
|
||||
private static final CoreMessageLogger log = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
ForeignKeyHelper.class.getName()
|
||||
);
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
private final HelperContext helperContext;
|
||||
|
||||
public ForeignKeyHelper(HelperContext helperContext) {
|
||||
public ForeignKeyHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -245,8 +237,8 @@ public class ForeignKeyHelper {
|
|||
return foreignKey;
|
||||
}
|
||||
|
||||
private LocalBindingContext bindingContext() {
|
||||
return helperContext.bindingContext();
|
||||
private BinderLocalBindingContext bindingContext() {
|
||||
return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext();
|
||||
}
|
||||
|
||||
private class JoinColumnResolutionContextImpl implements ForeignKeyContributingSource.JoinColumnResolutionContext {
|
||||
|
@ -332,7 +324,7 @@ public class ForeignKeyHelper {
|
|||
String.format(
|
||||
"Could not resolve named referenced property [%s] against entity [%s]",
|
||||
attributeName,
|
||||
referencedEntityBinding.getEntity().getName()
|
||||
referencedEntityBinding.getEntityName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -341,7 +333,7 @@ public class ForeignKeyHelper {
|
|||
String.format(
|
||||
"Referenced property [%s] against entity [%s] is a plural attribute; it must be a singular attribute.",
|
||||
attributeName,
|
||||
referencedEntityBinding.getEntity().getName()
|
||||
referencedEntityBinding.getEntityName()
|
||||
)
|
||||
);
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
|
@ -41,7 +41,7 @@ public class HashedNameUtil {
|
|||
* They're cached, keyed by name, in multiple locations.
|
||||
*
|
||||
* @param prefix
|
||||
* @param table
|
||||
* @param tableName
|
||||
* @param columnNames
|
||||
* @return String The generated name
|
||||
*/
|
||||
|
@ -64,11 +64,12 @@ public class HashedNameUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper method for {@link #generateName(String, TableSpecification, String...)}.
|
||||
* Helper method for {@link #generateName}
|
||||
*
|
||||
* @param prefix
|
||||
* @param table
|
||||
* @param columns
|
||||
* @param tableName
|
||||
* @param columnNames
|
||||
*
|
||||
* @return String The generated name
|
||||
*/
|
||||
public static String generateName(String prefix, String tableName, List<String> columnNames) {
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.PropertyDescriptor;
|
||||
|
@ -37,12 +37,18 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
|||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
import org.hibernate.metamodel.source.spi.AttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.BasicPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.source.spi.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding;
|
||||
|
@ -64,25 +70,20 @@ import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
|||
import org.hibernate.metamodel.spi.relational.AbstractValue;
|
||||
import org.hibernate.metamodel.spi.relational.JdbcDataType;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tuple.component.ComponentMetamodel;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Delegate for handling:<ol>
|
||||
* <li>
|
||||
* binding of Hibernate type information ({@link org.hibernate.metamodel.spi.source.HibernateTypeSource} ->
|
||||
* binding of Hibernate type information ({@link org.hibernate.metamodel.source.spi.HibernateTypeSource} ->
|
||||
* {@link HibernateTypeDescriptor}
|
||||
* </li>
|
||||
* <li>
|
||||
|
@ -120,11 +121,20 @@ class HibernateTypeHelper {
|
|||
* <li>collection index type</li>
|
||||
* </ul>
|
||||
*/
|
||||
static class ReflectedCollectionJavaTypes {
|
||||
public static class ReflectedCollectionJavaTypes {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final ReflectedCollectionJavaTypes NONE = new ReflectedCollectionJavaTypes();
|
||||
|
||||
private final String collectionTypeName;
|
||||
private final String collectionElementTypeName;
|
||||
private final String collectionIndexTypeName;
|
||||
|
||||
public ReflectedCollectionJavaTypes() {
|
||||
this( null, null, null );
|
||||
}
|
||||
|
||||
private ReflectedCollectionJavaTypes(
|
||||
Class<?> collectionType,
|
||||
Class<?> collectionElementType,
|
||||
|
@ -302,10 +312,10 @@ class HibernateTypeHelper {
|
|||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
//package scope methods
|
||||
HibernateTypeHelper(HelperContext helperContext) {
|
||||
HibernateTypeHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -379,7 +389,7 @@ class HibernateTypeHelper {
|
|||
);
|
||||
bindHibernateTypeDescriptor(
|
||||
attributeBinding.getHibernateTypeDescriptor(),
|
||||
composite.getDescriptor().getName().fullName(),
|
||||
composite.getDescriptor().getName().toString(),
|
||||
null,
|
||||
defaultTypeDescriptor,
|
||||
resolvedType
|
||||
|
@ -410,7 +420,7 @@ class HibernateTypeHelper {
|
|||
final HibernateTypeDescriptor typeDescriptor = syntheticAttributeBinding.getHibernateTypeDescriptor();
|
||||
final String className = syntheticAttribute.getSingularAttributeType().getDescriptor() == null ?
|
||||
null :
|
||||
syntheticAttribute.getSingularAttributeType().getDescriptor().getName().fullName();
|
||||
syntheticAttribute.getSingularAttributeType().getDescriptor().getName().toString();
|
||||
bindHibernateTypeDescriptor(
|
||||
typeDescriptor,
|
||||
className,
|
||||
|
@ -425,7 +435,7 @@ class HibernateTypeHelper {
|
|||
final EntityBinding referencedEntityBinding,
|
||||
final JavaTypeDescriptor defaultElementTypeDescriptor) {
|
||||
final Type resolvedElementType = typeFactory().manyToOne(
|
||||
referencedEntityBinding.getEntity().getName(),
|
||||
referencedEntityBinding.getEntityName(),
|
||||
elementSource.getReferencedEntityAttributeName(),
|
||||
false,
|
||||
false,
|
||||
|
@ -435,7 +445,7 @@ class HibernateTypeHelper {
|
|||
final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor();
|
||||
bindHibernateTypeDescriptor(
|
||||
hibernateTypeDescriptor,
|
||||
referencedEntityBinding.getEntity().getName(),
|
||||
referencedEntityBinding.getEntityName(),
|
||||
null,
|
||||
defaultElementTypeDescriptor,
|
||||
resolvedElementType
|
||||
|
@ -469,7 +479,7 @@ class HibernateTypeHelper {
|
|||
final JavaTypeDescriptor defaultTypeDescriptor;
|
||||
if ( attributeTypeDescriptor != null ) {
|
||||
attributeBinding.getAttribute().resolveType(
|
||||
makeDomainType( attributeTypeDescriptor.getName().fullName() )
|
||||
makeDomainType( attributeTypeDescriptor.getName().toString() )
|
||||
);
|
||||
defaultTypeDescriptor = attributeTypeDescriptor;
|
||||
}
|
||||
|
@ -514,7 +524,7 @@ class HibernateTypeHelper {
|
|||
role,
|
||||
propertyRef,
|
||||
classLoaderService.classForName(
|
||||
pluralAttributeSource.getElementTypeDescriptor().getName().fullName()
|
||||
pluralAttributeSource.getElementTypeDescriptor().getName().toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -565,7 +575,7 @@ class HibernateTypeHelper {
|
|||
final SingularAttribute singularAttribute) {
|
||||
if ( singularAttribute.getSingularAttributeType() != null ) {
|
||||
return getHeuristicType(
|
||||
singularAttribute.getSingularAttributeType().getDescriptor().getName().fullName(),
|
||||
singularAttribute.getSingularAttributeType().getDescriptor().getName().toString(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
@ -771,8 +781,8 @@ class HibernateTypeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private LocalBindingContext bindingContext() {
|
||||
return helperContext.bindingContext();
|
||||
private BinderLocalBindingContext bindingContext() {
|
||||
return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext();
|
||||
}
|
||||
|
||||
private InFlightMetadataCollector metadataCollector() {
|
||||
|
@ -783,15 +793,19 @@ class HibernateTypeHelper {
|
|||
return bindingContext().makeDomainType( name );
|
||||
}
|
||||
|
||||
private org.hibernate.metamodel.spi.domain.Type makeDomainType(Name name) {
|
||||
private org.hibernate.metamodel.spi.domain.Type makeDomainType(DotName name) {
|
||||
return bindingContext().makeDomainType( name );
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private static methods
|
||||
private static String determineTypeName(final HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
return hibernateTypeDescriptor.getExplicitTypeName() != null
|
||||
? hibernateTypeDescriptor.getExplicitTypeName()
|
||||
: hibernateTypeDescriptor.getJavaTypeDescriptor().getName().fullName();
|
||||
if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) {
|
||||
return hibernateTypeDescriptor.getExplicitTypeName();
|
||||
}
|
||||
if ( hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) {
|
||||
return hibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -799,7 +813,7 @@ class HibernateTypeHelper {
|
|||
final AttributeSource attributeSource,
|
||||
final AttributeContainer attributeContainer) {
|
||||
if ( attributeSource.getTypeInformation() != null && attributeSource.getTypeInformation().getJavaType() != null ) {
|
||||
return bindingContext().typeDescriptor( attributeSource.getTypeInformation().getJavaType().getName() );
|
||||
return attributeSource.getTypeInformation().getJavaType();
|
||||
}
|
||||
else if ( attributeContainer.getDescriptor() == null ) {
|
||||
return null;
|
||||
|
@ -818,7 +832,7 @@ class HibernateTypeHelper {
|
|||
// check fields...
|
||||
for ( FieldDescriptor field : containerTypeDescriptor.getDeclaredFields() ) {
|
||||
if ( field.getName().equals( attributeName ) ) {
|
||||
return field.getType();
|
||||
return field.getType().getErasedType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,19 +844,26 @@ class HibernateTypeHelper {
|
|||
for ( MethodDescriptor method : containerTypeDescriptor.getDeclaredMethods() ) {
|
||||
// look for a setter...
|
||||
if ( method.getName().equals( setterName ) ) {
|
||||
if ( method.getParameterTypes().size() == 1 ) {
|
||||
if ( method.getArgumentTypes().size() == 1 ) {
|
||||
// technically the setters could be overloaded. but we'll assume this was it...
|
||||
return method.getParameterTypes().iterator().next();
|
||||
return method.getArgumentTypes().iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
// look for a getter
|
||||
if ( method.getName().equals( getterName ) || method.getName().equals( isGetterName ) ) {
|
||||
return method.getReturnType();
|
||||
return method.getReturnType().getErasedType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ClassDescriptor.class.isInstance( containerTypeDescriptor ) ) {
|
||||
final ClassDescriptor superType = ( (ClassDescriptor) containerTypeDescriptor ).getSuperType();
|
||||
if ( superType != null ) {
|
||||
return determineAttributeType( superType, attributeName );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -864,9 +885,10 @@ class HibernateTypeHelper {
|
|||
return null; // EARLY RETURN
|
||||
}
|
||||
|
||||
final String ownerClassName = attribute.getAttributeContainer().getDescriptor().getName().fullName();
|
||||
final Class ownerClass = classLoaderService.classForName( ownerClassName );
|
||||
|
||||
final String ownerClassName = attribute.getAttributeContainer().getDescriptor().getName().toString();
|
||||
try {
|
||||
final Class ownerClass = classLoaderService.classForName( ownerClassName );
|
||||
PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate(
|
||||
ownerClass,
|
||||
attribute.getName()
|
|
@ -21,10 +21,9 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
|
||||
|
@ -66,9 +65,9 @@ public class ManyToManyCollectionTableNamingStrategyHelper extends TableNamingSt
|
|||
@Override
|
||||
public String determineImplicitName(NamingStrategy strategy) {
|
||||
return strategy.collectionTableName(
|
||||
ownerEntityBinding.getEntity().getName(),
|
||||
ownerEntityBinding.getEntityName(),
|
||||
ownerTableLogicalName,
|
||||
inverseEntityBinding.getEntity().getName(),
|
||||
inverseEntityBinding.getEntityName(),
|
||||
inverseTableLogicalName,
|
||||
propertyName
|
||||
);
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -32,12 +32,12 @@ import org.hibernate.metamodel.spi.relational.UniqueKey;
|
|||
*/
|
||||
public class NaturalIdUniqueKeyHelper {
|
||||
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
private Map<TableSpecification, UniqueKey> naturalIdUniqueKeys
|
||||
= new HashMap<TableSpecification, UniqueKey>();
|
||||
|
||||
public NaturalIdUniqueKeyHelper(HelperContext helperContext) {
|
||||
public NaturalIdUniqueKeyHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class NaturalIdUniqueKeyHelper {
|
|||
}
|
||||
else {
|
||||
// TODO: For now, leave this out of the naming strategy. It has nothing to do with the columns.
|
||||
String keyName = "UK_" + HashedNameUtil.hashedName( table.getLogicalName().getText() + "_NaturalID" );
|
||||
String keyName = "UK_" + HashedNameUtil.hashedName( table.getLogicalName().getText() + "_NaturalID" );
|
||||
uniqueKey = new UniqueKey();
|
||||
uniqueKey.setTable( table );
|
||||
uniqueKey.setName( keyName );
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -32,9 +32,9 @@ import org.hibernate.metamodel.spi.relational.Identifier;
|
|||
*/
|
||||
public class RelationalIdentifierHelper {
|
||||
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
RelationalIdentifierHelper(HelperContext helperContext) {
|
||||
RelationalIdentifierHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,6 @@ public class RelationalIdentifierHelper {
|
|||
}
|
||||
|
||||
private ObjectNameNormalizer getObjectNameNormalizer() {
|
||||
return helperContext.bindingContext().getMetadataCollector().getObjectNameNormalizer();
|
||||
return helperContext.getMetadataCollector().getObjectNameNormalizer();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -30,6 +30,11 @@ import java.util.List;
|
|||
import org.hibernate.TruthValue;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.source.spi.ColumnSource;
|
||||
import org.hibernate.metamodel.source.spi.DerivedValueSource;
|
||||
import org.hibernate.metamodel.source.spi.RelationalValueSource;
|
||||
import org.hibernate.metamodel.source.spi.RelationalValueSourceContainer;
|
||||
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
|
@ -38,20 +43,15 @@ import org.hibernate.metamodel.spi.relational.Column;
|
|||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.ColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.DerivedValueSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class RelationalValueBindingHelper {
|
||||
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
public RelationalValueBindingHelper(HelperContext helperContext) {
|
||||
public RelationalValueBindingHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -92,10 +92,13 @@ public class RelationalValueBindingHelper {
|
|||
final List<Binder.DefaultNamingStrategy> defaultNameStrategies,
|
||||
final boolean forceNonNullable) {
|
||||
final List<RelationalValueBinding> valueBindings = new ArrayList<RelationalValueBinding>();
|
||||
final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = SingularAttributeSource.class.isInstance(
|
||||
valueSourceContainer
|
||||
) ? SingularAttributeSource.class.cast( valueSourceContainer ).getNaturalIdMutability()
|
||||
: SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
|
||||
final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
|
||||
if ( SingularAttributeSource.class.isInstance( valueSourceContainer ) ) {
|
||||
naturalIdMutability = SingularAttributeSource.class.cast( valueSourceContainer ).getNaturalIdMutability();
|
||||
}
|
||||
else {
|
||||
naturalIdMutability = SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
|
||||
}
|
||||
final boolean isNaturalId = naturalIdMutability != SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
|
||||
final boolean isImmutableNaturalId = isNaturalId && ( naturalIdMutability == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE );
|
||||
final boolean reallyForceNonNullable = forceNonNullable ; //|| isNaturalId; todo is a natural id column should be not nullable?
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
|
@ -31,34 +31,39 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.source.spi.AttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.source.spi.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
|
||||
import org.hibernate.metamodel.source.spi.EntitySource;
|
||||
import org.hibernate.metamodel.source.spi.IdentifiableTypeSource;
|
||||
import org.hibernate.metamodel.source.spi.IdentifierSource;
|
||||
import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.SimpleIdentifierSource;
|
||||
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.source.IdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
import org.hibernate.metamodel.spi.source.SimpleIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
* Used to build indexes (x-refs) of various parts of an entity hierarchy and
|
||||
* its attributes.
|
||||
*
|
||||
* @author Gail Badner
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SourceIndex {
|
||||
private static final CoreMessageLogger log = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
SourceIndex.class.getName()
|
||||
);
|
||||
private static final Logger log = CoreLogging.logger( SourceIndex.class );
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
|
||||
private final Map<String, EntitySourceIndex> entitySourceIndexByEntityName = new HashMap<String, EntitySourceIndex>();
|
||||
|
@ -66,18 +71,116 @@ public class SourceIndex {
|
|||
private final Map<AttributeSourceKey, AttributeSourceKey> mappedByAttributeKeysByOwnerAttributeKeys =
|
||||
new HashMap<AttributeSourceKey, AttributeSourceKey>();
|
||||
|
||||
public void indexEntitySource(final RootEntitySource rootEntitySource, final EntitySource entitySource) {
|
||||
String entityName = entitySource.getEntityName();
|
||||
EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, rootEntitySource, entitySource );
|
||||
|
||||
public void indexHierarchy(EntityHierarchySource hierarchy) {
|
||||
final String hierarchyKey = hierarchy.getRoot().getEntityName();
|
||||
final HierarchyInfo hierarchyInfo = new HierarchyInfo( hierarchyKey, hierarchy );
|
||||
indexIdentifierAttributeSources( hierarchy, hierarchyInfo );
|
||||
|
||||
indexIdentifiableTypeSource( hierarchy.getRoot(), hierarchyInfo );
|
||||
}
|
||||
|
||||
private void indexIdentifiableTypeSource(IdentifiableTypeSource identifiableTypeSource, HierarchyInfo hierarchyInfo) {
|
||||
if ( EntitySource.class.isInstance( identifiableTypeSource ) ) {
|
||||
indexEntitySource( (EntitySource) identifiableTypeSource, hierarchyInfo );
|
||||
}
|
||||
|
||||
for ( IdentifiableTypeSource subTypes : identifiableTypeSource.getSubTypes() ) {
|
||||
indexIdentifiableTypeSource( subTypes, hierarchyInfo );
|
||||
}
|
||||
}
|
||||
|
||||
private void indexEntitySource(EntitySource entitySource, HierarchyInfo hierarchyInfo) {
|
||||
final String entityName = entitySource.getEntityName();
|
||||
EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, hierarchyInfo, entitySource );
|
||||
entitySourceIndexByEntityName.put( entityName, entitySourceIndex );
|
||||
log.debugf( "Mapped entity source \"%s\"", entityName );
|
||||
log.debugf( "Indexing entity source [%s]", entityName );
|
||||
indexAttributes( entitySourceIndex );
|
||||
}
|
||||
|
||||
public void resolveAssociationSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
entitySourceIndexByEntityName
|
||||
.get( bindingContextContext.getEntityBinding().getEntityName() )
|
||||
.resolveAttributeSources( bindingContextContext );
|
||||
private void indexIdentifierAttributeSources(EntityHierarchySource entityHierarchySource, HierarchyInfo hierarchyInfo) {
|
||||
final IdentifierSource identifierSource = entityHierarchySource.getIdentifierSource();
|
||||
|
||||
switch ( identifierSource.getNature() ) {
|
||||
case SIMPLE: {
|
||||
final AttributeSource identifierAttributeSource =
|
||||
( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource();
|
||||
indexAttributeSources( hierarchyInfo, EMPTY_STRING, identifierAttributeSource, true );
|
||||
break;
|
||||
}
|
||||
case NON_AGGREGATED_COMPOSITE: {
|
||||
final List<SingularAttributeSource> nonAggregatedAttributeSources =
|
||||
( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier();
|
||||
for ( SingularAttributeSource nonAggregatedAttributeSource : nonAggregatedAttributeSources ) {
|
||||
indexAttributeSources( hierarchyInfo, EMPTY_STRING, nonAggregatedAttributeSource, true );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AGGREGATED_COMPOSITE: {
|
||||
final ComponentAttributeSource aggregatedAttributeSource =
|
||||
( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource();
|
||||
indexAttributeSources( hierarchyInfo, EMPTY_STRING, aggregatedAttributeSource, true );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Unknown type of identifier: [%s]", identifierSource.getNature() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void indexAttributeSources(
|
||||
AttributeIndexingTarget attributeIndexingTarget,
|
||||
String pathBase,
|
||||
AttributeSource attributeSource,
|
||||
boolean isInIdentifier) {
|
||||
final AttributeSourceKey key = new AttributeSourceKey(
|
||||
attributeIndexingTarget.getAttributeSourceKeyBase(),
|
||||
pathBase,
|
||||
attributeSource.getName()
|
||||
);
|
||||
attributeSourcesByKey.put( key, attributeSource );
|
||||
log.debugf( "Indexing attribute source [%s]", key );
|
||||
|
||||
if ( attributeSource.isSingular() ) {
|
||||
attributeIndexingTarget.indexSingularAttributeSource( pathBase, (SingularAttributeSource) attributeSource, isInIdentifier );
|
||||
}
|
||||
else {
|
||||
attributeIndexingTarget.indexPluralAttributeSource( pathBase, (PluralAttributeSource) attributeSource );
|
||||
}
|
||||
|
||||
if ( attributeSource instanceof ComponentAttributeSource ) {
|
||||
for ( AttributeSource subAttributeSource : ( (ComponentAttributeSource) attributeSource ).attributeSources() ) {
|
||||
indexAttributeSources(
|
||||
attributeIndexingTarget,
|
||||
key.attributePath(),
|
||||
subAttributeSource,
|
||||
isInIdentifier
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void indexAttributes(EntitySourceIndex entitySourceIndex) {
|
||||
final String emptyString = "";
|
||||
for ( final AttributeSource attributeSource : entitySourceIndex.entitySource.attributeSources() ) {
|
||||
indexAttributeSources(entitySourceIndex, emptyString, attributeSource, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void resolveAssociationSources(EntitySource source, BinderLocalBindingContext context) {
|
||||
final EntityBinding binding = context.locateBinding( source );
|
||||
entitySourceIndexByEntityName.get( binding.getEntityName() ).resolveAttributeSources( context );
|
||||
}
|
||||
|
||||
public Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
|
@ -99,6 +202,15 @@ public class SourceIndex {
|
|||
return attributeSourcesByKey.get( new AttributeSourceKey( entityName, attributePath ) );
|
||||
}
|
||||
|
||||
public AttributeSource attributeSource(EntityBinding entityBinding, AttributeBinding attributeBinding) {
|
||||
return attributeSourcesByKey.get(
|
||||
new AttributeSourceKey(
|
||||
entityBinding.getEntityName(),
|
||||
attributeBinding.getAttributePath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public AttributeSource locateAttributeSourceOwnedBy(final String entityName, final String attributePath) {
|
||||
AttributeSourceKey ownerKey = new AttributeSourceKey( entityName, attributePath );
|
||||
AttributeSourceKey mappedByKey = mappedByAttributeKeysByOwnerAttributeKeys.get( ownerKey );
|
||||
|
@ -113,72 +225,6 @@ public class SourceIndex {
|
|||
return entitySourceIndexByEntityName.get( entityName );
|
||||
}
|
||||
|
||||
private void indexAttributes(EntitySourceIndex entitySourceIndex) {
|
||||
final String emptyString = "";
|
||||
if ( entitySourceIndex.entitySource instanceof RootEntitySource ) {
|
||||
indexIdentifierAttributeSources( entitySourceIndex );
|
||||
}
|
||||
for ( final AttributeSource attributeSource : entitySourceIndex.entitySource.attributeSources() ) {
|
||||
indexAttributeSources(entitySourceIndex, emptyString, attributeSource, false );
|
||||
}
|
||||
}
|
||||
|
||||
private void indexIdentifierAttributeSources(EntitySourceIndex entitySourceIndex) {
|
||||
RootEntitySource rootEntitySource = (RootEntitySource) entitySourceIndex.entitySource;
|
||||
IdentifierSource identifierSource = rootEntitySource.getIdentifierSource();
|
||||
switch ( identifierSource.getNature() ) {
|
||||
case SIMPLE:
|
||||
final AttributeSource identifierAttributeSource =
|
||||
( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource();
|
||||
indexAttributeSources( entitySourceIndex, EMPTY_STRING, identifierAttributeSource, true );
|
||||
break;
|
||||
case NON_AGGREGATED_COMPOSITE:
|
||||
final List<SingularAttributeSource> nonAggregatedAttributeSources =
|
||||
( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier();
|
||||
for ( SingularAttributeSource nonAggregatedAttributeSource : nonAggregatedAttributeSources ) {
|
||||
indexAttributeSources( entitySourceIndex, EMPTY_STRING, nonAggregatedAttributeSource, true );
|
||||
}
|
||||
break;
|
||||
case AGGREGATED_COMPOSITE:
|
||||
final ComponentAttributeSource aggregatedAttributeSource =
|
||||
( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource();
|
||||
indexAttributeSources( entitySourceIndex, EMPTY_STRING, aggregatedAttributeSource, true );
|
||||
break;
|
||||
default:
|
||||
throw new AssertionFailure(
|
||||
String.format( "Unknown type of identifier: [%s]", identifierSource.getNature() )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void indexAttributeSources(
|
||||
EntitySourceIndex entitySourceIndex,
|
||||
String pathBase,
|
||||
AttributeSource attributeSource,
|
||||
boolean isInIdentifier) {
|
||||
AttributeSourceKey key = new AttributeSourceKey( entitySourceIndex.entitySource.getEntityName(), pathBase, attributeSource.getName() );
|
||||
attributeSourcesByKey.put( key, attributeSource );
|
||||
log.debugf(
|
||||
"Mapped attribute source \"%s\"", key
|
||||
);
|
||||
if ( attributeSource.isSingular() ) {
|
||||
entitySourceIndex.indexSingularAttributeSource( pathBase, (SingularAttributeSource) attributeSource, isInIdentifier );
|
||||
}
|
||||
else {
|
||||
entitySourceIndex.indexPluralAttributeSource( pathBase, (PluralAttributeSource) attributeSource );
|
||||
}
|
||||
if ( attributeSource instanceof ComponentAttributeSource ) {
|
||||
for ( AttributeSource subAttributeSource : ( (ComponentAttributeSource) attributeSource ).attributeSources() ) {
|
||||
indexAttributeSources(
|
||||
entitySourceIndex,
|
||||
key.attributePath(),
|
||||
subAttributeSource,
|
||||
isInIdentifier
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addMappedByAssociationByOwnerAssociation(AttributeSourceKey ownerKey, AttributeSourceKey ownedKey) {
|
||||
mappedByAttributeKeysByOwnerAttributeKeys.put(
|
||||
ownerKey,
|
||||
|
@ -187,8 +233,11 @@ public class SourceIndex {
|
|||
|
||||
}
|
||||
|
||||
public static class AttributeSourceKey {
|
||||
|
||||
/**
|
||||
* Helper class for indexing attribute look ups.
|
||||
*/
|
||||
public static class AttributeSourceKey {
|
||||
private final String entityName;
|
||||
private final String containerPath;
|
||||
private final String attributeName;
|
||||
|
@ -225,9 +274,9 @@ public class SourceIndex {
|
|||
}
|
||||
|
||||
public String attributePath() {
|
||||
return StringHelper.isEmpty( containerPath ) ?
|
||||
attributeName :
|
||||
containerPath + '.' + attributeName;
|
||||
return StringHelper.isEmpty( containerPath )
|
||||
? attributeName
|
||||
: containerPath + '.' + attributeName;
|
||||
}
|
||||
|
||||
public String getAttributePathQualifiedByEntityName() {
|
||||
|
@ -248,19 +297,10 @@ public class SourceIndex {
|
|||
return false;
|
||||
}
|
||||
|
||||
AttributeSourceKey that = (AttributeSourceKey) o;
|
||||
|
||||
if ( !attributeName.equals( that.attributeName ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !containerPath.equals( that.containerPath ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !entityName.equals( that.entityName ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
final AttributeSourceKey that = (AttributeSourceKey) o;
|
||||
return attributeName.equals( that.attributeName )
|
||||
&& containerPath.equals( that.containerPath )
|
||||
&& entityName.equals( that.entityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -272,18 +312,27 @@ public class SourceIndex {
|
|||
}
|
||||
}
|
||||
|
||||
private static class EntitySourceIndex {
|
||||
private final SourceIndex sourceIndex;
|
||||
private final RootEntitySource rootEntitySource;
|
||||
private final EntitySource entitySource;
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
identifierAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
nonMappedBySingularAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
mappedBySingularAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<AttributeSourceKey, SingularAttributeSource> unresolvedSingularAttributeSourcesByKey =
|
||||
new HashMap<AttributeSourceKey, SingularAttributeSource>();
|
||||
private static interface AttributeIndexingTarget {
|
||||
public String getAttributeSourceKeyBase();
|
||||
|
||||
public void indexSingularAttributeSource(
|
||||
String pathBase,
|
||||
SingularAttributeSource attributeSource,
|
||||
boolean isInIdentifier);
|
||||
|
||||
public void indexPluralAttributeSource(String pathBase, PluralAttributeSource attributeSource);
|
||||
}
|
||||
|
||||
private static abstract class AbstractAttributeIndexingTarget implements AttributeIndexingTarget {
|
||||
private final Map<AttributeSourceKey, SingularAttributeSource> unresolvedSingularAttributeSourcesByKey
|
||||
= new HashMap<AttributeSourceKey, SingularAttributeSource>();
|
||||
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> identifierAttributeSourcesByNature
|
||||
= new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> nonMappedBySingularAttributeSourcesByNature
|
||||
= new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> mappedBySingularAttributeSourcesByNature
|
||||
= new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
|
||||
// TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests
|
||||
// depend on the ordering
|
||||
|
@ -293,21 +342,16 @@ public class SourceIndex {
|
|||
private final Map<AttributeSourceKey, PluralAttributeSource> inversePluralAttributeSourcesByKey =
|
||||
new LinkedHashMap<AttributeSourceKey, PluralAttributeSource>();
|
||||
|
||||
private EntitySourceIndex(
|
||||
final SourceIndex sourceIndex,
|
||||
final RootEntitySource rootEntitySource,
|
||||
final EntitySource entitySource) {
|
||||
this.sourceIndex = sourceIndex;
|
||||
this.rootEntitySource = rootEntitySource;
|
||||
this.entitySource = entitySource;
|
||||
protected AttributeSourceKey makeKey(String pathBase, AttributeSource attributeSource) {
|
||||
return new AttributeSourceKey( getAttributeSourceKeyBase(), pathBase, attributeSource.getName() );
|
||||
}
|
||||
|
||||
private void indexSingularAttributeSource(
|
||||
@Override
|
||||
public void indexSingularAttributeSource(
|
||||
String pathBase,
|
||||
SingularAttributeSource attributeSource,
|
||||
boolean isInIdentifier) {
|
||||
final AttributeSourceKey attributeSourceKey =
|
||||
new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() );
|
||||
final AttributeSourceKey attributeSourceKey = makeKey( pathBase, attributeSource );
|
||||
if ( attributeSource.getNature() == null ) {
|
||||
unresolvedSingularAttributeSourcesByKey.put( attributeSourceKey, attributeSource );
|
||||
return;
|
||||
|
@ -324,11 +368,8 @@ public class SourceIndex {
|
|||
else {
|
||||
map = nonMappedBySingularAttributeSourcesByNature;
|
||||
}
|
||||
indexSingularAttributeSource(
|
||||
attributeSourceKey,
|
||||
attributeSource,
|
||||
map
|
||||
);
|
||||
|
||||
indexSingularAttributeSource( attributeSourceKey, attributeSource, map );
|
||||
}
|
||||
|
||||
private static void indexSingularAttributeSource(
|
||||
|
@ -350,7 +391,24 @@ public class SourceIndex {
|
|||
}
|
||||
}
|
||||
|
||||
private Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
|
||||
@Override
|
||||
public void indexPluralAttributeSource(
|
||||
String pathBase,
|
||||
PluralAttributeSource attributeSource) {
|
||||
final AttributeSourceKey key = makeKey( pathBase, attributeSource );
|
||||
final Map<AttributeSourceKey,PluralAttributeSource> map = attributeSource.isInverse()
|
||||
? inversePluralAttributeSourcesByKey
|
||||
: nonInversePluralAttributeSourcesByKey;
|
||||
if ( map.put( key, attributeSource ) != null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Attempt to reindex attribute source for: [%s]", key )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
boolean isMappedBy,
|
||||
SingularAttributeSource.Nature nature) {
|
||||
final Map<AttributeSourceKey, SingularAttributeSource> entries;
|
||||
|
@ -366,37 +424,17 @@ public class SourceIndex {
|
|||
return entries;
|
||||
}
|
||||
|
||||
private void indexPluralAttributeSource(
|
||||
String pathBase,
|
||||
PluralAttributeSource attributeSource) {
|
||||
AttributeSourceKey key =
|
||||
new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() );
|
||||
final Map<AttributeSourceKey,PluralAttributeSource> map =
|
||||
attributeSource.isInverse() ?
|
||||
inversePluralAttributeSourcesByKey :
|
||||
nonInversePluralAttributeSourcesByKey;
|
||||
if ( map.put( key, attributeSource ) != null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Attempt to reindex attribute source for: [%s]",
|
||||
new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<AttributeSourceKey, PluralAttributeSource> getPluralAttributeSources(
|
||||
boolean isInverse) {
|
||||
final Map<AttributeSourceKey,PluralAttributeSource> map =
|
||||
isInverse ?
|
||||
inversePluralAttributeSourcesByKey :
|
||||
nonInversePluralAttributeSourcesByKey;
|
||||
public Map<AttributeSourceKey, PluralAttributeSource> getPluralAttributeSources(boolean isInverse) {
|
||||
final Map<AttributeSourceKey,PluralAttributeSource> map = isInverse
|
||||
? inversePluralAttributeSourcesByKey
|
||||
: nonInversePluralAttributeSourcesByKey;
|
||||
return Collections.unmodifiableMap( map );
|
||||
}
|
||||
|
||||
private void resolveAttributeSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
final AttributeSourceResolutionContext sourceResolutionContext =
|
||||
new AttributeSourceResolutionContextImpl( bindingContextContext );
|
||||
|
||||
public void resolveAttributeSources(BinderLocalBindingContext context) {
|
||||
final AttributeSourceResolutionContext sourceResolutionContext = makeAttributeSourceResolutionContext( context );
|
||||
|
||||
// Resolve plural attributes.
|
||||
for ( PluralAttributeSource pluralAttributeSource : inversePluralAttributeSourcesByKey.values() ) {
|
||||
if ( pluralAttributeSource.getMappedBy() != null ) {
|
||||
|
@ -440,35 +478,122 @@ public class SourceIndex {
|
|||
indexSingularAttributeSource(
|
||||
attributeSourceKey,
|
||||
attributeSource,
|
||||
toOneAttributeSource.isMappedBy() ?
|
||||
mappedBySingularAttributeSourcesByNature :
|
||||
nonMappedBySingularAttributeSourcesByNature
|
||||
toOneAttributeSource.isMappedBy()
|
||||
? mappedBySingularAttributeSourcesByNature
|
||||
: nonMappedBySingularAttributeSourcesByNature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeSourceResolutionContextImpl implements AttributeSourceResolutionContext {
|
||||
private final EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext;
|
||||
protected abstract AttributeSourceResolutionContext makeAttributeSourceResolutionContext(BinderLocalBindingContext context);
|
||||
}
|
||||
|
||||
public AttributeSourceResolutionContextImpl(
|
||||
EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
this.bindingContextContext = bindingContextContext;
|
||||
}
|
||||
private static class HierarchyInfo extends AbstractAttributeIndexingTarget {
|
||||
private final String hierarchyKey;
|
||||
private final EntityHierarchySource hierarchySource;
|
||||
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return bindingContextContext.getRootEntitySource().getIdentifierSource();
|
||||
}
|
||||
private HierarchyInfo(String hierarchyKey, EntityHierarchySource hierarchySource) {
|
||||
this.hierarchyKey = hierarchyKey;
|
||||
this.hierarchySource = hierarchySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String entityName, String attributeName) {
|
||||
return sourceIndex.attributeSource( entityName, attributeName );
|
||||
}
|
||||
@Override
|
||||
public String getAttributeSourceKeyBase() {
|
||||
return hierarchyKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> resolveIdentifierColumns() {
|
||||
return bindingContextContext.getEntityBinding().getPrimaryTable().getPrimaryKey().getColumns();
|
||||
}
|
||||
@Override
|
||||
public void indexPluralAttributeSource(String pathBase, PluralAttributeSource attributeSource) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Identifiers should not contain plural attributes: [%s]",
|
||||
makeKey( pathBase, attributeSource )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<AttributeSourceKey, PluralAttributeSource> getPluralAttributeSources(boolean isInverse) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext(final BinderLocalBindingContext context) {
|
||||
return new AttributeSourceResolutionContext() {
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return hierarchySource.getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String entityName, String attributeName) {
|
||||
throw new UnsupportedOperationException( "Whaaa!?!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> resolveIdentifierColumns() {
|
||||
return context.locateBinding( hierarchySource ).getRootEntityBinding().getPrimaryTable().getPrimaryKey().getColumns();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static class EntitySourceIndex extends AbstractAttributeIndexingTarget {
|
||||
private final SourceIndex sourceIndex;
|
||||
private final HierarchyInfo hierarchyInfo;
|
||||
private final EntitySource entitySource;
|
||||
|
||||
private EntitySourceIndex(
|
||||
final SourceIndex sourceIndex,
|
||||
final HierarchyInfo hierarchyInfo,
|
||||
final EntitySource entitySource) {
|
||||
this.sourceIndex = sourceIndex;
|
||||
this.hierarchyInfo = hierarchyInfo;
|
||||
this.entitySource = entitySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttributeSourceKeyBase() {
|
||||
return entitySource.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
boolean isMappedBy,
|
||||
SingularAttributeSource.Nature nature) {
|
||||
Map<AttributeSourceKey, SingularAttributeSource> values = hierarchyInfo.getSingularAttributeSources( isMappedBy, nature );
|
||||
if ( values == null || values.isEmpty() ) {
|
||||
values = super.getSingularAttributeSources( isMappedBy, nature );
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext(
|
||||
final BinderLocalBindingContext context) {
|
||||
return new AttributeSourceResolutionContext() {
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return entitySource.getHierarchy().getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String entityName, String attributeName) {
|
||||
return sourceIndex.attributeSource( entityName, attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> resolveIdentifierColumns() {
|
||||
return context.locateBinding( entitySource ).getPrimaryTable().getPrimaryKey().getColumns();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DependencyTreeNode {
|
||||
private String dependedOnHierarchyKey;
|
||||
private List<String> dependantHierarchyKeys;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -29,8 +29,14 @@ import java.util.List;
|
|||
import org.hibernate.TruthValue;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.IndexNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.UniqueKeyNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.IndexNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.UniqueKeyNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.source.spi.ColumnSource;
|
||||
import org.hibernate.metamodel.source.spi.InLineViewSource;
|
||||
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
||||
import org.hibernate.metamodel.source.spi.SizeSource;
|
||||
import org.hibernate.metamodel.source.spi.TableSource;
|
||||
import org.hibernate.metamodel.source.spi.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.Index;
|
||||
|
@ -38,13 +44,7 @@ import org.hibernate.metamodel.spi.relational.Schema;
|
|||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
import org.hibernate.metamodel.spi.source.ColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.InLineViewSource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.MappingDefaults;
|
||||
import org.hibernate.metamodel.spi.source.SizeSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -56,9 +56,9 @@ public class TableHelper {
|
|||
TableHelper.class.getName()
|
||||
);
|
||||
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
public TableHelper(HelperContext helperContext) {
|
||||
public TableHelper(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,14 @@ public class TableHelper {
|
|||
String logicTableName = TableNamingStrategyHelper.class.cast( namingStrategyHelper ).getLogicalName(
|
||||
bindingContext().getBuildingOptions().getNamingStrategy()
|
||||
);
|
||||
tableSpec = createTableSpecification( schema, tableName, logicTableName, includedTable );
|
||||
String rowId = isTableSourceNull ? null : TableSource.class.cast( tableSpecSource ).getRowId();
|
||||
tableSpec = createTableSpecification(
|
||||
schema,
|
||||
tableName,
|
||||
logicTableName,
|
||||
includedTable,
|
||||
rowId
|
||||
);
|
||||
}
|
||||
else {
|
||||
final InLineViewSource inLineViewSource = (InLineViewSource) tableSpecSource;
|
||||
|
@ -112,24 +119,28 @@ public class TableHelper {
|
|||
return bindingContext().getMetadataCollector().getDatabase().locateSchema( schemaName );
|
||||
}
|
||||
|
||||
public TableSpecification createTableSpecification(
|
||||
private TableSpecification createTableSpecification(
|
||||
final Schema schema,
|
||||
final String tableName,
|
||||
final String logicTableName,
|
||||
final Table includedTable) {
|
||||
final Table includedTable,
|
||||
String rowId) {
|
||||
final Identifier logicalTableId = createIdentifier( logicTableName );
|
||||
final Identifier physicalTableId = createIdentifier( tableName );
|
||||
final Table table = schema.locateTable( logicalTableId );
|
||||
if ( table != null ) {
|
||||
return table;
|
||||
}
|
||||
TableSpecification tableSpec;
|
||||
Table tableSpec;
|
||||
if ( includedTable == null ) {
|
||||
tableSpec = schema.createTable( logicalTableId, physicalTableId );
|
||||
}
|
||||
else {
|
||||
tableSpec = schema.createDenormalizedTable( logicalTableId, physicalTableId, includedTable );
|
||||
}
|
||||
|
||||
tableSpec.setRowId( rowId );
|
||||
|
||||
return tableSpec;
|
||||
}
|
||||
|
||||
|
@ -268,7 +279,7 @@ public class TableHelper {
|
|||
return helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( explicitName, namingStrategyHelper );
|
||||
}
|
||||
|
||||
private LocalBindingContext bindingContext() {
|
||||
return helperContext.bindingContext();
|
||||
private BinderLocalBindingContext bindingContext() {
|
||||
return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
package org.hibernate.metamodel.internal.binder;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
|
@ -48,8 +48,9 @@ class TableNamingStrategyHelper implements ObjectNameNormalizer.LogicalNamingStr
|
|||
}
|
||||
|
||||
protected String getImplicitTableName() {
|
||||
return StringHelper.isNotEmpty( entityBinding.getJpaEntityName() ) ? entityBinding.getJpaEntityName() : entityBinding
|
||||
.getEntity().getName();
|
||||
return StringHelper.isNotEmpty( entityBinding.getJpaEntityName() )
|
||||
? entityBinding.getJpaEntityName()
|
||||
: entityBinding.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -25,6 +25,9 @@ package org.hibernate.metamodel.internal.resolver;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.source.spi.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
|
@ -32,9 +35,6 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
|||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
|
|
|
@ -28,9 +28,15 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.HelperContext;
|
||||
import org.hibernate.metamodel.internal.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.internal.binder.BinderRootContext;
|
||||
import org.hibernate.metamodel.internal.binder.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.source.spi.AssociationSource;
|
||||
import org.hibernate.metamodel.source.spi.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
@ -44,21 +50,15 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
|||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public class MappedByAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver {
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
public MappedByAssociationRelationalBindingResolverImpl(HelperContext helperContext) {
|
||||
public MappedByAssociationRelationalBindingResolverImpl(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,7 @@ public class MappedByAssociationRelationalBindingResolverImpl implements Associa
|
|||
}
|
||||
|
||||
private LocalBindingContext bindingContext() {
|
||||
return helperContext.bindingContext();
|
||||
return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext();
|
||||
}
|
||||
|
||||
private MappedByAssociationSource getMappedByAssociationSource(AssociationSource associationSource) {
|
||||
|
|
|
@ -30,12 +30,22 @@ import java.util.List;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.Binder;
|
||||
import org.hibernate.metamodel.internal.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.HelperContext;
|
||||
import org.hibernate.metamodel.internal.ManyToManyCollectionTableNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.internal.TableHelper;
|
||||
import org.hibernate.metamodel.internal.binder.Binder;
|
||||
import org.hibernate.metamodel.internal.binder.BinderRootContext;
|
||||
import org.hibernate.metamodel.internal.binder.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.ManyToManyCollectionTableNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.binder.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.internal.binder.TableHelper;
|
||||
import org.hibernate.metamodel.source.spi.AssociationSource;
|
||||
import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.source.spi.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeKeySource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.RelationalValueSourceContainer;
|
||||
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
|
@ -44,25 +54,15 @@ import org.hibernate.metamodel.spi.relational.Column;
|
|||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeKeySource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public class StandardAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver {
|
||||
private final HelperContext helperContext;
|
||||
private final BinderRootContext helperContext;
|
||||
|
||||
public StandardAssociationRelationalBindingResolverImpl(HelperContext helperContext) {
|
||||
public StandardAssociationRelationalBindingResolverImpl(BinderRootContext helperContext) {
|
||||
this.helperContext = helperContext;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ public class StandardAssociationRelationalBindingResolverImpl implements Associa
|
|||
defaultTable,
|
||||
false,
|
||||
attributeSource.getDefaultNamingStrategies(
|
||||
attributeBindingContainer.seekEntityBinding().getEntity().getName(),
|
||||
attributeBindingContainer.seekEntityBinding().getEntityName(),
|
||||
defaultTable.getLogicalName().getText(),
|
||||
referencedAttributeBinding
|
||||
)
|
||||
|
@ -163,7 +163,7 @@ public class StandardAssociationRelationalBindingResolverImpl implements Associa
|
|||
defaultTable,
|
||||
false,
|
||||
attributeSource.getDefaultNamingStrategies(
|
||||
attributeBindingContainer.seekEntityBinding().getEntity().getName(),
|
||||
attributeBindingContainer.seekEntityBinding().getEntityName(),
|
||||
defaultTable.getLogicalName().getText(),
|
||||
referencedAttributeBinding
|
||||
)
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public abstract class AbstractPluralAttributeElementSourceImpl implements AnnotationAttributeSource {
|
||||
private final String path;
|
||||
protected AttributeOverride attributeOverride;
|
||||
protected AssociationOverride associationOverride;
|
||||
|
||||
public AbstractPluralAttributeElementSourceImpl(
|
||||
final PluralAssociationAttribute associationAttribute,
|
||||
final String relativePath) {
|
||||
if ( associationAttribute.getPluralAttributeNature() == PluralAttributeSource.Nature.MAP ) {
|
||||
this.path = relativePath + ".value";
|
||||
}
|
||||
else {
|
||||
this.path = relativePath + ".element";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAttributeOverride(Map<String, AttributeOverride> attributeOverrideMap) {
|
||||
this.attributeOverride = attributeOverrideMap.get( path );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAssociationOverride(Map<String, AssociationOverride> associationOverrideMap) {
|
||||
this.associationOverride = associationOverrideMap.get( path );
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* 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.internal.source.annotations;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.id.EntityIdentifierNature;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
|
||||
import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToolingHintSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource {
|
||||
private final RootEntitySourceImpl rootEntitySource;
|
||||
private final ComponentAttributeSourceImpl componentAttributeSource;
|
||||
|
||||
public AggregatedCompositeIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource) {
|
||||
this.rootEntitySource = rootEntitySource;
|
||||
// the entity class reference should contain one single id attribute...
|
||||
Iterator<MappedAttribute> idAttributes = rootEntitySource.getEntityClass().getIdAttributes().values().iterator();
|
||||
noIdentifierCheck( rootEntitySource, idAttributes );
|
||||
final MappedAttribute idAttribute = idAttributes.next();
|
||||
if ( idAttributes.hasNext() ) {
|
||||
throw rootEntitySource.getLocalBindingContext().makeMappingException(
|
||||
String.format(
|
||||
"Encountered multiple identifier attributes on entity %s",
|
||||
rootEntitySource.getEntityName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final EmbeddableClass embeddableClass = rootEntitySource.getEntityClass().getEmbeddedClasses().get(
|
||||
idAttribute.getName()
|
||||
);
|
||||
if ( embeddableClass == null ) {
|
||||
throw rootEntitySource.getLocalBindingContext().makeMappingException(
|
||||
"Could not locate embedded identifier class metadata"
|
||||
);
|
||||
}
|
||||
|
||||
componentAttributeSource = new ComponentAttributeSourceImpl( embeddableClass, "", embeddableClass.getClassAccessType() );
|
||||
}
|
||||
|
||||
private void noIdentifierCheck(RootEntitySourceImpl rootEntitySource, Iterator<MappedAttribute> idAttributes) {
|
||||
if ( !idAttributes.hasNext() ) {
|
||||
throw rootEntitySource.getLocalBindingContext().makeMappingException(
|
||||
String.format(
|
||||
"Could not locate identifier attributes on entity %s",
|
||||
rootEntitySource.getEntityName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getLookupIdClass() {
|
||||
return rootEntitySource.locateIdClassType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdClassPropertyAccessorName() {
|
||||
return rootEntitySource.determineIdClassAccessStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentAttributeSource getIdentifierAttributeSource() {
|
||||
return componentAttributeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) {
|
||||
// for now, return null. this is that stupid specj bs
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() {
|
||||
// annotations do not currently allow generators to be attached to composite identifiers as a whole
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdentifierNature getNature() {
|
||||
return EntityIdentifierNature.AGGREGATED_COMPOSITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUnsavedValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ToolingHintSource> getToolingHintSources() {
|
||||
// not relevant for annotations
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class BasicPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource {
|
||||
private final PluralAssociationAttribute associationAttribute;
|
||||
private final ConfiguredClass entityClass;
|
||||
private final Nature nature;
|
||||
|
||||
|
||||
|
||||
public BasicPluralAttributeElementSourceImpl(
|
||||
final PluralAssociationAttribute associationAttribute,
|
||||
final ConfiguredClass entityClass,
|
||||
final String relativePath) {
|
||||
super(associationAttribute, relativePath);
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.entityClass = entityClass;
|
||||
this.nature = resolveNature( associationAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeSource getExplicitHibernateTypeSource() {
|
||||
return new HibernateTypeSourceImpl( associationAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
private static Nature resolveNature(PluralAssociationAttribute attribute){
|
||||
switch ( attribute.getNature() ){
|
||||
case ELEMENT_COLLECTION_BASIC:
|
||||
return Nature.BASIC;
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE:
|
||||
return Nature.AGGREGATE;
|
||||
default:
|
||||
throw new AssertionError(
|
||||
"Wrong attribute nature for a element collection attribute: " + attribute.getNature()
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>();
|
||||
if(attributeOverride!=null){
|
||||
attributeOverride.apply( associationAttribute );
|
||||
}
|
||||
if ( !associationAttribute.getColumnValues().isEmpty() ) {
|
||||
for ( Column columnValues : associationAttribute.getColumnValues() ) {
|
||||
valueSources.add( new ColumnSourceImpl( columnValues ) );
|
||||
}
|
||||
}
|
||||
return valueSources;
|
||||
}
|
||||
|
||||
// TODO - these values are also hard coded in the hbm version of this source implementation. Do we really need them? (HF)
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToolingHintSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
/**
|
||||
* Annotation backed implementation of {@code ComponentAttributeSource}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class ComponentAttributeSourceImpl implements ComponentAttributeSource, AnnotationAttributeSource {
|
||||
private final EmbeddableClass embeddableClass;
|
||||
private final JavaTypeDescriptor typeDescriptor;
|
||||
private final String path;
|
||||
private final AccessType classAccessType;
|
||||
private Map<String, AttributeOverride> attributeOverrideMap;
|
||||
private Map<String, AssociationOverride> associationOverrideMap;
|
||||
|
||||
public ComponentAttributeSourceImpl(
|
||||
final EmbeddableClass embeddableClass,
|
||||
final String parentPath,
|
||||
final AccessType classAccessType) {
|
||||
this.embeddableClass = embeddableClass;
|
||||
this.typeDescriptor = getLocalBindingContext().typeDescriptor( embeddableClass.getConfiguredClass().getName() );
|
||||
this.path = StringHelper.isEmpty( parentPath ) ? embeddableClass.getEmbeddedAttributeName() : parentPath + "." + embeddableClass.getEmbeddedAttributeName();
|
||||
this.classAccessType = classAccessType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAssociationOverride(Map<String, AssociationOverride> associationOverrideMap) {
|
||||
this.associationOverrideMap = associationOverrideMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAttributeOverride(Map<String, AttributeOverride> attributeOverrideMap) {
|
||||
this.attributeOverrideMap = attributeOverrideMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.COMPOSITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getTypeDescriptor() {
|
||||
return typeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return embeddableClass.getEmbeddedAttributeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitTuplizerClassName() {
|
||||
return StringHelper.isEmpty( embeddableClass.getCustomTuplizerClass() ) ? embeddableClass.getCustomTuplizer() : embeddableClass
|
||||
.getCustomTuplizerClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyAccessorName() {
|
||||
return classAccessType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalBindingContext getLocalBindingContext() {
|
||||
return embeddableClass.getLocalBindingContext();
|
||||
}
|
||||
|
||||
// private final ValueHolder<List<AttributeSource>> attributeSourcesValue = new ValueHolder<List<AttributeSource>>(
|
||||
// new ValueHolder.DeferredInitializer<List<AttributeSource>>() {
|
||||
// @Override
|
||||
// public List<AttributeSource> initialize() {
|
||||
// List<AttributeSource> attributeList = new ArrayList<AttributeSource>();
|
||||
// for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes().values() ) {
|
||||
// attribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// attributeList.add( new SingularAttributeSourceImpl( attribute ) );
|
||||
// }
|
||||
// for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) {
|
||||
// embeddable.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// attributeList.add(
|
||||
// new ComponentAttributeSourceImpl(
|
||||
// embeddable,
|
||||
// getPath(),
|
||||
// classAccessType
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes().values() ) {
|
||||
// associationAttribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// }
|
||||
// SourceHelper.resolveAssociationAttributes( embeddableClass, attributeList );
|
||||
// return Collections.unmodifiableList( attributeList );
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
@Override
|
||||
public List<AttributeSource> attributeSources() {
|
||||
// return attributeSourcesValue.getValue();
|
||||
return SourceHelper.resolveAttributes( embeddableClass, getPath(), attributeOverrideMap, associationOverrideMap ).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentReferenceAttributeName() {
|
||||
return embeddableClass.getParentReferencingAttributeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ToolingHintSource> getToolingHintSources() {
|
||||
// not relevant for annotations
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableName() {
|
||||
// none, it is defined on the sub-attributes
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
// none, they are defined on the sub-attributes
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeSource getTypeInformation() {
|
||||
// probably need to check for @Target in EmbeddableClass (HF)
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyGeneration getGeneration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
|
||||
return embeddableClass.getNaturalIdMutability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "ComponentAttributeSourceImpl" );
|
||||
sb.append( "{embeddableClass=" ).append( embeddableClass.getConfiguredClass().getSimpleName() );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @authors tag. All rights reserved.
|
||||
* See the copyright.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
* You should have received a copy of the GNU Lesser General Public License,
|
||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.CascadeType;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.CompositePluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.ToolingHintSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class CompositePluralAttributeElementSourceImpl implements CompositePluralAttributeElementSource,AnnotationAttributeSource {
|
||||
private final AssociationAttribute associationAttribute;
|
||||
private final ConfiguredClass entityClass;
|
||||
|
||||
// private final List<AttributeSource> attributeSources
|
||||
// = new ArrayList<AttributeSource>();
|
||||
//
|
||||
private final String parentReferenceAttributeName;
|
||||
private final EmbeddableClass embeddableClass;
|
||||
|
||||
private final String overridePath;
|
||||
|
||||
private Map<String, AttributeOverride> attributeOverrideMap;
|
||||
private Map<String, AssociationOverride> associationOverrideMap;
|
||||
|
||||
public CompositePluralAttributeElementSourceImpl(
|
||||
final PluralAssociationAttribute associationAttribute,
|
||||
final ConfiguredClass rootEntityClass,
|
||||
final String parentPath) {
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.entityClass = rootEntityClass;
|
||||
this.embeddableClass = entityClass
|
||||
.getCollectionEmbeddedClasses()
|
||||
.get( associationAttribute.getName() );
|
||||
|
||||
this.parentReferenceAttributeName = embeddableClass.getParentReferencingAttributeName();
|
||||
if ( associationAttribute.getPluralAttributeNature() == PluralAttributeSource.Nature.MAP ) {
|
||||
this.overridePath = parentPath + ".value";
|
||||
}
|
||||
else {
|
||||
this.overridePath = parentPath + ".element";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAssociationOverride(Map<String, AssociationOverride> associationOverrideMap) {
|
||||
this.associationOverrideMap = associationOverrideMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAttributeOverride(Map<String, AttributeOverride> attributeOverrideMap) {
|
||||
this.attributeOverrideMap = attributeOverrideMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.AGGREGATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttributeSource> attributeSources() {
|
||||
return SourceHelper.resolveAttributes( embeddableClass, overridePath, attributeOverrideMap, associationOverrideMap ).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalBindingContext getLocalBindingContext() {
|
||||
return associationAttribute.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CascadeStyle> getCascadeStyles() {
|
||||
Set<CascadeStyle> cascadeStyles = new HashSet<CascadeStyle>();
|
||||
for ( javax.persistence.CascadeType cascadeType : associationAttribute
|
||||
.getCascadeTypes() ) {
|
||||
cascadeStyles.add( CascadeType.getCascadeType( cascadeType )
|
||||
.toCascadeStyle() );
|
||||
}
|
||||
return cascadeStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ToolingHintSource> getToolingHintSources() {
|
||||
// HBM only
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getTypeDescriptor() {
|
||||
return getLocalBindingContext().typeDescriptor(
|
||||
associationAttribute.getReferencedEntityType()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentReferenceAttributeName() {
|
||||
return parentReferenceAttributeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitTuplizerClassName() {
|
||||
// TODO ?
|
||||
return null;
|
||||
}
|
||||
|
||||
// private void buildAttributeSources() {
|
||||
// // TODO: Duplicates code in ComponentAttributeSourceImpl.
|
||||
// for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes().values() ) {
|
||||
// attribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// attributeSources.add( new SingularAttributeSourceImpl( attribute ) );
|
||||
// }
|
||||
// for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) {
|
||||
// embeddable.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// attributeSources.add(
|
||||
// new ComponentAttributeSourceImpl(
|
||||
// embeddable,
|
||||
// getPath(),
|
||||
// embeddableClass.getClassAccessType()
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes().values() ) {
|
||||
// associationAttribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
|
||||
// }
|
||||
// SourceHelper.resolveAssociationAttributes( embeddableClass, attributeSources );
|
||||
// }
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityHierarchyImpl implements EntityHierarchy {
|
||||
private final RootEntitySource rootEntitySource;
|
||||
private final InheritanceType inheritanceType;
|
||||
|
||||
public EntityHierarchyImpl(RootEntitySource source, InheritanceType inheritanceType) {
|
||||
this.rootEntitySource = source;
|
||||
this.inheritanceType = inheritanceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InheritanceType getHierarchyInheritanceType() {
|
||||
return inheritanceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootEntitySource getRootEntitySource() {
|
||||
return rootEntitySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "EntityHierarchyImpl" );
|
||||
sb.append( "{rootEntitySource=" ).append( rootEntitySource.getEntityName() );
|
||||
sb.append( ", inheritanceType=" ).append( inheritanceType );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.Binder;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.IdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.SimpleIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class IndexedPluralAttributeSourceImpl extends PluralAttributeSourceImpl
|
||||
implements IndexedPluralAttributeSource {
|
||||
private PluralAttributeIndexSource indexSource;
|
||||
private final static EnumSet<MappedAttribute.Nature> VALID_NATURES = EnumSet.of(
|
||||
MappedAttribute.Nature.MANY_TO_MANY,
|
||||
MappedAttribute.Nature.ONE_TO_MANY,
|
||||
MappedAttribute.Nature.ELEMENT_COLLECTION_BASIC,
|
||||
MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE);
|
||||
|
||||
public IndexedPluralAttributeSourceImpl(
|
||||
final PluralAssociationAttribute attribute,
|
||||
final ConfiguredClass entityClass,
|
||||
final String relativePath) {
|
||||
super( attribute, entityClass, relativePath );
|
||||
if ( !VALID_NATURES.contains( attribute.getNature() ) ) {
|
||||
throw new MappingException(
|
||||
"Indexed column could be only mapped on the MANY side",
|
||||
attribute.getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
|
||||
if ( attribute.getPluralAttributeNature() == PluralAttributeSource.Nature.ARRAY
|
||||
&& !attribute.annotations().containsKey( JPADotNames.ORDER_COLUMN ) ) {
|
||||
throw new AnnotationException( "The array attribute '" + attribute.getRole()
|
||||
+ "' must be annotated with @OrderColumn!" );
|
||||
}
|
||||
|
||||
if ( attribute.isSequentiallyIndexed() ) {
|
||||
final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() {
|
||||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.propertyToColumnName( attribute.getName() ) + "_ORDER";
|
||||
}
|
||||
};
|
||||
indexSource = new SequentialPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy );
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY ) ) {
|
||||
// need to wait until the ID or attribute source can be resolved.
|
||||
indexSource = null;
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_CLASS ) ) {
|
||||
// can be anything
|
||||
throw new NotYetImplementedException( "@MapKeyClass is not supported yet." );
|
||||
}
|
||||
//TODO the map attribute may contains both {@code MAP_KEY_COLUMN} and {@code MAP_KEY_CLASS}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_COLUMN ) ) {
|
||||
final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() {
|
||||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.propertyToColumnName( attribute.getName() ) + "_KEY";
|
||||
}
|
||||
};
|
||||
indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy );
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_ENUMERATED ) ) {
|
||||
// basic
|
||||
throw new NotYetImplementedException( "@MapKeyEnumerated is not supported yet." );
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_TEMPORAL ) ) {
|
||||
// basic
|
||||
throw new NotYetImplementedException( "@MapKeyTemporal is not supported yet." );
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMN ) ) {
|
||||
// association
|
||||
throw new NotYetImplementedException( "@MapKeyJoinColumn is not supported yet." );
|
||||
}
|
||||
else if ( attribute.annotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMNS ) ) {
|
||||
// association
|
||||
throw new NotYetImplementedException( "@MapKeyJoinColumns is not supported yet." );
|
||||
}
|
||||
else if ( String.class.equals( attribute.getIndexType() ) || attribute.getIndexType().isPrimitive() ) {
|
||||
final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() {
|
||||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.propertyToColumnName( attribute.getName() ) + "_KEY";
|
||||
}
|
||||
};
|
||||
indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute, defaultNamingStrategy );
|
||||
}
|
||||
else {
|
||||
// either @Embeddable or entity type.
|
||||
|
||||
// composite:
|
||||
// index is @Embeddable
|
||||
// @MapKeyClass is not basic, not entity type
|
||||
|
||||
// association:
|
||||
// MapKeyJoinColumn, MapKeyJoinColumns are present
|
||||
// If the primary key of the referenced entity is not a simple primary key, must have MapKeyJoinColumns.
|
||||
//indexSource = new BasicPluralAttributeIndexSourceImpl( this, attribute );
|
||||
throw new NotYetImplementedException( "Embeddable and entity keys are not supported yet." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext attributeSourceResolutionContext) {
|
||||
if ( indexSource == null ) {
|
||||
if ( pluralAssociationAttribute().annotations().containsKey( JPADotNames.MAP_KEY ) ) {
|
||||
indexSource = resolveMapKeyPluralAttributeIndexSource( attributeSourceResolutionContext );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "caonnot resolve index source." );
|
||||
}
|
||||
}
|
||||
return indexSource;
|
||||
}
|
||||
|
||||
private PluralAttributeIndexSource resolveMapKeyPluralAttributeIndexSource(AttributeSourceResolutionContext attributeSourceResolutionContext) {
|
||||
final AnnotationInstance mapKeyAnnotation =
|
||||
JandexHelper.getSingleAnnotation( pluralAssociationAttribute().annotations(), JPADotNames.MAP_KEY );
|
||||
final String attributeName = JandexHelper.getValue( mapKeyAnnotation, "name", String.class,
|
||||
entityClass.getLocalBindingContext().getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
final PluralAttributeIndexSource innerIndexSource;
|
||||
if ( attributeName == null ) {
|
||||
IdentifierSource identifierSource = attributeSourceResolutionContext.resolveIdentifierSource(
|
||||
pluralAssociationAttribute().getReferencedEntityType()
|
||||
);
|
||||
switch ( identifierSource.getNature() ) {
|
||||
case SIMPLE:
|
||||
innerIndexSource = new BasicPluralAttributeIndexSourceImpl(
|
||||
this,
|
||||
pluralAssociationAttribute(),
|
||||
null,
|
||||
( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource().relationalValueSources() );
|
||||
break;
|
||||
default:
|
||||
throw new NotYetImplementedException( "Only simple IDs are supported for @MapKey" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
AttributeSource attributeSource = attributeSourceResolutionContext.resolveAttributeSource(
|
||||
pluralAssociationAttribute().getReferencedEntityType(),
|
||||
attributeName
|
||||
);
|
||||
if ( ! attributeSource.isSingular() ) {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
"Plural attribute index [%s.%s] is not a singular attribute.",
|
||||
pluralAssociationAttribute().getReferencedEntityType(),
|
||||
attributeName
|
||||
),
|
||||
pluralAssociationAttribute().getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
final SingularAttributeSource mapKeyAttributeSource = (SingularAttributeSource) attributeSource;
|
||||
switch ( mapKeyAttributeSource.getNature() ) {
|
||||
case BASIC:
|
||||
innerIndexSource = new BasicPluralAttributeIndexSourceImpl(
|
||||
this,
|
||||
pluralAssociationAttribute(),
|
||||
null,
|
||||
mapKeyAttributeSource.relationalValueSources() );
|
||||
break;
|
||||
case COMPOSITE:
|
||||
innerIndexSource = new CompositePluralAttributeIndexSourceImpl(
|
||||
pluralAssociationAttribute(),
|
||||
( ( ComponentAttributeSource) attributeSource ).attributeSources(),
|
||||
null
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new NotYetImplementedException( "Only basic plural attribute index sources are supported for @MapKey" );
|
||||
}
|
||||
}
|
||||
return new MapKeyPluralAttributeIndexSourceImpl( pluralAssociationAttribute(), innerIndexSource, attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeIndexSource getIndexSource() {
|
||||
return indexSource;
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.metamodel.spi.source.JpaCallbackSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class JpaCallbackSourceImpl implements JpaCallbackSource {
|
||||
|
||||
private final Map<Class<?>, String> callbacksByType;
|
||||
private final String name;
|
||||
private final boolean isListener;
|
||||
|
||||
public JpaCallbackSourceImpl(String name,
|
||||
Map<Class<?>, String> callbacksByType,
|
||||
boolean isListener) {
|
||||
this.name = name;
|
||||
this.callbacksByType = callbacksByType;
|
||||
this.isListener = isListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCallbackMethod(Class<?> callbackType) {
|
||||
return callbacksByType.get( callbackType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListener() {
|
||||
return isListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "JpaCallbackSourceImpl" );
|
||||
sb.append( "{name='" ).append( name ).append( '\'' );
|
||||
sb.append( ", isListener=" ).append( isListener );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.metamodel.spi.source.ManyToAnyPluralAttributeElementSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ManyToAnyPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAssociationElementSourceImpl implements ManyToAnyPluralAttributeElementSource {
|
||||
|
||||
public ManyToAnyPluralAttributeElementSourceImpl(PluralAttributeSourceImpl pluralAttributeSource, String relativePath) {
|
||||
super( pluralAttributeSource, relativePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.MANY_TO_ANY;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,423 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.FilterSource;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.ToolingHintSource;
|
||||
import org.hibernate.metamodel.spi.source.Orderable;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeKeySource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.Sortable;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class PluralAttributeSourceImpl implements AnnotationAttributeSource, PluralAttributeSource, Orderable, Sortable {
|
||||
|
||||
private final PluralAssociationAttribute associationAttribute;
|
||||
protected final ConfiguredClass entityClass;
|
||||
private final Nature nature;
|
||||
private final HibernateTypeSource typeSource;
|
||||
private final PluralAttributeKeySource keySource;
|
||||
private final FilterSource[] filterSources;
|
||||
private final String attributePath;
|
||||
|
||||
// If it is not the owner side (i.e., mappedBy != null), then the AttributeSource
|
||||
// for the owner is required to determine elementSource.
|
||||
private PluralAttributeElementSource elementSource;
|
||||
private AttributeSource ownerAttributeSource;
|
||||
public PluralAttributeSourceImpl(
|
||||
final PluralAssociationAttribute associationAttribute,
|
||||
final ConfiguredClass entityClass,
|
||||
final String relativePath) {
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.entityClass = entityClass;
|
||||
this.keySource = new PluralAttributeKeySourceImpl( associationAttribute );
|
||||
this.typeSource = new HibernateTypeSourceImpl( associationAttribute );
|
||||
this.nature = associationAttribute.getPluralAttributeNature();
|
||||
this.attributePath = StringHelper.isEmpty( relativePath ) ? associationAttribute.getName() : relativePath + "." + associationAttribute.getName();
|
||||
|
||||
if ( associationAttribute.getMappedBy() == null ) {
|
||||
this.ownerAttributeSource = this;
|
||||
this.elementSource = determineElementSource( this, this, entityClass, attributePath );
|
||||
}
|
||||
this.filterSources = determineFilterSources(associationAttribute);
|
||||
}
|
||||
|
||||
private FilterSource[] determineFilterSources(PluralAssociationAttribute associationAttribute) {
|
||||
AnnotationInstance filtersAnnotation = JandexHelper.getSingleAnnotation(
|
||||
associationAttribute.annotations(),
|
||||
HibernateDotNames.FILTERS
|
||||
);
|
||||
List<FilterSource> filterSourceList = new ArrayList<FilterSource>();
|
||||
if ( filtersAnnotation != null ) {
|
||||
AnnotationInstance[] annotationInstances = filtersAnnotation.value().asNestedArray();
|
||||
for ( AnnotationInstance filterAnnotation : annotationInstances ) {
|
||||
FilterSource filterSource = new FilterSourceImpl( filterAnnotation, entityClass.getLocalBindingContext() );
|
||||
filterSourceList.add( filterSource );
|
||||
}
|
||||
|
||||
}
|
||||
AnnotationInstance filterAnnotation = JandexHelper.getSingleAnnotation(
|
||||
associationAttribute.annotations(),
|
||||
HibernateDotNames.FILTER
|
||||
);
|
||||
if ( filterAnnotation != null ) {
|
||||
FilterSource filterSource = new FilterSourceImpl( filterAnnotation, entityClass.getLocalBindingContext() );
|
||||
filterSourceList.add( filterSource );
|
||||
}
|
||||
if ( filterSourceList.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return filterSourceList.toArray( new FilterSource[filterSourceList.size()] );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeElementSource getElementSource() {
|
||||
if ( elementSource == null ) {
|
||||
throw new IllegalStateException( "elementSource has not been initialized yet." );
|
||||
}
|
||||
return elementSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAssociationOverride(Map<String, AssociationOverride> associationOverrideMap) {
|
||||
if(elementSource != null && elementSource instanceof AnnotationAttributeSource){
|
||||
((AnnotationAttributeSource)elementSource).applyAssociationOverride( associationOverrideMap );
|
||||
}else{
|
||||
//TODO what to do here, store this and apply later ( to the owner side )?
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAttributeOverride(Map<String, AttributeOverride> attributeOverrideMap) {
|
||||
if(elementSource != null && elementSource instanceof AnnotationAttributeSource){
|
||||
((AnnotationAttributeSource)elementSource).applyAttributeOverride( attributeOverrideMap );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterSource[] getFilterSources() {
|
||||
return filterSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return associationAttribute.getBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesJoinTable() {
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
throw new IllegalStateException( "Cannot determine if a join table is used because plural attribute is not the owner." );
|
||||
}
|
||||
// By default, a unidirectional one-to-many (i.e., with mappedBy == null) uses a join table,
|
||||
// unless it has join columns defined.
|
||||
return associationAttribute.getJoinTableAnnotation() != null ||
|
||||
( associationAttribute.getJoinTableAnnotation() == null &&
|
||||
associationAttribute.getJoinColumnValues().size() == 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getElementTypeDescriptor() {
|
||||
// needed for arrays
|
||||
Class<?> attributeType = associationAttribute.getAttributeType();
|
||||
if ( attributeType.isArray() ) {
|
||||
return entityClass.getLocalBindingContext().typeDescriptor( attributeType.getComponentType().getName() );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static PluralAttributeElementSource determineElementSource(
|
||||
AttributeSource ownerAttributeSource,
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
ConfiguredClass entityClass,
|
||||
String relativePath) {
|
||||
if ( ownerAttributeSource == null ) {
|
||||
throw new AssertionFailure( "ownerAssociationSource must be non-null." );
|
||||
}
|
||||
final PluralAssociationAttribute associationAttribute = pluralAttributeSource.pluralAssociationAttribute();
|
||||
switch ( pluralAttributeSource.pluralAssociationAttribute().getNature() ) {
|
||||
case MANY_TO_MANY:
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath,
|
||||
entityClass.getLocalBindingContext() ) :
|
||||
new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
case MANY_TO_ANY:
|
||||
return new ManyToAnyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
case ONE_TO_MANY:
|
||||
boolean usesJoinTable = ownerAttributeSource.isSingular() ?
|
||||
( (ToOneAttributeSource) ownerAttributeSource ).getContainingTableName() != null :
|
||||
( (PluralAttributeSource) ownerAttributeSource ).usesJoinTable();
|
||||
if ( usesJoinTable ) {
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath,
|
||||
entityClass.getLocalBindingContext() ) :
|
||||
new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
}
|
||||
else {
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new OneToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ) :
|
||||
new OneToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
}
|
||||
case ELEMENT_COLLECTION_BASIC:
|
||||
return new BasicPluralAttributeElementSourceImpl( associationAttribute, entityClass, relativePath );
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE: {
|
||||
// TODO: cascadeStyles?
|
||||
return new CompositePluralAttributeElementSourceImpl(
|
||||
associationAttribute, entityClass, relativePath
|
||||
);
|
||||
}
|
||||
}
|
||||
throw new AssertionError( "Unexpected attribute nature for a association:" + associationAttribute.getNature() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeKeySource getKeySource() {
|
||||
return keySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableSpecificationSource getCollectionTableSpecificationSource() {
|
||||
// todo - see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey
|
||||
// todo - needs to cater for @CollectionTable and @JoinTable
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
throw new IllegalStateException( "Cannot get collection table because this association is not the owner." );
|
||||
}
|
||||
final AnnotationInstance joinTableAnnotation = associationAttribute.getJoinTableAnnotation();
|
||||
return joinTableAnnotation == null ? null : new TableSourceImpl( joinTableAnnotation, entityClass.getLocalBindingContext() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCollectionTableComment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCollectionTableCheck() {
|
||||
return associationAttribute.getCheckCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Caching getCaching() {
|
||||
return associationAttribute.getCaching();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomPersisterClassName() {
|
||||
return associationAttribute.getCustomPersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhere() {
|
||||
return associationAttribute.getWhereClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedBy() {
|
||||
return associationAttribute.getMappedBy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInverse() {
|
||||
return getMappedBy() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomLoaderName() {
|
||||
return associationAttribute.getCustomLoaderName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSQL getCustomSqlInsert() {
|
||||
return associationAttribute.getCustomInsert();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSQL getCustomSqlUpdate() {
|
||||
return associationAttribute.getCustomUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSQL getCustomSqlDelete() {
|
||||
return associationAttribute.getCustomDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSQL getCustomSqlDeleteAll() {
|
||||
return associationAttribute.getCustomDeleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return associationAttribute.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeSource getTypeInformation() {
|
||||
return typeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyAccessorName() {
|
||||
return associationAttribute.getAccessType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return associationAttribute.isOptimisticLockable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ToolingHintSource> getToolingHintSources() {
|
||||
// not relevant for annotations
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrder() {
|
||||
return elementSource.getNature() == PluralAttributeElementSource.Nature.MANY_TO_MANY ?
|
||||
null :
|
||||
associationAttribute.getOrderBy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return associationAttribute.isMutable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrdered() {
|
||||
return StringHelper.isNotEmpty( getOrder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComparatorName() {
|
||||
return associationAttribute.getComparatorName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSorted() {
|
||||
return associationAttribute.isSorted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getFetchTiming() {
|
||||
if ( associationAttribute.isExtraLazy() ) {
|
||||
return FetchTiming.EXTRA_LAZY;
|
||||
}
|
||||
else if ( associationAttribute.isLazy() ) {
|
||||
return FetchTiming.DELAYED;
|
||||
}
|
||||
else {
|
||||
return FetchTiming.IMMEDIATE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStyle getFetchStyle() {
|
||||
return associationAttribute.getFetchStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeElementSource resolvePluralAttributeElementSource(
|
||||
AttributeSourceResolutionContext context) {
|
||||
if ( elementSource == null ) {
|
||||
// elementSource has not been initialized, so we need to resolve it using the
|
||||
// association owner.
|
||||
// Get the owner attribute source that maps the opposite side of the association.
|
||||
ownerAttributeSource = context.resolveAttributeSource(
|
||||
associationAttribute.getReferencedEntityType(),
|
||||
associationAttribute.getMappedBy()
|
||||
);
|
||||
// Initialize resolved entitySource.
|
||||
elementSource = determineElementSource( ownerAttributeSource, this, entityClass, "" ); //TODO not sure what relativePath should be here
|
||||
if ( !MappedByAssociationSource.class.isInstance( elementSource ) ) {
|
||||
throw new AssertionFailure( "expected a mappedBy association." );
|
||||
}
|
||||
final AssociationSource ownerAssociationSource;
|
||||
if ( ownerAttributeSource.isSingular() ) {
|
||||
ownerAssociationSource = (ToOneAttributeSource) ownerAttributeSource;
|
||||
}
|
||||
else {
|
||||
final PluralAttributeSource pluralAttributeSource = (PluralAttributeSource) ownerAttributeSource;
|
||||
if ( !AssociationSource.class.isInstance( pluralAttributeSource.getElementSource() ) ) {
|
||||
throw new AssertionFailure( "Owner is not an association." );
|
||||
}
|
||||
ownerAssociationSource = (AssociationSource) pluralAttributeSource.getElementSource();
|
||||
}
|
||||
ownerAssociationSource.addMappedByAssociationSource( (MappedByAssociationSource) elementSource );
|
||||
}
|
||||
return elementSource;
|
||||
}
|
||||
|
||||
protected PluralAssociationAttribute pluralAssociationAttribute() {
|
||||
return associationAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.IdType;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.source.DiscriminatorSource;
|
||||
import org.hibernate.metamodel.spi.source.IdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.MultiTenancySource;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
import org.hibernate.metamodel.spi.source.VersionAttributeSource;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntitySource {
|
||||
private final RootEntityClass rootEntityClass;
|
||||
|
||||
public RootEntitySourceImpl(RootEntityClass entityClass) {
|
||||
super( entityClass );
|
||||
this.rootEntityClass = entityClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierSource getIdentifierSource() {
|
||||
IdType idType = rootEntityClass.getIdType();
|
||||
switch ( idType ) {
|
||||
case SIMPLE: {
|
||||
MappedAttribute attribute = getEntityClass().getIdAttributes().values().iterator().next();
|
||||
return new SimpleIdentifierSourceImpl( this, (BasicAttribute) attribute );
|
||||
}
|
||||
case COMPOSED: {
|
||||
return new NonAggregatedCompositeIdentifierSourceImpl( this );
|
||||
}
|
||||
case EMBEDDED: {
|
||||
return new AggregatedCompositeIdentifierSourceImpl( this );
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Entity [%s] did not define an identifier", getEntityName() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionAttributeSource getVersionAttributeSource() {
|
||||
final EntityClass entityClass = getEntityClass();
|
||||
if ( entityClass.getVersionAttribute() == null ) {
|
||||
return null;
|
||||
}
|
||||
return new VersionAttributeSourceImpl( entityClass.getVersionAttribute() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscriminatorSource getDiscriminatorSource() {
|
||||
DiscriminatorSource discriminatorSource = null;
|
||||
if ( rootEntityClass.needsDiscriminatorColumn() ) {
|
||||
discriminatorSource = new DiscriminatorSourceImpl( rootEntityClass );
|
||||
}
|
||||
return discriminatorSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiTenancySource getMultiTenancySource() {
|
||||
return getEntityClass().hasMultiTenancySourceInformation()
|
||||
? new MutliTenancySourceImpl( getEntityClass() )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMode getEntityMode() {
|
||||
return EntityMode.POJO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return getEntityClass().isMutable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicitPolymorphism() {
|
||||
return getEntityClass().isExplicitPolymorphism();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhere() {
|
||||
return getEntityClass().getWhereClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRowId() {
|
||||
return getEntityClass().getRowId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptimisticLockStyle getOptimisticLockStyle() {
|
||||
return getEntityClass().getOptimisticLockStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Caching getCaching() {
|
||||
return getEntityClass().getCaching();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Caching getNaturalIdCaching() {
|
||||
return getEntityClass().getNaturalIdCaching();
|
||||
}
|
||||
|
||||
Class locateIdClassType() {
|
||||
final RootEntityClass rootEntityClass = (RootEntityClass) getEntityClass();
|
||||
final AnnotationInstance idClassAnnotation = rootEntityClass.getIdClassAnnotation();
|
||||
|
||||
if ( idClassAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getLocalBindingContext().locateClassByName(
|
||||
JandexHelper.getValue(
|
||||
idClassAnnotation,
|
||||
"value",
|
||||
String.class,
|
||||
rootEntityClass.getLocalBindingContext().getBuildingOptions()
|
||||
.getServiceRegistry()
|
||||
.getService( ClassLoaderService.class )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
String determineIdClassAccessStrategy() {
|
||||
return getEntityClass().getClassAccessType().name().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToolingHintSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class SingularAttributeSourceImpl implements SingularAttributeSource, AnnotationAttributeSource {
|
||||
private final MappedAttribute attribute;
|
||||
private final HibernateTypeSource type;
|
||||
private final String attributePath;
|
||||
|
||||
protected AttributeOverride attributeOverride;
|
||||
|
||||
public SingularAttributeSourceImpl(MappedAttribute attribute) {
|
||||
this(attribute, "");
|
||||
}
|
||||
|
||||
public SingularAttributeSourceImpl(MappedAttribute attribute, String parentPath) {
|
||||
this.attribute = attribute;
|
||||
this.type = new HibernateTypeSourceImpl( attribute );
|
||||
this.attributePath = StringHelper.isEmpty( parentPath ) ? attribute.getName() : parentPath + "." + attribute.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAssociationOverride(Map<String, AssociationOverride> associationOverrideMap) {
|
||||
//doing nothing here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAttributeOverride(Map<String, AttributeOverride> attributeOverrideMap) {
|
||||
this.attributeOverride = attributeOverrideMap.get( attributePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernateTypeSource getTypeInformation() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyAccessorName() {
|
||||
return attribute.getAccessType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyGeneration getGeneration() {
|
||||
return attribute.getPropertyGeneration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return attribute.isLazy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
|
||||
return attribute.getNaturalIdMutability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return attribute.isOptimisticLockable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return attribute.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private final ValueHolder<List<RelationalValueSource>> relationalValueSources = new ValueHolder<List<RelationalValueSource>>(
|
||||
new ValueHolder.DeferredInitializer<List<RelationalValueSource>>() {
|
||||
@Override
|
||||
public List<RelationalValueSource> initialize() {
|
||||
List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>();
|
||||
if ( attributeOverride != null ) {
|
||||
attributeOverride.apply( attribute );
|
||||
}
|
||||
boolean hasDefinedColumnSource = !attribute.getColumnValues().isEmpty();
|
||||
if ( hasDefinedColumnSource ) {
|
||||
for ( Column columnValues : attribute.getColumnValues() ) {
|
||||
|
||||
valueSources.add( new ColumnSourceImpl( attribute, columnValues ) );
|
||||
}
|
||||
}
|
||||
else if ( attribute.getFormulaValue() != null ) {
|
||||
valueSources.add( new DerivedValueSourceImpl( attribute.getFormulaValue() ) );
|
||||
}
|
||||
else if ( attribute instanceof BasicAttribute ) {
|
||||
//for column transformer
|
||||
BasicAttribute basicAttribute = BasicAttribute.class.cast( attribute );
|
||||
if ( basicAttribute.getCustomReadFragment() != null && basicAttribute.getCustomWriteFragment() != null ) {
|
||||
|
||||
valueSources.add( new ColumnSourceImpl( attribute, null ) );
|
||||
}
|
||||
}
|
||||
return valueSources;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* very ugly, can we just return the columnSourceImpl anyway?
|
||||
*/
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
return relationalValueSources.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.BASIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ToolingHintSource> getToolingHintSources() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return attribute.isInsertable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
return !attribute.isId() && attribute.isUpdatable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
return !attribute.isId() && attribute.isOptional();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class SourceHelper {
|
||||
|
||||
public static ValueHolder<List<AttributeSource>> resolveAttributes(
|
||||
final ConfiguredClass configuredClass,
|
||||
final String relativePath,
|
||||
final Map<String, AttributeOverride> attributeOverrideMap,
|
||||
final Map<String, AssociationOverride> associationAttributeMap){
|
||||
return new ValueHolder<List<AttributeSource>>(
|
||||
new ValueHolder.DeferredInitializer<List<AttributeSource>>() {
|
||||
@Override
|
||||
public List<AttributeSource> initialize() {
|
||||
List<AttributeSource> attributeList = new ArrayList<AttributeSource>();
|
||||
for ( BasicAttribute attribute : configuredClass.getSimpleAttributes().values() ) {
|
||||
SingularAttributeSourceImpl source = new SingularAttributeSourceImpl( attribute, relativePath );
|
||||
attributeList.add( source );
|
||||
}
|
||||
|
||||
for ( Map.Entry<String, EmbeddableClass> entry : configuredClass.getEmbeddedClasses()
|
||||
.entrySet() ) {
|
||||
final String attributeName = entry.getKey();
|
||||
if ( !configuredClass.isIdAttribute( attributeName ) ) {
|
||||
final EmbeddableClass component = entry.getValue();
|
||||
ComponentAttributeSourceImpl source = new ComponentAttributeSourceImpl(
|
||||
component,
|
||||
relativePath,
|
||||
configuredClass.getClassAccessType()
|
||||
);
|
||||
attributeList.add( source );
|
||||
}
|
||||
}
|
||||
resolveAssociationAttributes( configuredClass, attributeList, relativePath );
|
||||
for ( AttributeSource attributeSource : attributeList ) {
|
||||
if ( attributeSource instanceof AnnotationAttributeSource ) {
|
||||
AnnotationAttributeSource source = (AnnotationAttributeSource) attributeSource;
|
||||
source.applyAssociationOverride(
|
||||
associationAttributeMap != null ? associationAttributeMap : Collections
|
||||
.<String, AssociationOverride>emptyMap()
|
||||
);
|
||||
source.applyAttributeOverride(
|
||||
attributeOverrideMap != null ? attributeOverrideMap : Collections.<String, AttributeOverride>emptyMap()
|
||||
);
|
||||
}
|
||||
}
|
||||
return attributeList;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static ValueHolder<List<AttributeSource>> resolveAttributes(final ConfiguredClass configuredClass, final String relativePath){
|
||||
return resolveAttributes( configuredClass, relativePath, configuredClass.getAttributeOverrideMap(), configuredClass.getAssociationOverrideMap() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind association attributes within {@param configuredClass} to the proper source impl based on its nature.
|
||||
*
|
||||
* @param configuredClass The holder of association attributes.
|
||||
* @param attributeList Attribute source container, can't be <code>null</code>.
|
||||
*/
|
||||
private static void resolveAssociationAttributes(ConfiguredClass configuredClass, List<AttributeSource> attributeList, final String relativePath) {
|
||||
for ( AssociationAttribute associationAttribute : configuredClass.getAssociationAttributes().values() ) {
|
||||
switch ( associationAttribute.getNature() ) {
|
||||
case ONE_TO_ONE:
|
||||
case MANY_TO_ONE: {
|
||||
final SingularAssociationAttribute singularAssociationAttribute =
|
||||
(SingularAssociationAttribute) associationAttribute;
|
||||
final SingularAttributeSource source =
|
||||
associationAttribute.getMappedBy() == null ?
|
||||
new ToOneAttributeSourceImpl( singularAssociationAttribute, relativePath,
|
||||
configuredClass.getLocalBindingContext() ) :
|
||||
new ToOneMappedByAttributeSourceImpl( singularAssociationAttribute, relativePath );
|
||||
attributeList.add( source );
|
||||
break;
|
||||
}
|
||||
case MANY_TO_MANY:
|
||||
case ONE_TO_MANY:
|
||||
case ELEMENT_COLLECTION_BASIC:
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE: {
|
||||
attributeList.add(
|
||||
createPluralAttributeSource(
|
||||
configuredClass,
|
||||
(PluralAssociationAttribute) associationAttribute,
|
||||
relativePath
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new NotYetImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PluralAttributeSource createPluralAttributeSource(
|
||||
ConfiguredClass configuredClass,
|
||||
PluralAssociationAttribute pluralAssociationAttribute,
|
||||
String relativePath) {
|
||||
switch ( pluralAssociationAttribute.getPluralAttributeNature() ) {
|
||||
case BAG: // fall through intentionally
|
||||
case SET: {
|
||||
return new PluralAttributeSourceImpl( pluralAssociationAttribute, configuredClass, relativePath );
|
||||
}
|
||||
case ARRAY: // fall through intentionally
|
||||
case MAP: // fall through intentionally
|
||||
case LIST: {
|
||||
return new IndexedPluralAttributeSourceImpl( pluralAssociationAttribute, configuredClass, relativePath );
|
||||
}
|
||||
case ID_BAG: {
|
||||
throw new NotYetImplementedException(
|
||||
String.format(
|
||||
"%s attributes are not supported yet",
|
||||
pluralAssociationAttribute.getPluralAttributeNature()
|
||||
)
|
||||
);
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Unknown plural attribute nature: %s",
|
||||
pluralAssociationAttribute.getPluralAttributeNature()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.source.TableSource;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
class TableSourceImpl implements TableSource {
|
||||
private final TableInfo tableInfo;
|
||||
private final EntityBindingContext bindingContext;
|
||||
|
||||
TableSourceImpl(AnnotationInstance tableAnnotation, EntityBindingContext bindingContext) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.tableInfo = createTableInfo( tableAnnotation );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitSchemaName() {
|
||||
return tableInfo.getSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitCatalogName() {
|
||||
return tableInfo.getCatalog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitTableName() {
|
||||
return tableInfo.getTableName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TableSourceImpl that = ( TableSourceImpl ) o;
|
||||
|
||||
if ( tableInfo != null ? !tableInfo.equals( that.tableInfo ) : that.tableInfo != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tableInfo != null ? tableInfo.hashCode() : 0;
|
||||
}
|
||||
|
||||
private TableInfo createTableInfo(AnnotationInstance tableAnnotation) {
|
||||
if ( tableAnnotation != null ) {
|
||||
return createPrimaryTableInfo( tableAnnotation );
|
||||
}
|
||||
else {
|
||||
return new TableInfo( null, null, null );
|
||||
}
|
||||
}
|
||||
|
||||
private TableInfo createPrimaryTableInfo(AnnotationInstance tableAnnotation) {
|
||||
final String schemaName = determineSchemaName( tableAnnotation );
|
||||
final String catalogName = determineCatalogName( tableAnnotation );
|
||||
|
||||
final String explicitTableName = tableAnnotation == null
|
||||
? null
|
||||
: JandexHelper.getValue( tableAnnotation, "name", String.class,
|
||||
bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
|
||||
return new TableInfo( schemaName, catalogName, explicitTableName );
|
||||
}
|
||||
|
||||
private String determineSchemaName(AnnotationInstance tableAnnotation) {
|
||||
return tableAnnotation == null
|
||||
? null
|
||||
: JandexHelper.getValue( tableAnnotation, "schema", String.class,
|
||||
bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
private String determineCatalogName(AnnotationInstance tableAnnotation) {
|
||||
return tableAnnotation == null
|
||||
? null
|
||||
: JandexHelper.getValue( tableAnnotation, "catalog", String.class,
|
||||
bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
private static class TableInfo {
|
||||
private final String schema;
|
||||
private final String catalog;
|
||||
private final String tableName;
|
||||
|
||||
private TableInfo(String schema, String catalog, String tableName) {
|
||||
this.schema = schema;
|
||||
this.catalog = catalog;
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public String getCatalog() {
|
||||
return catalog;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TableInfo tableInfo = ( TableInfo ) o;
|
||||
|
||||
if ( catalog != null ? !catalog.equals( tableInfo.catalog ) : tableInfo.catalog != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( schema != null ? !schema.equals( tableInfo.schema ) : tableInfo.schema != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( tableName != null ? !tableName.equals( tableInfo.tableName ) : tableInfo.tableName != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = schema != null ? schema.hashCode() : 0;
|
||||
result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 );
|
||||
result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "TableInfo" );
|
||||
sb.append( "{schema='" ).append( schema ).append( '\'' );
|
||||
sb.append( ", catalog='" ).append( catalog ).append( '\'' );
|
||||
sb.append( ", tableName='" ).append( tableName ).append( '\'' );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,577 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.FetchType;
|
||||
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.source.internal.jandex.MockHelper;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Represents an association attribute.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class AssociationAttribute extends MappedAttribute {
|
||||
private static final CoreMessageLogger coreLogger = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
AssociationAttribute.class.getName()
|
||||
);
|
||||
|
||||
private final boolean ignoreNotFound;
|
||||
private final String referencedEntityType;
|
||||
private final Class<?> referencedAttributeType;
|
||||
private final String mappedBy;
|
||||
private final Set<CascadeType> cascadeTypes;
|
||||
private final Set<org.hibernate.annotations.CascadeType> hibernateCascadeTypes;
|
||||
private final boolean isOptional;
|
||||
private final boolean isLazy;
|
||||
private final boolean isUnWrapProxy;
|
||||
private final boolean isOrphanRemoval;
|
||||
private final FetchStyle fetchStyle;
|
||||
private final boolean mapsId;
|
||||
private final String referencedIdAttributeName;
|
||||
private ArrayList<Column> joinColumnValues = new ArrayList<Column>();
|
||||
private ArrayList<Column> inverseJoinColumnValues = new ArrayList<Column>();
|
||||
private final AnnotationInstance joinTableAnnotation;
|
||||
private AttributeTypeResolver resolver;
|
||||
|
||||
AssociationAttribute(
|
||||
ClassInfo classInfo,
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Class<?> referencedAttributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
super( name, attributeType, attributeNature, accessType, annotations, context );
|
||||
this.ignoreNotFound = determineNotFoundBehavior();
|
||||
|
||||
AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
attributeNature.getAnnotationDotName()
|
||||
);
|
||||
if ( associationAnnotation == null &&
|
||||
( attributeNature == Nature.ELEMENT_COLLECTION_BASIC || attributeNature == Nature.ELEMENT_COLLECTION_EMBEDDABLE ) ) {
|
||||
|
||||
AnnotationTarget target = MockHelper.getTarget(
|
||||
context.getBuildingOptions().getServiceRegistry(),
|
||||
classInfo,
|
||||
name,
|
||||
MockHelper.TargetType.valueOf( accessType.toUpperCase() )
|
||||
);
|
||||
|
||||
|
||||
associationAnnotation = AnnotationInstance.create(
|
||||
attributeNature.getAnnotationDotName(),
|
||||
target,
|
||||
MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY
|
||||
);
|
||||
}
|
||||
|
||||
// using jandex we don't really care which exact type of annotation we are dealing with
|
||||
this.referencedEntityType = determineReferencedEntityType( associationAnnotation, referencedAttributeType );
|
||||
this.referencedAttributeType = referencedAttributeType;
|
||||
this.mappedBy = determineMappedByAttributeName( associationAnnotation );
|
||||
this.isOptional = determineOptionality( associationAnnotation );
|
||||
this.isLazy = determineIsLazy( associationAnnotation );
|
||||
this.isUnWrapProxy = determinIsUnwrapProxy();
|
||||
this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation );
|
||||
this.cascadeTypes = determineCascadeTypes( associationAnnotation );
|
||||
this.hibernateCascadeTypes = determineHibernateCascadeTypes( annotations );
|
||||
|
||||
if ( this.mappedBy == null ) {
|
||||
determineJoinColumnAnnotations( annotations );
|
||||
determineJoinTableAnnotations( annotations, referencedAttributeType );
|
||||
joinColumnValues.trimToSize();
|
||||
inverseJoinColumnValues.trimToSize();
|
||||
this.joinTableAnnotation = determineExplicitJoinTable( annotations );
|
||||
}
|
||||
else {
|
||||
this.joinTableAnnotation = null;
|
||||
}
|
||||
|
||||
this.fetchStyle = determineFetchStyle();
|
||||
this.referencedIdAttributeName = determineMapsId();
|
||||
this.mapsId = referencedIdAttributeName != null;
|
||||
}
|
||||
|
||||
public boolean isIgnoreNotFound() {
|
||||
return ignoreNotFound;
|
||||
}
|
||||
|
||||
public String getReferencedEntityType() {
|
||||
return referencedEntityType;
|
||||
}
|
||||
|
||||
public Class<?> getReferencedAttributeType() {
|
||||
return referencedAttributeType;
|
||||
}
|
||||
|
||||
public String getMappedBy() {
|
||||
return mappedBy;
|
||||
}
|
||||
|
||||
public Set<CascadeType> getCascadeTypes() {
|
||||
return cascadeTypes;
|
||||
}
|
||||
|
||||
public Set<org.hibernate.annotations.CascadeType> getHibernateCascadeTypes() {
|
||||
return hibernateCascadeTypes;
|
||||
}
|
||||
|
||||
public boolean isOrphanRemoval() {
|
||||
return isOrphanRemoval;
|
||||
}
|
||||
|
||||
public FetchStyle getFetchStyle() {
|
||||
return fetchStyle;
|
||||
}
|
||||
|
||||
public String getReferencedIdAttributeName() {
|
||||
return referencedIdAttributeName;
|
||||
}
|
||||
|
||||
public boolean mapsId() {
|
||||
return mapsId;
|
||||
}
|
||||
|
||||
public List<Column> getJoinColumnValues() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join column information because assocation is not owner." );
|
||||
}
|
||||
return joinColumnValues;
|
||||
}
|
||||
|
||||
public List<Column> getInverseJoinColumnValues() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine inverse join column information because assocation is not owner." );
|
||||
}
|
||||
return inverseJoinColumnValues;
|
||||
}
|
||||
|
||||
public AnnotationInstance getJoinTableAnnotation() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because assocation is not owner." );
|
||||
}
|
||||
return joinTableAnnotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeTypeResolver getHibernateTypeResolver() {
|
||||
if ( resolver == null ) {
|
||||
resolver = getDefaultHibernateTypeResolver();
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return isLazy;
|
||||
}
|
||||
|
||||
public boolean isUnWrapProxy() {
|
||||
return isUnWrapProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
return true;
|
||||
}
|
||||
protected boolean hasOptimisticLockAnnotation(){
|
||||
AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.OPTIMISTIC_LOCK
|
||||
);
|
||||
return optimisticLockAnnotation != null;
|
||||
}
|
||||
@Override
|
||||
public boolean isOptimisticLockable() {
|
||||
if(hasOptimisticLockAnnotation()){
|
||||
return super.isOptimisticLockable();
|
||||
} else {
|
||||
Nature nature = getNature();
|
||||
return (nature != Nature.ONE_TO_ONE && nature != Nature.MANY_TO_ONE ) || isInsertable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyGeneration getPropertyGeneration() {
|
||||
return PropertyGeneration.NEVER;
|
||||
}
|
||||
|
||||
protected AttributeTypeResolver getDefaultHibernateTypeResolver() {
|
||||
return new CompositeAttributeTypeResolver(
|
||||
this,
|
||||
HibernateTypeResolver.createAttributeTypeResolver( this )
|
||||
);
|
||||
}
|
||||
|
||||
private boolean determineNotFoundBehavior() {
|
||||
NotFoundAction action = NotFoundAction.EXCEPTION;
|
||||
AnnotationInstance notFoundAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.NOT_FOUND
|
||||
);
|
||||
if ( notFoundAnnotation != null ) {
|
||||
AnnotationValue actionValue = notFoundAnnotation.value( "action" );
|
||||
if ( actionValue != null ) {
|
||||
action = Enum.valueOf( NotFoundAction.class, actionValue.asEnum() );
|
||||
}
|
||||
}
|
||||
|
||||
return NotFoundAction.IGNORE.equals( action );
|
||||
}
|
||||
|
||||
private boolean determinIsUnwrapProxy() {
|
||||
AnnotationInstance lazyToOne = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.LAZY_TO_ONE );
|
||||
if ( lazyToOne != null ) {
|
||||
return JandexHelper.getEnumValue( lazyToOne, "value", LazyToOneOption.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) == LazyToOneOption.NO_PROXY;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean determineOptionality(AnnotationInstance associationAnnotation) {
|
||||
boolean optional = true;
|
||||
|
||||
AnnotationValue optionalValue = associationAnnotation.value( "optional" );
|
||||
if ( optionalValue != null ) {
|
||||
optional = optionalValue.asBoolean();
|
||||
}
|
||||
|
||||
return optional;
|
||||
}
|
||||
|
||||
private boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) {
|
||||
boolean orphanRemoval = false;
|
||||
AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" );
|
||||
if ( orphanRemovalValue != null ) {
|
||||
orphanRemoval = orphanRemovalValue.asBoolean();
|
||||
}
|
||||
return orphanRemoval;
|
||||
}
|
||||
|
||||
protected boolean determineIsLazy(AnnotationInstance associationAnnotation) {
|
||||
FetchType fetchType = JandexHelper.getEnumValue( associationAnnotation, "fetch", FetchType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
boolean lazy = fetchType == FetchType.LAZY;
|
||||
final AnnotationInstance lazyToOneAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.LAZY_TO_ONE
|
||||
);
|
||||
if ( lazyToOneAnnotation != null ) {
|
||||
LazyToOneOption option = JandexHelper.getEnumValue( lazyToOneAnnotation, "value", LazyToOneOption.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
lazy = option != LazyToOneOption.FALSE;
|
||||
}
|
||||
|
||||
if ( associationAnnotation.value( "fetch" ) != null ) {
|
||||
lazy = FetchType.LAZY == fetchType;
|
||||
}
|
||||
final AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.FETCH
|
||||
);
|
||||
if ( fetchAnnotation != null ) {
|
||||
lazy = JandexHelper.getEnumValue( fetchAnnotation, "value", FetchMode.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) != FetchMode.JOIN;
|
||||
}
|
||||
if ( getFetchStyle() != null ) {
|
||||
lazy = getFetchStyle() != FetchStyle.JOIN;
|
||||
}
|
||||
return lazy;
|
||||
}
|
||||
|
||||
private String determineReferencedEntityType(AnnotationInstance associationAnnotation, Class<?> referencedAttributeType) {
|
||||
// use the annotated attribute type as default target type
|
||||
String targetTypeName = null;
|
||||
|
||||
// unless we have an explicit @Target
|
||||
AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.TARGET
|
||||
);
|
||||
if ( targetAnnotation != null ) {
|
||||
targetTypeName = targetAnnotation.value().asClass().name().toString();
|
||||
}
|
||||
|
||||
AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" );
|
||||
if ( targetEntityValue != null ) {
|
||||
targetTypeName = targetEntityValue.asClass().name().toString();
|
||||
}
|
||||
|
||||
if( StringHelper.isEmpty( targetTypeName ) ) {
|
||||
if ( referencedAttributeType != null ) {
|
||||
targetTypeName = referencedAttributeType.getName();
|
||||
}
|
||||
else {
|
||||
throw getContext().makeMappingException( "Can't find the target type for this collection attribute: "+ getRole() );
|
||||
}
|
||||
}
|
||||
|
||||
return targetTypeName;
|
||||
}
|
||||
|
||||
private String determineMappedByAttributeName(AnnotationInstance associationAnnotation) {
|
||||
String mappedBy = null;
|
||||
AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" );
|
||||
if ( mappedByAnnotationValue != null ) {
|
||||
mappedBy = mappedByAnnotationValue.asString();
|
||||
}
|
||||
|
||||
return mappedBy;
|
||||
}
|
||||
|
||||
private Set<CascadeType> determineCascadeTypes(AnnotationInstance associationAnnotation) {
|
||||
Set<CascadeType> cascadeTypes = new HashSet<CascadeType>();
|
||||
AnnotationValue cascadeValue = associationAnnotation.value( "cascade" );
|
||||
if ( cascadeValue != null ) {
|
||||
String[] cascades = cascadeValue.asEnumArray();
|
||||
for ( String s : cascades ) {
|
||||
cascadeTypes.add( Enum.valueOf( CascadeType.class, s ) );
|
||||
}
|
||||
}
|
||||
return cascadeTypes;
|
||||
}
|
||||
|
||||
private Set<org.hibernate.annotations.CascadeType> determineHibernateCascadeTypes(
|
||||
Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
AnnotationInstance cascadeAnnotation = JandexHelper
|
||||
.getSingleAnnotation(
|
||||
annotations, HibernateDotNames.CASCADE );
|
||||
Set<org.hibernate.annotations.CascadeType> cascadeTypes
|
||||
= new HashSet<org.hibernate.annotations.CascadeType>();
|
||||
if ( cascadeAnnotation != null ) {
|
||||
AnnotationValue cascadeValue = cascadeAnnotation.value();
|
||||
if ( cascadeValue != null ) {
|
||||
String[] cascades = cascadeValue.asEnumArray();
|
||||
for ( String s : cascades ) {
|
||||
cascadeTypes.add( Enum.valueOf(
|
||||
org.hibernate.annotations.CascadeType.class, s ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return cascadeTypes;
|
||||
}
|
||||
|
||||
private FetchStyle determineFetchStyle() {
|
||||
AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.FETCH );
|
||||
if ( fetchAnnotation != null ) {
|
||||
org.hibernate.annotations.FetchMode annotationFetchMode = JandexHelper.getEnumValue(
|
||||
fetchAnnotation,
|
||||
"value",
|
||||
org.hibernate.annotations.FetchMode.class,
|
||||
getContext().getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
return EnumConversionHelper.annotationFetchModeToFetchStyle( annotationFetchMode );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String determineMapsId() {
|
||||
AnnotationInstance mapsIdAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.MAPS_ID );
|
||||
if ( mapsIdAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( !( Nature.MANY_TO_ONE.equals( getNature() ) || Nature.MANY_TO_ONE
|
||||
.equals( getNature() ) ) ) {
|
||||
throw new MappingException(
|
||||
"@MapsId can only be specified on a many-to-one or one-to-one associations, property: "+ getRole(),
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
return JandexHelper.getValue( mapsIdAnnotation, "value", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ));
|
||||
}
|
||||
|
||||
private void determineJoinColumnAnnotations(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join column information because association is not the owner." );
|
||||
}
|
||||
|
||||
Collection<AnnotationInstance> joinColumnAnnotations = JandexHelper.getAnnotations(
|
||||
annotations,
|
||||
JPADotNames.JOIN_COLUMN,
|
||||
JPADotNames.JOIN_COLUMNS,
|
||||
true,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
for ( AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) {
|
||||
joinColumnValues.add( new Column( joinColumnAnnotation ) );
|
||||
}
|
||||
|
||||
// @JoinColumn as part of @CollectionTable
|
||||
AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.COLLECTION_TABLE
|
||||
);
|
||||
if ( collectionTableAnnotation != null ) {
|
||||
List<AnnotationInstance> columnsList = Arrays.asList(
|
||||
JandexHelper.getValue( collectionTableAnnotation, "joinColumns", AnnotationInstance[].class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
for ( AnnotationInstance annotation : columnsList ) {
|
||||
joinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void determineJoinTableAnnotations(
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
Class<?> referencedAttributeType ) {
|
||||
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because association is not the owner." );
|
||||
}
|
||||
|
||||
// @JoinColumn as part of @JoinTable
|
||||
AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.JOIN_TABLE
|
||||
);
|
||||
if (joinTableAnnotation != null) {
|
||||
List<AnnotationInstance> columnsList = Arrays.asList(
|
||||
JandexHelper.getValue( joinTableAnnotation, "joinColumns", AnnotationInstance[].class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
List<AnnotationInstance> inverseColumnsList = Arrays.asList(
|
||||
JandexHelper.getValue( joinTableAnnotation, "inverseJoinColumns", AnnotationInstance[].class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
|
||||
for ( AnnotationInstance annotation : columnsList ) {
|
||||
joinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
for ( AnnotationInstance annotation : inverseColumnsList ) {
|
||||
inverseJoinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationInstance determineExplicitJoinTable(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because association is not the owner." );
|
||||
}
|
||||
|
||||
AnnotationInstance annotationInstance = null;
|
||||
AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.COLLECTION_TABLE
|
||||
);
|
||||
|
||||
AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.JOIN_TABLE
|
||||
);
|
||||
|
||||
// sanity checks
|
||||
if ( collectionTableAnnotation != null && joinTableAnnotation != null ) {
|
||||
String msg = coreLogger.collectionTableAndJoinTableUsedTogether(
|
||||
getContext().getOrigin().getName(),
|
||||
getName()
|
||||
);
|
||||
throw new MappingException( msg, getContext().getOrigin() );
|
||||
}
|
||||
|
||||
if ( collectionTableAnnotation != null ) {
|
||||
if ( JandexHelper.getSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION ) == null ) {
|
||||
String msg = coreLogger.collectionTableWithoutElementCollection(
|
||||
getContext().getOrigin().getName(),
|
||||
getName()
|
||||
);
|
||||
throw new MappingException( msg, getContext().getOrigin() );
|
||||
}
|
||||
annotationInstance = collectionTableAnnotation;
|
||||
}
|
||||
|
||||
if ( joinTableAnnotation != null ) {
|
||||
if ( JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ) == null
|
||||
&& JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ) == null
|
||||
&& JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) == null
|
||||
&& JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ) == null) {
|
||||
String msg = coreLogger.joinTableForNonAssociationAttribute(
|
||||
getContext().getOrigin().getName(),
|
||||
getName()
|
||||
);
|
||||
throw new MappingException( msg, getContext().getOrigin() );
|
||||
}
|
||||
annotationInstance = joinTableAnnotation;
|
||||
}
|
||||
|
||||
return annotationInstance;
|
||||
}
|
||||
}
|
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GenerationType;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.SourceType;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.EnumeratedTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.LobTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.TemporalTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Represent a basic attribute (explicitly or implicitly mapped).
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class BasicAttribute extends MappedAttribute {
|
||||
|
||||
/**
|
||||
* The id generator in case this basic attribute represents an simple id. Will be {@code null} in case there
|
||||
* is no explicit id generator or the containing entity does not have a simple id
|
||||
*/
|
||||
private final IdentifierGeneratorDefinition identifierGeneratorDefinition;
|
||||
|
||||
/**
|
||||
* Is this a versioned property (annotated w/ {@code @Version}).
|
||||
*/
|
||||
private final boolean isVersioned;
|
||||
|
||||
|
||||
private final SourceType versionSourceType;
|
||||
|
||||
/**
|
||||
* Is this property lazy loaded (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isLazy = false;
|
||||
|
||||
/**
|
||||
* Is this property optional (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isOptional = true;
|
||||
|
||||
/**
|
||||
* Are this properties generated and when
|
||||
*/
|
||||
private PropertyGeneration propertyGeneration;
|
||||
private boolean isInsertable = true;
|
||||
private boolean isUpdatable = true;
|
||||
|
||||
private final String customWriteFragment;
|
||||
private final String customReadFragment;
|
||||
private AttributeTypeResolver resolver;
|
||||
|
||||
public static BasicAttribute createSimpleAttribute(
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Nature attributeNature,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
String accessType,
|
||||
EntityBindingContext context) {
|
||||
return new BasicAttribute( name, attributeType, attributeNature, accessType, annotations, context );
|
||||
}
|
||||
|
||||
BasicAttribute(String name,
|
||||
Class<?> attributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
super( name, attributeType, attributeNature, accessType, annotations, context );
|
||||
|
||||
AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
|
||||
isVersioned = versionAnnotation != null;
|
||||
|
||||
if ( isVersioned ) {
|
||||
AnnotationInstance sourceAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
HibernateDotNames.SOURCE
|
||||
);
|
||||
this.versionSourceType = sourceAnnotation !=null ?
|
||||
JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) : null;
|
||||
}
|
||||
else {
|
||||
versionSourceType = null;
|
||||
}
|
||||
|
||||
if ( isId() ) {
|
||||
// an id must be unique and cannot be nullable
|
||||
for ( Column columnValue : getColumnValues() ) {
|
||||
columnValue.setNullable( false );
|
||||
}
|
||||
identifierGeneratorDefinition = checkGeneratedValueAnnotation();
|
||||
}
|
||||
else {
|
||||
identifierGeneratorDefinition = null;
|
||||
}
|
||||
|
||||
checkBasicAnnotation();
|
||||
checkGeneratedAnnotation();
|
||||
List<AnnotationInstance> columnTransformerAnnotations = getAllColumnTransformerAnnotations();
|
||||
String[] readWrite = createCustomReadWrite( columnTransformerAnnotations );
|
||||
this.customReadFragment = readWrite[0];
|
||||
this.customWriteFragment = readWrite[1];
|
||||
|
||||
}
|
||||
|
||||
public boolean isVersioned() {
|
||||
return isVersioned;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return isLazy;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
public boolean isInsertable() {
|
||||
return isInsertable;
|
||||
}
|
||||
|
||||
public boolean isUpdatable() {
|
||||
return isUpdatable;
|
||||
}
|
||||
|
||||
public PropertyGeneration getPropertyGeneration() {
|
||||
return propertyGeneration;
|
||||
}
|
||||
|
||||
public String getCustomWriteFragment() {
|
||||
return customWriteFragment;
|
||||
}
|
||||
|
||||
public String getCustomReadFragment() {
|
||||
return customReadFragment;
|
||||
}
|
||||
|
||||
public IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() {
|
||||
return identifierGeneratorDefinition;
|
||||
}
|
||||
|
||||
public SourceType getVersionSourceType() {
|
||||
return versionSourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimisticLockable() {
|
||||
boolean isOptimisticLockable = super.isOptimisticLockable();
|
||||
if ( !isOptimisticLockable ) {
|
||||
if ( isId() || isVersioned() ) {
|
||||
throw new AnnotationException(
|
||||
"@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
|
||||
+ getRole()
|
||||
);
|
||||
}
|
||||
}
|
||||
return isOptimisticLockable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "SimpleAttribute" );
|
||||
sb.append( "{name=" ).append( getRole() );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void checkBasicAnnotation() {
|
||||
AnnotationInstance basicAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.BASIC );
|
||||
if ( basicAnnotation != null ) {
|
||||
FetchType fetchType = FetchType.LAZY;
|
||||
AnnotationValue fetchValue = basicAnnotation.value( "fetch" );
|
||||
if ( fetchValue != null ) {
|
||||
fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() );
|
||||
}
|
||||
this.isLazy = fetchType == FetchType.LAZY;
|
||||
|
||||
AnnotationValue optionalValue = basicAnnotation.value( "optional" );
|
||||
if ( optionalValue != null ) {
|
||||
this.isOptional = optionalValue.asBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - there is more todo for updatable and insertable. Checking the @Generated annotation is only one part (HF)
|
||||
private void checkGeneratedAnnotation() {
|
||||
AnnotationInstance generatedAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.GENERATED
|
||||
);
|
||||
if ( generatedAnnotation != null ) {
|
||||
this.isInsertable = false;
|
||||
|
||||
AnnotationValue generationTimeValue = generatedAnnotation.value();
|
||||
if ( generationTimeValue != null ) {
|
||||
GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() );
|
||||
if ( GenerationTime.ALWAYS.equals( genTime ) ) {
|
||||
this.isUpdatable = false;
|
||||
this.propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( isId() ) {
|
||||
this.isInsertable = true;
|
||||
this.isUpdatable = false;
|
||||
this.propertyGeneration = PropertyGeneration.INSERT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<AnnotationInstance> getAllColumnTransformerAnnotations() {
|
||||
List<AnnotationInstance> allColumnTransformerAnnotations = new ArrayList<AnnotationInstance>();
|
||||
|
||||
// not quite sure about the usefulness of @ColumnTransformers (HF)
|
||||
AnnotationInstance columnTransformersAnnotations = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.COLUMN_TRANSFORMERS
|
||||
);
|
||||
if ( columnTransformersAnnotations != null ) {
|
||||
AnnotationInstance[] annotationInstances = allColumnTransformerAnnotations.get( 0 ).value().asNestedArray();
|
||||
allColumnTransformerAnnotations.addAll( Arrays.asList( annotationInstances ) );
|
||||
}
|
||||
|
||||
AnnotationInstance columnTransformerAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.COLUMN_TRANSFORMER
|
||||
);
|
||||
if ( columnTransformerAnnotation != null ) {
|
||||
allColumnTransformerAnnotations.add( columnTransformerAnnotation );
|
||||
}
|
||||
return allColumnTransformerAnnotations;
|
||||
}
|
||||
|
||||
private String[] createCustomReadWrite(List<AnnotationInstance> columnTransformerAnnotations) {
|
||||
String[] readWrite = new String[2];
|
||||
|
||||
boolean alreadyProcessedForColumn = false;
|
||||
for ( AnnotationInstance annotationInstance : columnTransformerAnnotations ) {
|
||||
String forColumn = annotationInstance.value( "forColumn" ) == null ?
|
||||
null : annotationInstance.value( "forColumn" ).asString();
|
||||
if ( forColumn != null && !isColumnPresentForTransformer( forColumn ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( alreadyProcessedForColumn ) {
|
||||
throw new AnnotationException( "Multiple definition of read/write conditions for column " + getRole() );
|
||||
}
|
||||
|
||||
readWrite[0] = annotationInstance.value( "read" ) == null ?
|
||||
null : annotationInstance.value( "read" ).asString();
|
||||
readWrite[1] = annotationInstance.value( "write" ) == null ?
|
||||
null : annotationInstance.value( "write" ).asString();
|
||||
|
||||
alreadyProcessedForColumn = true;
|
||||
}
|
||||
return readWrite;
|
||||
}
|
||||
|
||||
private boolean isColumnPresentForTransformer(final String forColumn) {
|
||||
assert forColumn != null;
|
||||
List<Column> columns = getColumnValues();
|
||||
for ( final Column column : columns ) {
|
||||
if ( forColumn.equals( column.getName() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return forColumn.equals( getName() );
|
||||
}
|
||||
|
||||
private IdentifierGeneratorDefinition checkGeneratedValueAnnotation() {
|
||||
AnnotationInstance generatedValueAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
JPADotNames.GENERATED_VALUE
|
||||
);
|
||||
if ( generatedValueAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IdentifierGeneratorDefinition generator = null;
|
||||
String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
if ( StringHelper.isNotEmpty( name ) ) {
|
||||
generator = getContext().findIdGenerator( name );
|
||||
if ( generator == null ) {
|
||||
throw new MappingException(
|
||||
String.format( "Unable to find named generator [%s] for %s", name, getRole() ),
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GenerationType genType = JandexHelper.getEnumValue( generatedValueAnnotation, "strategy", GenerationType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName(
|
||||
genType,
|
||||
getContext().getBuildingOptions().isUseNewIdentifierGenerators()
|
||||
);
|
||||
generator = new IdentifierGeneratorDefinition( null, strategy, null );
|
||||
}
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeTypeResolver getHibernateTypeResolver() {
|
||||
if ( resolver == null ) {
|
||||
resolver = getDefaultHibernateTypeResolver();
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
private AttributeTypeResolver getDefaultHibernateTypeResolver() {
|
||||
CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this );
|
||||
resolver.addHibernateTypeResolver( HibernateTypeResolver.createAttributeTypeResolver( this ) );
|
||||
resolver.addHibernateTypeResolver( TemporalTypeResolver.createAttributeTypeResolver( this ) );
|
||||
resolver.addHibernateTypeResolver( LobTypeResolver.createAttributeTypeResolve( this ) );
|
||||
resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createAttributeTypeResolver( this ) );
|
||||
return resolver;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Base class for the different types of mapped attributes
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public abstract class MappedAttribute implements Comparable<MappedAttribute> {
|
||||
/**
|
||||
* Annotations defined on the attribute, keyed against the annotation dot name.
|
||||
*/
|
||||
private final Map<DotName, List<AnnotationInstance>> annotations;
|
||||
|
||||
/**
|
||||
* The property name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The java type of the attribute
|
||||
*/
|
||||
private final Class<?> attributeType;
|
||||
|
||||
/**
|
||||
* The nature of the attribute
|
||||
*/
|
||||
private final Nature attributeNature;
|
||||
|
||||
/**
|
||||
* The access type for this property. At the moment this is either 'field' or 'property', but Hibernate
|
||||
* also allows custom named accessors (see {@link org.hibernate.property.PropertyAccessorFactory}).
|
||||
*/
|
||||
private final String accessType;
|
||||
|
||||
/**
|
||||
* Defines the column values (relational values) for this property. A mapped property can refer to multiple
|
||||
* column values in case of components or join columns etc
|
||||
*/
|
||||
private final List<Column> columnValues = new ArrayList<Column>();
|
||||
|
||||
/**
|
||||
* Is this a formula property ( annotated w/ {@code Formula}).
|
||||
*/
|
||||
private final FormulaValue formulaValue;
|
||||
|
||||
|
||||
/**
|
||||
* Is this property an id property (or part thereof).
|
||||
*/
|
||||
private final boolean isId;
|
||||
|
||||
/**
|
||||
* Is this property a natural id property and what's the mutability it is.
|
||||
*/
|
||||
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
|
||||
|
||||
/**
|
||||
* Whether a change of the property's value triggers a version increment of the entity (in case of optimistic
|
||||
* locking).
|
||||
*/
|
||||
private final boolean isOptimisticLockable;
|
||||
|
||||
/**
|
||||
* Contains the SQL check condition specified via {@link org.hibernate.annotations.Check} or null if no annotation
|
||||
* is specified.
|
||||
*/
|
||||
private final String checkCondition;
|
||||
|
||||
/**
|
||||
* FQN of the attribute.
|
||||
*/
|
||||
private final String role;
|
||||
|
||||
/**
|
||||
* The binding context
|
||||
*/
|
||||
private final EntityBindingContext context;
|
||||
|
||||
MappedAttribute(String name,
|
||||
Class<?> attributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context
|
||||
) {
|
||||
this.context = context;
|
||||
this.annotations = annotations;
|
||||
this.name = name;
|
||||
this.attributeType = attributeType;
|
||||
this.attributeNature = attributeNature;
|
||||
this.accessType = accessType;
|
||||
|
||||
//if this attribute has either @Id or @EmbeddedId, then it is an id attribute
|
||||
AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID );
|
||||
AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.EMBEDDED_ID
|
||||
);
|
||||
this.isId = ( idAnnotation != null || embeddedIdAnnotation != null );
|
||||
|
||||
this.isOptimisticLockable = checkOptimisticLockAnnotation();
|
||||
this.checkCondition = checkCheckAnnotation();
|
||||
this.naturalIdMutability = AnnotationParserHelper.checkNaturalId( annotations );
|
||||
this.role = context.getOrigin().getName() + "#" + name;
|
||||
checkColumnAnnotations( annotations );
|
||||
this.formulaValue = checkFormulaValueAnnotation();
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getRole(){
|
||||
return role;
|
||||
}
|
||||
|
||||
public final Class<?> getAttributeType() {
|
||||
return attributeType;
|
||||
}
|
||||
|
||||
public String getAccessType() {
|
||||
return accessType;
|
||||
}
|
||||
|
||||
public EntityBindingContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public Map<DotName, List<AnnotationInstance>> annotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public List<Column> getColumnValues() {
|
||||
return columnValues;
|
||||
}
|
||||
|
||||
public boolean isId() {
|
||||
return isId;
|
||||
}
|
||||
|
||||
public boolean isOptimisticLockable() {
|
||||
return isOptimisticLockable;
|
||||
}
|
||||
|
||||
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
|
||||
return naturalIdMutability;
|
||||
}
|
||||
|
||||
public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
|
||||
this.naturalIdMutability = naturalIdMutability;
|
||||
}
|
||||
|
||||
public Nature getNature() {
|
||||
return attributeNature;
|
||||
}
|
||||
|
||||
public String getCheckCondition() {
|
||||
return checkCondition;
|
||||
}
|
||||
|
||||
public FormulaValue getFormulaValue() {
|
||||
return formulaValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MappedAttribute mappedProperty) {
|
||||
return name.compareTo( mappedProperty.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "MappedAttribute" );
|
||||
sb.append( "{name='" ).append( getRole() ).append( '\'' );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public abstract AttributeTypeResolver getHibernateTypeResolver();
|
||||
|
||||
public abstract boolean isLazy();
|
||||
|
||||
public abstract boolean isOptional();
|
||||
|
||||
public abstract boolean isInsertable();
|
||||
|
||||
public abstract boolean isUpdatable();
|
||||
|
||||
public abstract PropertyGeneration getPropertyGeneration();
|
||||
|
||||
private boolean checkOptimisticLockAnnotation() {
|
||||
boolean triggersVersionIncrement = true;
|
||||
AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.OPTIMISTIC_LOCK
|
||||
);
|
||||
if ( optimisticLockAnnotation != null ) {
|
||||
boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean();
|
||||
triggersVersionIncrement = !exclude;
|
||||
}
|
||||
return triggersVersionIncrement;
|
||||
}
|
||||
|
||||
private FormulaValue checkFormulaValueAnnotation() {
|
||||
AnnotationInstance formulaAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.FORMULA
|
||||
);
|
||||
if ( formulaAnnotation != null ) {
|
||||
if ( !getColumnValues().isEmpty() ) {
|
||||
throw new AnnotationException( "Can't having both @Formula and @Column on same attribute : " + getRole() );
|
||||
}
|
||||
final String expression = JandexHelper.getValue( formulaAnnotation, "value", String.class,
|
||||
context.getServiceRegistry().getService( ClassLoaderService.class ));
|
||||
if ( StringHelper.isEmpty( expression ) ) {
|
||||
throw new AnnotationException(
|
||||
String.format(
|
||||
"Formula expression defined on %s can't be empty string",
|
||||
getRole()
|
||||
)
|
||||
);
|
||||
}
|
||||
return new FormulaValue( null, expression );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void checkColumnAnnotations(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
// single @Column
|
||||
AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.COLUMN
|
||||
);
|
||||
if ( columnAnnotation != null ) {
|
||||
checkWrongColumnAnnotationLocation();
|
||||
columnValues.add( new Column( columnAnnotation ) );
|
||||
}
|
||||
|
||||
// @org.hibernate.annotations.Columns
|
||||
AnnotationInstance columnsAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
HibernateDotNames.COLUMNS
|
||||
);
|
||||
if ( columnsAnnotation != null ) {
|
||||
checkWrongColumnAnnotationLocation();
|
||||
List<AnnotationInstance> columnsList = Arrays.asList(
|
||||
JandexHelper.getValue( columnsAnnotation, "columns", AnnotationInstance[].class,
|
||||
context.getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
for ( AnnotationInstance annotation : columnsList ) {
|
||||
columnValues.add( new Column( annotation ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWrongColumnAnnotationLocation() {
|
||||
if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) {
|
||||
throw getContext().makeMappingException(
|
||||
"@Column(s) not allowed on a " + getNature() + " property: " + getRole()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private String checkCheckAnnotation() {
|
||||
final AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK );
|
||||
return checkAnnotation != null ? checkAnnotation.value( "constraints" ).toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum defining the type of a mapped attribute.
|
||||
*/
|
||||
public static enum Nature {
|
||||
BASIC( JPADotNames.BASIC ),
|
||||
ONE_TO_ONE( JPADotNames.ONE_TO_ONE ),
|
||||
ONE_TO_MANY( JPADotNames.ONE_TO_MANY ),
|
||||
MANY_TO_ONE( JPADotNames.MANY_TO_ONE ),
|
||||
MANY_TO_MANY( JPADotNames.MANY_TO_MANY ),
|
||||
MANY_TO_ANY( HibernateDotNames.MANY_TO_ANY ),
|
||||
ELEMENT_COLLECTION_BASIC( JPADotNames.ELEMENT_COLLECTION ),
|
||||
ELEMENT_COLLECTION_EMBEDDABLE( JPADotNames.ELEMENT_COLLECTION ),
|
||||
EMBEDDED_ID( JPADotNames.EMBEDDED_ID ),
|
||||
EMBEDDED( JPADotNames.EMBEDDED );
|
||||
|
||||
private final DotName annotationDotName;
|
||||
|
||||
Nature(DotName annotationDotName) {
|
||||
this.annotationDotName = annotationDotName;
|
||||
}
|
||||
|
||||
public DotName getAnnotationDotName() {
|
||||
return annotationDotName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,565 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.persistence.FetchType;
|
||||
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.CompositeAttributeTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.EnumeratedTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.HibernateTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.LobTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.type.TemporalTypeResolver;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Represents an collection (collection, list, set, map) association attribute.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class PluralAssociationAttribute extends AssociationAttribute {
|
||||
private final Class<?> indexType;
|
||||
private final String whereClause;
|
||||
private final String orderBy;
|
||||
private final boolean sorted;
|
||||
private final String comparatorName;
|
||||
private final Caching caching;
|
||||
private final String customPersister;
|
||||
private final String customLoaderName;
|
||||
private final CustomSQL customInsert;
|
||||
private final CustomSQL customUpdate;
|
||||
private final CustomSQL customDelete;
|
||||
private final CustomSQL customDeleteAll;
|
||||
private final ClassInfo entityClassInfo;
|
||||
private final boolean isExtraLazy;
|
||||
private final OnDeleteAction onDeleteAction;
|
||||
private final boolean isSequentiallyIndexed;
|
||||
// Used for the non-owning side of a ManyToMany relationship
|
||||
private String inverseForeignKeyName;
|
||||
private String explicitForeignKeyName;
|
||||
|
||||
private final PluralAttributeSource.Nature pluralAttributeNature;
|
||||
|
||||
private static final EnumSet<PluralAttributeSource.Nature> SHOULD_NOT_HAS_COLLECTION_ID = EnumSet.of( PluralAttributeSource.Nature.SET,
|
||||
PluralAttributeSource.Nature.MAP, PluralAttributeSource.Nature.LIST, PluralAttributeSource.Nature.ARRAY );
|
||||
|
||||
private LazyCollectionOption lazyOption;
|
||||
private final boolean isCollectionIdPresent;
|
||||
private final boolean mutable;
|
||||
private final int batchSize;
|
||||
|
||||
private AttributeTypeResolver elementTypeResolver;
|
||||
private AttributeTypeResolver indexTypeResolver;
|
||||
|
||||
public static PluralAssociationAttribute createPluralAssociationAttribute(
|
||||
ClassInfo entityClassInfo,
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Class<?> indexType,
|
||||
Class<?> referencedAttributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
return new PluralAssociationAttribute(
|
||||
entityClassInfo,
|
||||
name,
|
||||
attributeType,
|
||||
indexType,
|
||||
referencedAttributeType,
|
||||
attributeNature,
|
||||
accessType,
|
||||
annotations,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
public PluralAttributeSource.Nature getPluralAttributeNature() {
|
||||
return pluralAttributeNature;
|
||||
}
|
||||
|
||||
public Class<?> getIndexType() {
|
||||
return indexType;
|
||||
}
|
||||
|
||||
public String getWhereClause() {
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
public String getOrderBy() {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
public String getInverseForeignKeyName() {
|
||||
return inverseForeignKeyName;
|
||||
}
|
||||
public String getExplicitForeignKeyName(){
|
||||
return explicitForeignKeyName;
|
||||
}
|
||||
|
||||
public Caching getCaching() {
|
||||
return caching;
|
||||
}
|
||||
|
||||
public String getCustomPersister() {
|
||||
return customPersister;
|
||||
}
|
||||
|
||||
public String getCustomLoaderName() {
|
||||
return customLoaderName;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomInsert() {
|
||||
return customInsert;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomUpdate() {
|
||||
return customUpdate;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomDelete() {
|
||||
return customDelete;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomDeleteAll() {
|
||||
return customDeleteAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "PluralAssociationAttribute" );
|
||||
sb.append( "{name='" ).append( getName() ).append( '\'' );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
public OnDeleteAction getOnDeleteAction() {
|
||||
return onDeleteAction;
|
||||
}
|
||||
|
||||
public String getComparatorName() {
|
||||
return comparatorName;
|
||||
}
|
||||
|
||||
public boolean isSorted() {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
public boolean isSequentiallyIndexed() {
|
||||
return isSequentiallyIndexed;
|
||||
}
|
||||
|
||||
private PluralAssociationAttribute(
|
||||
final ClassInfo entityClassInfo,
|
||||
final String name,
|
||||
final Class<?> attributeType,
|
||||
final Class<?> indexType,
|
||||
final Class<?> referencedAttributeType,
|
||||
final Nature associationType,
|
||||
final String accessType,
|
||||
final Map<DotName, List<AnnotationInstance>> annotations,
|
||||
final EntityBindingContext context) {
|
||||
super( entityClassInfo, name, attributeType, referencedAttributeType, associationType, accessType, annotations, context );
|
||||
this.entityClassInfo = entityClassInfo;
|
||||
this.indexType = indexType;
|
||||
this.whereClause = determineWereClause();
|
||||
this.orderBy = determineOrderBy();
|
||||
|
||||
final ClassLoaderService cls = context.getServiceRegistry().getService( ClassLoaderService.class );
|
||||
|
||||
// TODO: This is UGLY -- pull into a util and find a better pattern?
|
||||
AnnotationInstance joinTable = JandexHelper.getSingleAnnotation(
|
||||
annotations(), JPADotNames.JOIN_TABLE );
|
||||
AnnotationInstance collectionTable = JandexHelper.getSingleAnnotation(
|
||||
annotations(), JPADotNames.COLLECTION_TABLE );
|
||||
if (joinTable != null) {
|
||||
AnnotationInstance jpaFkAnnotation = JandexHelper.getValue(
|
||||
joinTable, "foreignKey", AnnotationInstance.class, cls );
|
||||
explicitForeignKeyName = jpaFkAnnotation != null
|
||||
? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null;
|
||||
jpaFkAnnotation = JandexHelper.getValue(
|
||||
joinTable, "inverseForeignKey", AnnotationInstance.class, cls );
|
||||
inverseForeignKeyName = jpaFkAnnotation != null
|
||||
? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null;
|
||||
}
|
||||
if (collectionTable != null) {
|
||||
final AnnotationInstance jpaFkAnnotation = JandexHelper.getValue(
|
||||
collectionTable, "foreignKey", AnnotationInstance.class, cls );
|
||||
explicitForeignKeyName = jpaFkAnnotation != null
|
||||
? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null;
|
||||
}
|
||||
|
||||
this.mutable = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.IMMUTABLE ) == null;
|
||||
|
||||
this.caching = determineCachingSettings();
|
||||
this.isExtraLazy = lazyOption == LazyCollectionOption.EXTRA;
|
||||
this.customPersister = determineCustomPersister();
|
||||
this.customLoaderName = determineCustomLoaderName();
|
||||
this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_INSERT, annotations()
|
||||
);
|
||||
this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_UPDATE, annotations()
|
||||
);
|
||||
this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_DELETE, annotations()
|
||||
);
|
||||
this.customDeleteAll = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_DELETE_ALL, annotations()
|
||||
);
|
||||
this.onDeleteAction = determineOnDeleteAction();
|
||||
this.isCollectionIdPresent = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
HibernateDotNames.COLLECTION_ID
|
||||
) != null;
|
||||
final AnnotationInstance sortNaturalAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.SORT_NATURAL );
|
||||
final AnnotationInstance sortComparatorAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.SORT_COMPARATOR );
|
||||
|
||||
if ( sortNaturalAnnotation != null ) {
|
||||
this.sorted = true;
|
||||
this.comparatorName = "natural";
|
||||
}
|
||||
else if ( sortComparatorAnnotation != null ) {
|
||||
this.sorted = true;
|
||||
this.comparatorName = JandexHelper.getValue( sortComparatorAnnotation, "value", String.class, cls );
|
||||
}
|
||||
else {
|
||||
this.sorted = false;
|
||||
this.comparatorName = null;
|
||||
}
|
||||
|
||||
|
||||
AnnotationInstance orderColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ORDER_COLUMN );
|
||||
this.isSequentiallyIndexed = orderColumnAnnotation != null;
|
||||
this.pluralAttributeNature = resolvePluralAttributeNature();
|
||||
|
||||
AnnotationInstance batchAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.BATCH_SIZE );
|
||||
if ( batchAnnotation != null ) {
|
||||
this.batchSize = batchAnnotation.value( "size" ).asInt();
|
||||
}
|
||||
else {
|
||||
this.batchSize = -1;
|
||||
}
|
||||
validateMapping();
|
||||
}
|
||||
|
||||
private void validateMapping() {
|
||||
checkSortedTypeIsSortable();
|
||||
checkIfCollectionIdIsWronglyPlaced();
|
||||
}
|
||||
|
||||
private void checkIfCollectionIdIsWronglyPlaced() {
|
||||
if ( isCollectionIdPresent && SHOULD_NOT_HAS_COLLECTION_ID.contains( pluralAttributeNature ) ) {
|
||||
throw new MappingException(
|
||||
"The Collection type doesn't support @CollectionId annotation: " + getRole(),
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSortedTypeIsSortable() {
|
||||
//shortcut, a little performance improvement of avoiding the class type check
|
||||
if ( pluralAttributeNature == PluralAttributeSource.Nature.MAP
|
||||
|| pluralAttributeNature == PluralAttributeSource.Nature.SET ) {
|
||||
if ( SortedMap.class.isAssignableFrom( getAttributeType() )
|
||||
|| SortedSet.class.isAssignableFrom( getAttributeType() ) ) {
|
||||
if ( !isSorted() ) {
|
||||
throw new MappingException(
|
||||
"A sorted collection has to define @SortNatural or @SortComparator: " + getRole(),
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TODO org.hibernate.cfg.annotations.CollectionBinder#hasToBeSorted
|
||||
private PluralAttributeSource.Nature resolvePluralAttributeNature() {
|
||||
|
||||
if ( Map.class.isAssignableFrom( getAttributeType() ) ) {
|
||||
return PluralAttributeSource.Nature.MAP;
|
||||
}
|
||||
else if ( List.class.isAssignableFrom( getAttributeType() ) ) {
|
||||
if ( isSequentiallyIndexed() ) {
|
||||
return PluralAttributeSource.Nature.LIST;
|
||||
}
|
||||
else if ( isCollectionIdPresent ) {
|
||||
return PluralAttributeSource.Nature.ID_BAG;
|
||||
}
|
||||
else {
|
||||
return PluralAttributeSource.Nature.BAG;
|
||||
}
|
||||
}
|
||||
else if ( Set.class.isAssignableFrom( getAttributeType() ) ) {
|
||||
return PluralAttributeSource.Nature.SET;
|
||||
}
|
||||
else if ( getAttributeType().isArray() ) {
|
||||
return PluralAttributeSource.Nature.ARRAY;
|
||||
}
|
||||
else if ( Collection.class.isAssignableFrom( getAttributeType() ) ) {
|
||||
return isCollectionIdPresent ? PluralAttributeSource.Nature.ID_BAG : PluralAttributeSource.Nature.BAG;
|
||||
}
|
||||
else {
|
||||
return PluralAttributeSource.Nature.BAG;
|
||||
}
|
||||
}
|
||||
|
||||
//todo duplicated with the one in EntityClass
|
||||
private OnDeleteAction determineOnDeleteAction() {
|
||||
final AnnotationInstance onDeleteAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.ON_DELETE
|
||||
);
|
||||
if ( onDeleteAnnotation != null ) {
|
||||
return JandexHelper.getEnumValue( onDeleteAnnotation, "action", OnDeleteAction.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimisticLockable() {
|
||||
return hasOptimisticLockAnnotation() ? super.isOptimisticLockable() : StringHelper.isEmpty( getMappedBy() );
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
private String determineCustomLoaderName() {
|
||||
String loader = null;
|
||||
final AnnotationInstance customLoaderAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(), HibernateDotNames.LOADER
|
||||
);
|
||||
if ( customLoaderAnnotation != null ) {
|
||||
loader = JandexHelper.getValue( customLoaderAnnotation, "namedQuery", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
|
||||
private String determineCustomPersister() {
|
||||
String entityPersisterClass = null;
|
||||
final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(), HibernateDotNames.PERSISTER
|
||||
);
|
||||
if ( persisterAnnotation != null ) {
|
||||
entityPersisterClass = JandexHelper.getValue( persisterAnnotation, "impl", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
return entityPersisterClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean determineIsLazy(AnnotationInstance associationAnnotation) {
|
||||
FetchType fetchType = JandexHelper.getEnumValue( associationAnnotation, "fetch", FetchType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
boolean lazy = fetchType == FetchType.LAZY;
|
||||
final AnnotationInstance lazyCollectionAnnotationInstance = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.LAZY_COLLECTION
|
||||
);
|
||||
if ( lazyCollectionAnnotationInstance != null ) {
|
||||
lazyOption = JandexHelper.getEnumValue(
|
||||
lazyCollectionAnnotationInstance,
|
||||
"value",
|
||||
LazyCollectionOption.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
lazy = !( lazyOption == LazyCollectionOption.FALSE );
|
||||
|
||||
}
|
||||
final AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.FETCH
|
||||
);
|
||||
if ( fetchAnnotation != null && fetchAnnotation.value() != null ) {
|
||||
FetchMode fetchMode = FetchMode.valueOf( fetchAnnotation.value( ).asEnum().toUpperCase() );
|
||||
if ( fetchMode == FetchMode.JOIN ) {
|
||||
lazy = false;
|
||||
}
|
||||
}
|
||||
return lazy;
|
||||
}
|
||||
|
||||
public boolean isExtraLazy() {
|
||||
return isExtraLazy;
|
||||
}
|
||||
|
||||
private String determineWereClause() {
|
||||
String where = null;
|
||||
|
||||
AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.WHERE );
|
||||
if ( whereAnnotation != null ) {
|
||||
where = JandexHelper.getValue( whereAnnotation, "clause", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
private String determineOrderBy() {
|
||||
String orderBy = null;
|
||||
|
||||
AnnotationInstance hibernateOrderByAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.ORDER_BY
|
||||
);
|
||||
|
||||
AnnotationInstance jpaOrderByAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
JPADotNames.ORDER_BY
|
||||
);
|
||||
|
||||
if ( jpaOrderByAnnotation != null && hibernateOrderByAnnotation != null ) {
|
||||
throw new MappingException(
|
||||
"Cannot use sql order by clause (@org.hibernate.annotations.OrderBy) " +
|
||||
"in conjunction with JPA order by clause (@java.persistence.OrderBy) on " + getRole(),
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
|
||||
if ( hibernateOrderByAnnotation != null ) {
|
||||
orderBy = JandexHelper.getValue( hibernateOrderByAnnotation, "clause", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
if ( jpaOrderByAnnotation != null ) {
|
||||
// this could be an empty string according to JPA spec 11.1.38 -
|
||||
// If the ordering element is not specified for an entity association, ordering by the primary key of the
|
||||
// associated entity is assumed
|
||||
// The binder will need to take this into account and generate the right property names
|
||||
orderBy = JandexHelper.getValue( jpaOrderByAnnotation, "value", String.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
if ( orderBy == null ) {
|
||||
orderBy = isBasicCollection() ? "$element$ asc" :"id asc" ;
|
||||
}
|
||||
if ( orderBy.equalsIgnoreCase( "desc" ) ) {
|
||||
orderBy = isBasicCollection() ? "$element$ desc" :"id desc";
|
||||
}
|
||||
}
|
||||
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
private boolean isBasicCollection(){
|
||||
return getNature() == Nature.ELEMENT_COLLECTION_BASIC || getNature() == Nature.ELEMENT_COLLECTION_EMBEDDABLE;
|
||||
}
|
||||
|
||||
private Caching determineCachingSettings() {
|
||||
Caching caching = null;
|
||||
final AnnotationInstance hibernateCacheAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations(),
|
||||
HibernateDotNames.CACHE
|
||||
);
|
||||
if ( hibernateCacheAnnotation != null ) {
|
||||
org.hibernate.cache.spi.access.AccessType accessType;
|
||||
if ( hibernateCacheAnnotation.value( "usage" ) == null ) {
|
||||
accessType = getContext().getMappingDefaults().getCacheAccessType();
|
||||
}
|
||||
else {
|
||||
accessType = CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() )
|
||||
.toAccessType();
|
||||
}
|
||||
|
||||
return new Caching(
|
||||
hibernateCacheAnnotation.value( "region" ) == null
|
||||
? StringHelper.qualify( entityClassInfo.name().toString(), getName() )
|
||||
: hibernateCacheAnnotation.value( "region" ).asString(),
|
||||
accessType,
|
||||
hibernateCacheAnnotation.value( "include" ) != null
|
||||
&& "all".equals( hibernateCacheAnnotation.value( "include" ).asString() )
|
||||
);
|
||||
}
|
||||
return caching;
|
||||
}
|
||||
|
||||
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeTypeResolver getHibernateTypeResolver() {
|
||||
if ( elementTypeResolver == null ) {
|
||||
elementTypeResolver = getDefaultElementHibernateTypeResolver();
|
||||
}
|
||||
return elementTypeResolver;
|
||||
}
|
||||
|
||||
private AttributeTypeResolver getDefaultElementHibernateTypeResolver() {
|
||||
CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this );
|
||||
resolver.addHibernateTypeResolver( HibernateTypeResolver.createCollectionElementTypeResolver( this ) );
|
||||
resolver.addHibernateTypeResolver( TemporalTypeResolver.createCollectionElementTypeResolver( this ) );
|
||||
resolver.addHibernateTypeResolver( LobTypeResolver.createCollectionElementTypeResolve( this ) );
|
||||
resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createCollectionElementTypeResolver( this ) );
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public AttributeTypeResolver getIndexTypeResolver() {
|
||||
if ( indexType == null ) {
|
||||
return getDefaultHibernateTypeResolver();
|
||||
}
|
||||
else if ( indexTypeResolver == null ) {
|
||||
CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this );
|
||||
final String name = getName() + ".index";
|
||||
resolver.addHibernateTypeResolver( HibernateTypeResolver.createCollectionIndexTypeResolver( this ) );
|
||||
// TODO: Lob allowed as collection index? I don't see an annotation for that.
|
||||
resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createCollectionIndexTypeResolver( this ) );
|
||||
resolver.addHibernateTypeResolver( TemporalTypeResolver.createCollectionIndexTypeResolver( this ) );
|
||||
indexTypeResolver = resolver;
|
||||
}
|
||||
return indexTypeResolver;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class SingularAssociationAttribute extends AssociationAttribute {
|
||||
private final boolean hasPrimaryKeyJoinColumn;
|
||||
public static AssociationAttribute createSingularAssociationAttribute(
|
||||
ClassInfo classInfo,
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
return new SingularAssociationAttribute(
|
||||
classInfo,
|
||||
name,
|
||||
attributeType,
|
||||
attributeType,
|
||||
attributeNature,
|
||||
accessType,
|
||||
annotations,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
SingularAssociationAttribute(
|
||||
ClassInfo classInfo,
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Class<?> referencedAttributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
super( classInfo, name, attributeType, referencedAttributeType, attributeNature, accessType, annotations, context );
|
||||
this.hasPrimaryKeyJoinColumn =
|
||||
JandexHelper.containsSingleAnnotation( annotations, JPADotNames.PRIMARY_KEY_JOIN_COLUMN ) ||
|
||||
JandexHelper.containsSingleAnnotation( annotations, JPADotNames.PRIMARY_KEY_JOIN_COLUMNS );
|
||||
}
|
||||
|
||||
public boolean hasPrimaryKeyJoinColumn() {
|
||||
return hasPrimaryKeyJoinColumn;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute.type;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EnumeratedTypeResolver extends AbstractAttributeTypeResolver {
|
||||
private final boolean isEnum;
|
||||
private final javax.persistence.EnumType enumType;
|
||||
|
||||
public static EnumeratedTypeResolver createAttributeTypeResolver(MappedAttribute attribute) {
|
||||
return new EnumeratedTypeResolver(
|
||||
attribute.getName(),
|
||||
attribute.getAttributeType(),
|
||||
resolveAnnotationInstance( attribute.annotations(),JPADotNames.ENUMERATED ),
|
||||
attribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public static EnumeratedTypeResolver createCollectionElementTypeResolver(
|
||||
PluralAssociationAttribute pluralAssociationAttribute) {
|
||||
return new EnumeratedTypeResolver(
|
||||
pluralAssociationAttribute.getName(),
|
||||
pluralAssociationAttribute.getReferencedAttributeType(),
|
||||
resolveAnnotationInstance( pluralAssociationAttribute.annotations(),JPADotNames.ENUMERATED ),
|
||||
pluralAssociationAttribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public static EnumeratedTypeResolver createCollectionIndexTypeResolver(
|
||||
PluralAssociationAttribute pluralAssociationAttribute) {
|
||||
return new EnumeratedTypeResolver(
|
||||
pluralAssociationAttribute.getName(),
|
||||
pluralAssociationAttribute.getIndexType(),
|
||||
resolveAnnotationInstance( pluralAssociationAttribute.annotations(), JPADotNames.MAP_KEY_ENUMERATED ),
|
||||
pluralAssociationAttribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
private EnumeratedTypeResolver(
|
||||
String name,
|
||||
Class<?> javaClass,
|
||||
AnnotationInstance annotation,
|
||||
EntityBindingContext context) {
|
||||
super( name, javaClass, annotation, context );
|
||||
this.isEnum = javaClass().isEnum();
|
||||
this.enumType = annotation == null ?
|
||||
null :
|
||||
JandexHelper.getEnumValue( annotation, "value", javax.persistence.EnumType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveHibernateTypeName() {
|
||||
if ( annotation() != null ) {
|
||||
if ( isEnum ) {
|
||||
return EnumType.class.getName();
|
||||
} else {
|
||||
throw new AnnotationException(
|
||||
String.format(
|
||||
"Attribute %s is not a Enumerated type, but has %s or %s annotation.",
|
||||
name(),
|
||||
JPADotNames.ENUMERATED,
|
||||
JPADotNames.MAP_KEY_ENUMERATED
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( !hasTypeDef() && isEnum ) {
|
||||
return EnumType.class.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> resolveHibernateTypeParameters() {
|
||||
HashMap<String, String> typeParameters = new HashMap<String, String>();
|
||||
|
||||
if ( enumType != null ) {
|
||||
typeParameters.put(EnumType.ENUM, javaClass().getName() );
|
||||
if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) {
|
||||
typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) );
|
||||
typeParameters.put( EnumType.NAMED, String.valueOf( false ) );
|
||||
}
|
||||
else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) {
|
||||
typeParameters.put( EnumType.TYPE, String.valueOf( Types.VARCHAR ) );
|
||||
typeParameters.put( EnumType.NAMED, String.valueOf( true ) );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unknown EnumType: " + enumType );
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) );
|
||||
}
|
||||
typeParameters.put( DynamicParameterizedType.RETURNED_CLASS, javaClass().getName() );
|
||||
return typeParameters;
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.type.CharacterArrayClobType;
|
||||
import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
||||
import org.hibernate.type.SerializableToBlobType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.WrappedMaterializedBlobType;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class LobTypeResolver extends AbstractAttributeTypeResolver {
|
||||
public static LobTypeResolver createAttributeTypeResolve(MappedAttribute attribute) {
|
||||
return new LobTypeResolver(
|
||||
attribute.getName(),
|
||||
attribute.getAttributeType(),
|
||||
resolveAnnotationInstance( attribute.annotations(), JPADotNames.LOB ),
|
||||
attribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public static LobTypeResolver createCollectionElementTypeResolve(PluralAssociationAttribute pluralAssociationAttribute) {
|
||||
return new LobTypeResolver(
|
||||
pluralAssociationAttribute.getName(),
|
||||
pluralAssociationAttribute.getReferencedAttributeType(),
|
||||
resolveAnnotationInstance( pluralAssociationAttribute.annotations(), JPADotNames.LOB ),
|
||||
pluralAssociationAttribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
private LobTypeResolver(String name,
|
||||
Class<?> javaClass,
|
||||
AnnotationInstance annotation,
|
||||
EntityBindingContext context) {
|
||||
super( name, javaClass, annotation, context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveHibernateTypeName() {
|
||||
if ( annotation() == null ) {
|
||||
//only check attributes annotated with @Lob
|
||||
return null;
|
||||
}
|
||||
String type = "blob";
|
||||
if ( Clob.class.isAssignableFrom( javaClass() ) ) {
|
||||
type = StandardBasicTypes.CLOB.getName();
|
||||
}
|
||||
else if ( Blob.class.isAssignableFrom( javaClass() ) ) {
|
||||
type = StandardBasicTypes.BLOB.getName();
|
||||
}
|
||||
else if ( String.class.isAssignableFrom( javaClass() ) ) {
|
||||
type = StandardBasicTypes.MATERIALIZED_CLOB.getName();
|
||||
}
|
||||
else if ( Character[].class.isAssignableFrom( javaClass() ) ) {
|
||||
type = CharacterArrayClobType.class.getName();
|
||||
}
|
||||
else if ( char[].class.isAssignableFrom( javaClass() ) ) {
|
||||
type = PrimitiveCharacterArrayClobType.class.getName();
|
||||
}
|
||||
else if ( Byte[].class.isAssignableFrom( javaClass() ) ) {
|
||||
type = WrappedMaterializedBlobType.class.getName();
|
||||
}
|
||||
else if ( byte[].class.isAssignableFrom( javaClass() ) ) {
|
||||
type = StandardBasicTypes.MATERIALIZED_BLOB.getName();
|
||||
}
|
||||
else if ( Serializable.class.isAssignableFrom( javaClass() ) ) {
|
||||
type = SerializableToBlobType.class.getName();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
protected Map<String, String> resolveHibernateTypeParameters() {
|
||||
if ( SerializableToBlobType.class.getName().equals( getExplicitHibernateTypeName() ) ) {
|
||||
return Collections.singletonMap( SerializableToBlobType.CLASS_NAME, javaClass().getName() );
|
||||
}
|
||||
else {
|
||||
return super.resolveHibernateTypeParameters();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.metamodel.internal.source.annotations.attribute.type;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.annotations.SourceType;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class TemporalTypeResolver extends AbstractAttributeTypeResolver {
|
||||
private final SourceType versionSourceType;
|
||||
|
||||
public static TemporalTypeResolver createAttributeTypeResolver(BasicAttribute attribute) {
|
||||
return new TemporalTypeResolver(
|
||||
attribute.getName(),
|
||||
attribute.getAttributeType(),
|
||||
resolveAnnotationInstance( attribute.annotations(), JPADotNames.TEMPORAL ),
|
||||
attribute.getContext(),
|
||||
attribute.isVersioned() ? attribute.getVersionSourceType() : null
|
||||
);
|
||||
}
|
||||
|
||||
public static TemporalTypeResolver createCollectionElementTypeResolver(PluralAssociationAttribute attribute) {
|
||||
return new TemporalTypeResolver(
|
||||
attribute.getName(),
|
||||
attribute.getReferencedAttributeType(),
|
||||
resolveAnnotationInstance( attribute.annotations(), JPADotNames.TEMPORAL ),
|
||||
attribute.getContext(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public static TemporalTypeResolver createCollectionIndexTypeResolver(PluralAssociationAttribute attribute) {
|
||||
return new TemporalTypeResolver(
|
||||
attribute.getName(),
|
||||
attribute.getIndexType(),
|
||||
resolveAnnotationInstance( attribute.annotations(), JPADotNames.MAP_KEY_TEMPORAL ),
|
||||
attribute.getContext(),
|
||||
null
|
||||
);
|
||||
}
|
||||
private TemporalTypeResolver(String name,
|
||||
Class<?> javaClass,
|
||||
AnnotationInstance annotation,
|
||||
EntityBindingContext context,
|
||||
SourceType versionSourceType) {
|
||||
super( name, javaClass, annotation, context );
|
||||
this.versionSourceType = versionSourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveHibernateTypeName() {
|
||||
Class attributeType = javaClass();
|
||||
|
||||
if ( isTemporalType( attributeType ) ) {
|
||||
if (versionSourceType != null ) {
|
||||
return versionSourceType.typeName();
|
||||
}
|
||||
if ( annotation() == null ) {
|
||||
// Although JPA 2.1 states that @Temporal is required on
|
||||
// Date/Calendar attributes, allow it to be left off in order
|
||||
// to support legacy mappings.
|
||||
// java.util.Date -> TimestampType
|
||||
// java.sql.Timestamp -> TimestampType
|
||||
// java.sql.Date -> DateType
|
||||
// java.sql.Time -> TimeType
|
||||
// java.util.Calendar -> CalendarType
|
||||
if ( java.sql.Date.class.isAssignableFrom( attributeType ) ) {
|
||||
return StandardBasicTypes.DATE.getName();
|
||||
} else if ( Time.class.isAssignableFrom( attributeType ) ) {
|
||||
return StandardBasicTypes.TIME.getName();
|
||||
} else if ( Calendar.class.isAssignableFrom( attributeType ) ) {
|
||||
return StandardBasicTypes.CALENDAR.getName();
|
||||
} else {
|
||||
return StandardBasicTypes.TIMESTAMP.getName();
|
||||
}
|
||||
} else {
|
||||
final TemporalType temporalType = JandexHelper.getEnumValue(
|
||||
annotation(),
|
||||
"value",
|
||||
TemporalType.class,
|
||||
getContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
final boolean isDate = Date.class.isAssignableFrom( attributeType );
|
||||
String type;
|
||||
switch ( temporalType ) {
|
||||
case DATE:
|
||||
type = isDate ? StandardBasicTypes.DATE.getName() : StandardBasicTypes.CALENDAR_DATE.getName();
|
||||
break;
|
||||
case TIME:
|
||||
type = StandardBasicTypes.TIME.getName();
|
||||
if ( !isDate ) {
|
||||
throw new NotYetImplementedException( "Calendar cannot persist TIME only" );
|
||||
}
|
||||
break;
|
||||
case TIMESTAMP:
|
||||
type = isDate ? StandardBasicTypes.TIMESTAMP.getName() : StandardBasicTypes.CALENDAR.getName();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionFailure( "Unknown temporal type: " + temporalType );
|
||||
}
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
if ( annotation() != null ) {
|
||||
throw new AnnotationException(
|
||||
"@Temporal should only be set on a java.util.Date or java.util.Calendar property: " + name()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isTemporalType(Class type) {
|
||||
return Date.class.isAssignableFrom( type ) || Calendar.class.isAssignableFrom( type );
|
||||
}
|
||||
}
|
|
@ -1,830 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
|
||||
/**
|
||||
* Base class for a configured entity, mapped super class or embeddable
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class ConfiguredClass {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AssertionFailure.class.getName());
|
||||
|
||||
/**
|
||||
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||
*/
|
||||
private final ConfiguredClass parent;
|
||||
|
||||
/**
|
||||
* The Jandex class info for this configured class. Provides access to the annotation defined on this configured class.
|
||||
*/
|
||||
private final ClassInfo classInfo;
|
||||
|
||||
/**
|
||||
* The actual java type.
|
||||
*/
|
||||
private final Class<?> clazz;
|
||||
|
||||
/**
|
||||
* Is this class abstract?
|
||||
*/
|
||||
private final boolean isAbstract;
|
||||
|
||||
/**
|
||||
* The default access type for this entity
|
||||
*/
|
||||
private final AccessType classAccessType;
|
||||
|
||||
/**
|
||||
* The generically resolved type
|
||||
*/
|
||||
private final ResolvedTypeWithMembers genericResolvedType;
|
||||
|
||||
/**
|
||||
* The id attributes
|
||||
*/
|
||||
private final Map<String, MappedAttribute> idAttributeMap;
|
||||
|
||||
/**
|
||||
* The mapped association attributes for this entity
|
||||
*/
|
||||
private final Map<String, AssociationAttribute> associationAttributeMap;
|
||||
|
||||
/**
|
||||
* The mapped simple attributes for this entity
|
||||
*/
|
||||
private final Map<String, BasicAttribute> simpleAttributeMap;
|
||||
|
||||
/**
|
||||
* The version attribute or {@code null} in case none exists.
|
||||
*/
|
||||
private BasicAttribute versionAttribute;
|
||||
|
||||
/**
|
||||
* The embedded classes for this entity
|
||||
*/
|
||||
private final Map<String, EmbeddableClass> embeddedClasses
|
||||
= new HashMap<String, EmbeddableClass>();
|
||||
|
||||
/**
|
||||
* The collection element embedded classes for this entity
|
||||
*/
|
||||
private final Map<String, EmbeddableClass> collectionEmbeddedClasses
|
||||
= new HashMap<String, EmbeddableClass>();
|
||||
|
||||
private final Map<String, AttributeOverride> attributeOverrideMap =new HashMap<String, AttributeOverride>( );
|
||||
private final Map<String, AssociationOverride> associationOverrideMap = new HashMap<String, AssociationOverride>( );
|
||||
|
||||
private final Set<String> transientFieldNames = new HashSet<String>();
|
||||
private final Set<String> transientMethodNames = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* Fully qualified name of a custom tuplizer
|
||||
*/
|
||||
private final String customTuplizer;
|
||||
|
||||
private final EntityBindingContext localBindingContext;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final String contextPath;
|
||||
|
||||
public ConfiguredClass(
|
||||
final ClassInfo classInfo,
|
||||
final ResolvedTypeWithMembers fullyResolvedType,
|
||||
final AccessType defaultAccessType,
|
||||
final ConfiguredClass parent,
|
||||
final AnnotationBindingContext context) {
|
||||
this(classInfo, fullyResolvedType, defaultAccessType, parent, "",context );
|
||||
}
|
||||
|
||||
|
||||
public ConfiguredClass(
|
||||
final ClassInfo classInfo,
|
||||
final ResolvedTypeWithMembers fullyResolvedType,
|
||||
final AccessType defaultAccessType,
|
||||
final ConfiguredClass parent,
|
||||
final String contextPath,
|
||||
final AnnotationBindingContext context) {
|
||||
this.parent = parent;
|
||||
this.classInfo = classInfo;
|
||||
this.contextPath = contextPath;
|
||||
this.clazz = context.locateClassByName( classInfo.toString() );
|
||||
this.genericResolvedType = fullyResolvedType;
|
||||
this.localBindingContext = new EntityBindingContext( context, this );
|
||||
this.isAbstract = ReflectHelper.isAbstractClass( this.clazz );
|
||||
this.classAccessType = determineClassAccessType( defaultAccessType );
|
||||
this.customTuplizer = AnnotationParserHelper.determineCustomTuplizer( classInfo.annotations(), classInfo,
|
||||
localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
this.simpleAttributeMap = new TreeMap<String, BasicAttribute>();
|
||||
this.idAttributeMap = new TreeMap<String, MappedAttribute>();
|
||||
this.associationAttributeMap = new TreeMap<String, AssociationAttribute>();
|
||||
collectAttributeOverrides();
|
||||
collectAssociationOverrides();
|
||||
|
||||
collectAttributes();
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return clazz.getName();
|
||||
}
|
||||
|
||||
public Class<?> getConfiguredClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public ClassInfo getClassInfo() {
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
public ConfiguredClass getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return isAbstract;
|
||||
}
|
||||
|
||||
public EntityBindingContext getLocalBindingContext() {
|
||||
return localBindingContext;
|
||||
}
|
||||
|
||||
public boolean hostsAnnotation(DotName annotationName) {
|
||||
List<AnnotationInstance> annotationList = classInfo.annotations().get( annotationName );
|
||||
return CollectionHelper.isNotEmpty( annotationList );
|
||||
}
|
||||
|
||||
public Map<String, BasicAttribute> getSimpleAttributes() {
|
||||
return simpleAttributeMap;
|
||||
}
|
||||
|
||||
public boolean isIdAttribute(String attributeName) {
|
||||
return idAttributeMap.containsKey( attributeName );
|
||||
}
|
||||
|
||||
public Map<String, MappedAttribute> getIdAttributes() {
|
||||
return idAttributeMap;
|
||||
}
|
||||
|
||||
public BasicAttribute getVersionAttribute() {
|
||||
return versionAttribute;
|
||||
}
|
||||
|
||||
public Map<String,AssociationAttribute> getAssociationAttributes() {
|
||||
return associationAttributeMap;
|
||||
}
|
||||
|
||||
public Map<String, EmbeddableClass> getEmbeddedClasses() {
|
||||
return embeddedClasses;
|
||||
}
|
||||
|
||||
public Map<String, EmbeddableClass> getCollectionEmbeddedClasses() {
|
||||
return collectionEmbeddedClasses;
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String, AttributeOverride>> attributeOverrideMapHolder = new ValueHolder<Map<String, AttributeOverride>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String, AttributeOverride>>() {
|
||||
@Override
|
||||
public Map<String, AttributeOverride> initialize() {
|
||||
Map<String, AttributeOverride> map = new HashMap<String, AttributeOverride>();
|
||||
for ( EmbeddableClass embeddableClass : getEmbeddedClasses().values() ) {
|
||||
map.putAll( embeddableClass.getAttributeOverrideMap() );
|
||||
}
|
||||
for(EmbeddableClass embeddableClass : getCollectionEmbeddedClasses().values()){
|
||||
map.putAll( embeddableClass.getAttributeOverrideMap() );
|
||||
}
|
||||
map.putAll( attributeOverrideMap );
|
||||
return map;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public Map<String, AttributeOverride> getAttributeOverrideMap() {
|
||||
return attributeOverrideMapHolder.getValue();
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String, AssociationOverride>> associationOverrideMapHolder = new ValueHolder<Map<String, AssociationOverride>>( new ValueHolder.DeferredInitializer<Map<String, AssociationOverride>>() {
|
||||
@Override
|
||||
public Map<String, AssociationOverride> initialize() {
|
||||
Map<String, AssociationOverride> map = new HashMap<String, AssociationOverride>( );
|
||||
for ( EmbeddableClass embeddableClass : getEmbeddedClasses().values() ) {
|
||||
map.putAll( embeddableClass.getAssociationOverrideMap() );
|
||||
}
|
||||
for(EmbeddableClass embeddableClass : getCollectionEmbeddedClasses().values()){
|
||||
map.putAll( embeddableClass.getAssociationOverrideMap() );
|
||||
}
|
||||
map.putAll( associationOverrideMap );
|
||||
return map;
|
||||
}
|
||||
} );
|
||||
|
||||
public Map<String, AssociationOverride> getAssociationOverrideMap() {
|
||||
return associationOverrideMapHolder.getValue();
|
||||
}
|
||||
|
||||
public AccessType getClassAccessType() {
|
||||
return classAccessType;
|
||||
}
|
||||
|
||||
public String getCustomTuplizer() {
|
||||
return customTuplizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "ConfiguredClass" );
|
||||
sb.append( "{clazz=" ).append( clazz.getSimpleName() );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private AccessType determineClassAccessType(AccessType defaultAccessType) {
|
||||
// default to the hierarchy access type to start with
|
||||
AccessType accessType = defaultAccessType;
|
||||
|
||||
AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo,
|
||||
JPADotNames.ACCESS,
|
||||
ClassInfo.class
|
||||
);
|
||||
if ( accessAnnotation != null ) {
|
||||
accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class,
|
||||
localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
return accessType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all attributes for this configured class and add them to the corresponding map
|
||||
*/
|
||||
private void collectAttributes() {
|
||||
// find transient field and method names
|
||||
findTransientFieldAndMethodNames();
|
||||
|
||||
|
||||
final Set<String> explicitlyConfiguredMemberNames = createExplicitlyConfiguredAccessProperties( );
|
||||
|
||||
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
||||
Field fields[] = clazz.getDeclaredFields();
|
||||
Field.setAccessible( fields, true );
|
||||
for ( Field field : fields ) {
|
||||
if ( AnnotationParserHelper.isPersistentMember(
|
||||
transientFieldNames,
|
||||
explicitlyConfiguredMemberNames,
|
||||
field
|
||||
) ) {
|
||||
createMappedAttribute( field, AccessType.FIELD );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
Method.setAccessible( methods, true );
|
||||
for ( Method method : methods ) {
|
||||
if ( AnnotationParserHelper.isPersistentMember(
|
||||
transientMethodNames,
|
||||
explicitlyConfiguredMemberNames,
|
||||
method
|
||||
) ) {
|
||||
createMappedAttribute( method, AccessType.PROPERTY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@code MappedProperty} instances for the explicitly configured persistent properties
|
||||
*
|
||||
*
|
||||
* @return the property names of the explicitly configured attribute names in a set
|
||||
*/
|
||||
private Set<String> createExplicitlyConfiguredAccessProperties() {
|
||||
Set<String> explicitAccessPropertyNames = new HashSet<String>();
|
||||
|
||||
List<AnnotationInstance> accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS );
|
||||
if ( accessAnnotations == null ) {
|
||||
return explicitAccessPropertyNames;
|
||||
}
|
||||
|
||||
// iterate over all @Access annotations defined on the current class
|
||||
for ( AnnotationInstance accessAnnotation : accessAnnotations ) {
|
||||
// we are only interested at annotations defined on fields and methods
|
||||
AnnotationTarget annotationTarget = accessAnnotation.target();
|
||||
if ( !( annotationTarget.getClass().equals( MethodInfo.class ) || annotationTarget.getClass()
|
||||
.equals( FieldInfo.class ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final AccessType accessType;
|
||||
if ( JPADotNames.ACCESS.equals( accessAnnotation.name() ) ) {
|
||||
accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class,
|
||||
localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType );
|
||||
} else {
|
||||
accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() );
|
||||
}
|
||||
|
||||
// the placement is correct, get the member
|
||||
Member member;
|
||||
if ( annotationTarget instanceof MethodInfo ) {
|
||||
try {
|
||||
member = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new HibernateException(
|
||||
"Unable to load method "
|
||||
+ ( ( MethodInfo ) annotationTarget ).name()
|
||||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
member = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() );
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
throw new HibernateException(
|
||||
"Unable to load field "
|
||||
+ ( ( FieldInfo ) annotationTarget ).name()
|
||||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( ReflectHelper.isProperty( member ) ) {
|
||||
createMappedAttribute( member, accessType );
|
||||
explicitAccessPropertyNames.add( ReflectHelper.getPropertyName( member ) );
|
||||
}
|
||||
}
|
||||
return explicitAccessPropertyNames;
|
||||
}
|
||||
|
||||
private void checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) {
|
||||
// when the access type of the class is FIELD
|
||||
// overriding access annotations must be placed on properties AND have the access type PROPERTY
|
||||
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
||||
if ( !MethodInfo.class.isInstance( annotationTarget ) ) {
|
||||
String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnProperty( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
|
||||
if ( !AccessType.PROPERTY.equals( accessType ) ) {
|
||||
String msg = LOG.accessTypeOverrideShouldBeProperty( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
}
|
||||
|
||||
// when the access type of the class is PROPERTY
|
||||
// overriding access annotations must be placed on fields and have the access type FIELD
|
||||
if ( AccessType.PROPERTY.equals( classAccessType ) ) {
|
||||
if ( !FieldInfo.class.isInstance( annotationTarget ) ) {
|
||||
String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnField( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
|
||||
if ( !AccessType.FIELD.equals( accessType ) ) {
|
||||
String msg = LOG.accessTypeOverrideShouldBeField( classInfo.name().toString() );
|
||||
LOG.trace( msg );
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createMappedAttribute(Member member, AccessType accessType) {
|
||||
final String attributeName = ReflectHelper.getPropertyName( member );
|
||||
final ResolvedMember[] resolvedMembers = Field.class.isInstance( member ) ? genericResolvedType.getMemberFields() : genericResolvedType
|
||||
.getMemberMethods();
|
||||
ResolvedMember resolvedMember = findResolvedMember( member.getName(), resolvedMembers );
|
||||
final Map<DotName, List<AnnotationInstance>> annotations = JandexHelper.getMemberAnnotations(
|
||||
classInfo, member.getName(), localBindingContext.getServiceRegistry()
|
||||
);
|
||||
Class<?> attributeType = resolvedMember.getType().getErasedType();
|
||||
Class<?> collectionElementType = AnnotationParserHelper.resolveCollectionElementType(
|
||||
resolvedMember,
|
||||
annotations,
|
||||
getLocalBindingContext()
|
||||
);
|
||||
Class<?> collectionIndexType = null;
|
||||
if ( Map.class.isAssignableFrom( attributeType ) && !resolvedMember.getType().getTypeParameters().isEmpty()) {
|
||||
collectionIndexType = resolvedMember.getType().getTypeParameters().get( 0 ).getErasedType();
|
||||
}
|
||||
MappedAttribute.Nature attributeNature = determineAttributeNature(
|
||||
annotations, attributeType, collectionElementType
|
||||
);
|
||||
String accessTypeString = accessType.toString().toLowerCase();
|
||||
switch ( attributeNature ) {
|
||||
case BASIC: {
|
||||
BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
|
||||
attributeName,
|
||||
attributeType,
|
||||
attributeNature,
|
||||
annotations,
|
||||
accessTypeString,
|
||||
getLocalBindingContext()
|
||||
);
|
||||
if ( attribute.isId() ) {
|
||||
idAttributeMap.put( attributeName, attribute );
|
||||
}
|
||||
else if ( attribute.isVersioned() ) {
|
||||
if ( versionAttribute == null ) {
|
||||
versionAttribute = attribute;
|
||||
}
|
||||
else {
|
||||
throw new MappingException( "Multiple version attributes", localBindingContext.getOrigin() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
simpleAttributeMap.put( attributeName, attribute );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMBEDDED_ID: {
|
||||
final BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
|
||||
attributeName,
|
||||
attributeType,
|
||||
attributeNature,
|
||||
annotations,
|
||||
accessTypeString,
|
||||
getLocalBindingContext()
|
||||
);
|
||||
idAttributeMap.put( attributeName, attribute );
|
||||
}
|
||||
case EMBEDDED: {
|
||||
final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.TARGET
|
||||
);
|
||||
if ( targetAnnotation != null ) {
|
||||
attributeType = localBindingContext.locateClassByName(
|
||||
JandexHelper.getValue( targetAnnotation, "value", String.class,
|
||||
localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
}
|
||||
embeddedClasses.put( attributeName, resolveEmbeddable(
|
||||
attributeName, attributeType, resolvedMember.getType(), annotations ) );
|
||||
break;
|
||||
}
|
||||
case ONE_TO_ONE:
|
||||
case MANY_TO_ONE: {
|
||||
final AssociationAttribute attribute = SingularAssociationAttribute.createSingularAssociationAttribute(
|
||||
classInfo,
|
||||
attributeName,
|
||||
resolvedMember.getType().getErasedType(),
|
||||
attributeNature,
|
||||
accessTypeString,
|
||||
annotations,
|
||||
getLocalBindingContext()
|
||||
);
|
||||
if ( attribute.isId() ) {
|
||||
idAttributeMap.put( attributeName, attribute );
|
||||
}
|
||||
associationAttributeMap.put( attributeName, attribute );
|
||||
break;
|
||||
}
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE:
|
||||
collectionEmbeddedClasses.put( attributeName, resolveEmbeddable(
|
||||
attributeName+".element", collectionElementType,resolvedMember.getType().getTypeBindings().getBoundType( 0 ), annotations ) );
|
||||
// fall through
|
||||
case ELEMENT_COLLECTION_BASIC:
|
||||
case ONE_TO_MANY:
|
||||
case MANY_TO_MANY: {
|
||||
AssociationAttribute attribute = PluralAssociationAttribute.createPluralAssociationAttribute(
|
||||
classInfo,
|
||||
attributeName,
|
||||
resolvedMember.getType().getErasedType(),
|
||||
collectionIndexType,
|
||||
collectionElementType,
|
||||
attributeNature,
|
||||
accessTypeString,
|
||||
annotations,
|
||||
getLocalBindingContext()
|
||||
);
|
||||
associationAttributeMap.put( attributeName, attribute );
|
||||
break;
|
||||
}
|
||||
case MANY_TO_ANY: {}
|
||||
}
|
||||
}
|
||||
|
||||
private EmbeddableClass resolveEmbeddable(
|
||||
String attributeName,
|
||||
Class<?> type,
|
||||
ResolvedType resolvedType,
|
||||
Map<DotName,List<AnnotationInstance>> annotations) {
|
||||
final ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() );
|
||||
if ( embeddableClassInfo == null ) {
|
||||
final String msg = String.format(
|
||||
"Attribute '%s#%s' is annotated with @Embedded,\n but '%s' does not seem to be annotated " +
|
||||
"with @Embeddable.\n Are all annotated classes added to the configuration?",
|
||||
getConfiguredClass().getName(),
|
||||
attributeName,
|
||||
type.getName()
|
||||
);
|
||||
throw new AnnotationException( msg );
|
||||
}
|
||||
|
||||
final NaturalIdMutability naturalIdMutability = AnnotationParserHelper.checkNaturalId( annotations );
|
||||
//tuplizer on field
|
||||
final String customTuplizerClass = AnnotationParserHelper.determineCustomTuplizer( annotations,
|
||||
localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
|
||||
final EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy(
|
||||
localBindingContext.<Object>locateClassByName( embeddableClassInfo.toString() ),
|
||||
attributeName,
|
||||
resolvedType,
|
||||
classAccessType,
|
||||
naturalIdMutability,
|
||||
customTuplizerClass,
|
||||
localBindingContext
|
||||
);
|
||||
return hierarchy.getLeaf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the annotations defined on a persistent attribute this methods determines the attribute type.
|
||||
*
|
||||
* @param annotations the annotations defined on the persistent attribute
|
||||
* @param attributeType the attribute's type
|
||||
* @param referencedCollectionType the type of the collection element in case the attribute is collection valued
|
||||
*
|
||||
* @return an instance of the {@code AttributeType} enum
|
||||
*/
|
||||
private MappedAttribute.Nature determineAttributeNature(
|
||||
final Map<DotName,List<AnnotationInstance>> annotations,
|
||||
final Class<?> attributeType,
|
||||
final Class<?> referencedCollectionType ) {
|
||||
EnumSet<MappedAttribute.Nature> discoveredAttributeTypes = EnumSet.noneOf( MappedAttribute.Nature.class );
|
||||
AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE );
|
||||
if ( oneToOne != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.ONE_TO_ONE );
|
||||
}
|
||||
|
||||
AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY );
|
||||
if ( oneToMany != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.ONE_TO_MANY );
|
||||
}
|
||||
|
||||
AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE );
|
||||
if ( manyToOne != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.MANY_TO_ONE );
|
||||
}
|
||||
|
||||
AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY );
|
||||
if ( manyToMany != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.MANY_TO_MANY );
|
||||
}
|
||||
|
||||
AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID );
|
||||
if ( embeddedId != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.EMBEDDED_ID );
|
||||
}
|
||||
AnnotationInstance id = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID );
|
||||
AnnotationInstance embedded = JandexHelper.getSingleAnnotation(
|
||||
annotations, JPADotNames.EMBEDDED );
|
||||
if ( embedded != null ) {
|
||||
discoveredAttributeTypes.add( MappedAttribute.Nature.EMBEDDED );
|
||||
} else if ( embeddedId == null ) {
|
||||
// For backward compatibility, we're allowing attributes of an
|
||||
// @Embeddable type to leave off @Embedded. Check the type's
|
||||
// annotations. (see HHH-7678)
|
||||
// However, it's important to ignore this if the field is
|
||||
// annotated with @EmbeddedId.
|
||||
if ( isEmbeddableType( attributeType ) ) {
|
||||
LOG.warn( attributeType.getName() + " has @Embeddable on it, but the attribute of this type in entity["
|
||||
+ getName()
|
||||
+ "] doesn't have @Embedded, which may cause compatibility issue" );
|
||||
discoveredAttributeTypes.add( id!=null? MappedAttribute.Nature.EMBEDDED_ID : MappedAttribute.Nature.EMBEDDED );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
JPADotNames.ELEMENT_COLLECTION
|
||||
);
|
||||
if ( elementCollection != null || ( discoveredAttributeTypes.isEmpty() && CollectionHelper.isCollectionOrArray( attributeType ) )) {
|
||||
boolean isEmbeddable = isEmbeddableType( referencedCollectionType );
|
||||
discoveredAttributeTypes.add( isEmbeddable? MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE : MappedAttribute.Nature.ELEMENT_COLLECTION_BASIC );
|
||||
}
|
||||
|
||||
int size = discoveredAttributeTypes.size();
|
||||
switch ( size ) {
|
||||
case 0:
|
||||
return MappedAttribute.Nature.BASIC;
|
||||
case 1:
|
||||
return discoveredAttributeTypes.iterator().next();
|
||||
default:
|
||||
throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() );
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isEmbeddableType(Class<?> referencedCollectionType) {
|
||||
// class info can be null for types like string, etc where there are no annotations
|
||||
ClassInfo classInfo = getLocalBindingContext().getIndex().getClassByName(
|
||||
DotName.createSimple(
|
||||
referencedCollectionType.getName()
|
||||
)
|
||||
);
|
||||
return classInfo != null && CollectionHelper.isNotEmpty( classInfo.annotations().get( JPADotNames.EMBEDDABLE ) );
|
||||
}
|
||||
|
||||
private ResolvedMember findResolvedMember(String name, ResolvedMember[] resolvedMembers) {
|
||||
for ( ResolvedMember resolvedMember : resolvedMembers ) {
|
||||
if ( resolvedMember.getName().equals( name ) ) {
|
||||
return resolvedMember;
|
||||
}
|
||||
}
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Unable to resolve type of attribute %s of class %s",
|
||||
name,
|
||||
classInfo.name().toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the sets of transient field and method names.
|
||||
*/
|
||||
private void findTransientFieldAndMethodNames() {
|
||||
List<AnnotationInstance> transientMembers = classInfo.annotations().get( JPADotNames.TRANSIENT );
|
||||
if ( transientMembers == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( AnnotationInstance transientMember : transientMembers ) {
|
||||
AnnotationTarget target = transientMember.target();
|
||||
if ( target instanceof FieldInfo ) {
|
||||
transientFieldNames.add( ( ( FieldInfo ) target ).name() );
|
||||
}
|
||||
else if(target instanceof MethodInfo) {
|
||||
transientMethodNames.add( ( ( MethodInfo ) target ).name() );
|
||||
}
|
||||
else {
|
||||
throw new MappingException( "@Transient can be only defined on field or property", getLocalBindingContext().getOrigin() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void collectAssociationOverrides() {
|
||||
|
||||
// Add all instances of @AssociationOverride
|
||||
List<AnnotationInstance> overrideAnnotations = JandexHelper
|
||||
.getAnnotations( classInfo, JPADotNames.ASSOCIATION_OVERRIDE );
|
||||
if ( overrideAnnotations != null ) {
|
||||
for ( AnnotationInstance annotation : overrideAnnotations ) {
|
||||
AssociationOverride override = new AssociationOverride(
|
||||
createPathPrefix( annotation.target() ), annotation, localBindingContext
|
||||
);
|
||||
associationOverrideMap.put(
|
||||
override.getAttributePath(), override
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all instances of @AssociationOverrides children
|
||||
List<AnnotationInstance> overridesAnnotations = JandexHelper
|
||||
.getAnnotations( classInfo, JPADotNames.ASSOCIATION_OVERRIDES );
|
||||
if ( overridesAnnotations != null ) {
|
||||
for ( AnnotationInstance attributeOverridesAnnotation : overridesAnnotations ) {
|
||||
AnnotationInstance[] annotationInstances
|
||||
= attributeOverridesAnnotation.value().asNestedArray();
|
||||
for ( AnnotationInstance annotation : annotationInstances ) {
|
||||
AssociationOverride override = new AssociationOverride(
|
||||
createPathPrefix(
|
||||
attributeOverridesAnnotation.target()
|
||||
),
|
||||
annotation,
|
||||
localBindingContext
|
||||
);
|
||||
associationOverrideMap.put(
|
||||
override.getAttributePath(), override
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void collectAttributeOverrides() {
|
||||
|
||||
// Add all instances of @AttributeOverride
|
||||
List<AnnotationInstance> attributeOverrideAnnotations = JandexHelper
|
||||
.getAnnotations(classInfo, JPADotNames.ATTRIBUTE_OVERRIDE );
|
||||
if ( attributeOverrideAnnotations != null ) {
|
||||
for ( AnnotationInstance annotation : attributeOverrideAnnotations ) {
|
||||
AttributeOverride override = new AttributeOverride(
|
||||
createPathPrefix( annotation.target() ), annotation, localBindingContext );
|
||||
attributeOverrideMap.put(
|
||||
override.getAttributePath(), override
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all instances of @AttributeOverrides children
|
||||
List<AnnotationInstance> attributeOverridesAnnotations = JandexHelper
|
||||
.getAnnotations(classInfo, JPADotNames.ATTRIBUTE_OVERRIDES);
|
||||
if ( attributeOverridesAnnotations != null ) {
|
||||
for ( AnnotationInstance attributeOverridesAnnotation : attributeOverridesAnnotations ) {
|
||||
AnnotationInstance[] annotationInstances
|
||||
= attributeOverridesAnnotation.value().asNestedArray();
|
||||
for ( AnnotationInstance annotation : annotationInstances ) {
|
||||
AttributeOverride override = new AttributeOverride(
|
||||
createPathPrefix(
|
||||
attributeOverridesAnnotation.target() ),
|
||||
annotation,
|
||||
localBindingContext );
|
||||
attributeOverrideMap.put(
|
||||
override.getAttributePath(), override
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String createPathPrefix(AnnotationTarget target) {
|
||||
if ( target instanceof FieldInfo || target instanceof MethodInfo ) {
|
||||
String path = JandexHelper.getPropertyName( target );
|
||||
if( StringHelper.isEmpty( contextPath )){
|
||||
return path;
|
||||
}
|
||||
return contextPath + "." + path;
|
||||
}
|
||||
return contextPath;
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
|
||||
/**
|
||||
* Represents the information about an entity annotated with {@code @Embeddable}.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EmbeddableClass extends ConfiguredClass {
|
||||
private final String embeddedAttributeName;
|
||||
private final String parentReferencingAttributeName;
|
||||
//custom tuplizer defined on the embedded field
|
||||
private final String customTuplizerClass;
|
||||
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
|
||||
|
||||
public EmbeddableClass(
|
||||
ClassInfo classInfo,
|
||||
ResolvedTypeWithMembers fullyResolvedType,
|
||||
String embeddedAttributeName,
|
||||
ConfiguredClass parent,
|
||||
AccessType defaultAccessType,
|
||||
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
|
||||
String customTuplizerClass,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, fullyResolvedType, defaultAccessType, parent, embeddedAttributeName, context );
|
||||
this.embeddedAttributeName = embeddedAttributeName;
|
||||
this.naturalIdMutability = naturalIdMutability;
|
||||
this.parentReferencingAttributeName = checkParentAnnotation();
|
||||
this.customTuplizerClass = customTuplizerClass;
|
||||
|
||||
overrideNaturalIdMutability(naturalIdMutability);
|
||||
}
|
||||
|
||||
private void overrideNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
|
||||
for ( BasicAttribute attribute : getSimpleAttributes().values() ) {
|
||||
attribute.setNaturalIdMutability( naturalIdMutability );
|
||||
}
|
||||
for ( EmbeddableClass embeddable : getEmbeddedClasses().values() ) {
|
||||
embeddable.setNaturalIdMutability( naturalIdMutability );
|
||||
embeddable.overrideNaturalIdMutability( naturalIdMutability );
|
||||
}
|
||||
for ( AssociationAttribute associationAttribute : getAssociationAttributes().values() ) {
|
||||
associationAttribute.setNaturalIdMutability( naturalIdMutability );
|
||||
}
|
||||
}
|
||||
|
||||
private String checkParentAnnotation() {
|
||||
AnnotationInstance parentAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.PARENT
|
||||
);
|
||||
return parentAnnotation == null? null : JandexHelper.getPropertyName( parentAnnotation.target() );
|
||||
}
|
||||
|
||||
public String getEmbeddedAttributeName() {
|
||||
return embeddedAttributeName;
|
||||
}
|
||||
|
||||
public String getParentReferencingAttributeName() {
|
||||
return parentReferencingAttributeName;
|
||||
}
|
||||
|
||||
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
|
||||
return naturalIdMutability;
|
||||
}
|
||||
|
||||
public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
|
||||
this.naturalIdMutability = naturalIdMutability;
|
||||
}
|
||||
|
||||
public String getCustomTuplizerClass() {
|
||||
return customTuplizerClass;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.ClassmateHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
|
||||
import static org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability;
|
||||
|
||||
/**
|
||||
* Contains information about the access and inheritance type for all classes within a class hierarchy.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
|
||||
private final AccessType defaultAccessType;
|
||||
private final List<EmbeddableClass> embeddables;
|
||||
/**
|
||||
* Builds the configured class hierarchy for a an embeddable class.
|
||||
*
|
||||
* @param embeddableClass the top level embedded class
|
||||
* @param propertyName the name of the property in the entity class embedding this embeddable
|
||||
* @param accessType the access type inherited from the class in which the embeddable gets embedded
|
||||
* @param context the annotation binding context with access to the service registry and the annotation index
|
||||
*
|
||||
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
|
||||
*/
|
||||
public static EmbeddableHierarchy createEmbeddableHierarchy(
|
||||
final Class<?> embeddableClass,
|
||||
final String propertyName,
|
||||
final ResolvedType resolvedType,
|
||||
final AccessType accessType,
|
||||
final NaturalIdMutability naturalIdMutability,
|
||||
final String customTuplizerClass,
|
||||
final AnnotationBindingContext context) {
|
||||
|
||||
final ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() );
|
||||
checkIndexed( embeddableClass, embeddableClassInfo );
|
||||
checkEmbeddableAnnotation( embeddableClass, embeddableClassInfo );
|
||||
Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers = ClassmateHelper.resolveClassHierarchyTypesFromAttributeType(
|
||||
embeddableClass,
|
||||
resolvedType,
|
||||
context
|
||||
);
|
||||
List<ClassInfo> classInfoList = new ArrayList<ClassInfo>();
|
||||
Class<?> clazz = embeddableClass;
|
||||
while ( clazz != null && !clazz.equals( Object.class ) ) {
|
||||
ClassInfo tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
|
||||
if ( tmpClassInfo == null ) {
|
||||
continue;
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
classInfoList.add( 0, tmpClassInfo );
|
||||
}
|
||||
|
||||
return new EmbeddableHierarchy(
|
||||
classInfoList,
|
||||
resolvedTypeWithMembers,
|
||||
propertyName,
|
||||
naturalIdMutability,
|
||||
customTuplizerClass,
|
||||
context,
|
||||
accessType
|
||||
);
|
||||
}
|
||||
|
||||
private static void checkEmbeddableAnnotation(Class<?> embeddableClass, ClassInfo embeddableClassInfo) {
|
||||
if ( JandexHelper.getSingleAnnotation( embeddableClassInfo, JPADotNames.EMBEDDABLE ) == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"The specified class %s is not annotated with @Embeddable even though it is as embeddable",
|
||||
embeddableClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkIndexed(Class<?> embeddableClass, ClassInfo embeddableClassInfo) {
|
||||
if ( embeddableClassInfo == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"The specified class %s cannot be found in the annotation index",
|
||||
embeddableClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private EmbeddableHierarchy(
|
||||
final List<ClassInfo> classInfoList,
|
||||
final Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers,
|
||||
final String propertyName,
|
||||
final NaturalIdMutability naturalIdMutability,
|
||||
final String customTuplizerClass,
|
||||
final AnnotationBindingContext context,
|
||||
final AccessType defaultAccessType) {
|
||||
this.defaultAccessType = defaultAccessType;
|
||||
|
||||
this.embeddables = new ArrayList<EmbeddableClass>();
|
||||
ConfiguredClass parent = null;
|
||||
for ( ClassInfo info : classInfoList ) {
|
||||
ResolvedTypeWithMembers fullyResolvedType = resolvedTypeWithMembers.get( info.toString() );
|
||||
if ( fullyResolvedType == null ) {
|
||||
throw new AssertionFailure( "Unable to find resolved type information for " + info.toString() );
|
||||
}
|
||||
EmbeddableClass embeddable = new EmbeddableClass(
|
||||
info,
|
||||
fullyResolvedType,
|
||||
propertyName,
|
||||
parent,
|
||||
defaultAccessType,
|
||||
naturalIdMutability,
|
||||
customTuplizerClass,
|
||||
context
|
||||
);
|
||||
embeddables.add( embeddable );
|
||||
parent = embeddable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AccessType getDefaultAccessType() {
|
||||
return defaultAccessType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An iterator iterating in top down manner over the configured classes in this hierarchy.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<EmbeddableClass> iterator() {
|
||||
return embeddables.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the leaf configured class
|
||||
*/
|
||||
public EmbeddableClass getLeaf() {
|
||||
return embeddables.get( embeddables.size() - 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "EmbeddableHierarchy" );
|
||||
sb.append( "{defaultAccessType=" ).append( defaultAccessType );
|
||||
sb.append( ", embeddables=" ).append( embeddables );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,580 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
import org.hibernate.annotations.OptimisticLockType;
|
||||
import org.hibernate.annotations.PolymorphismType;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPAListenerHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.JpaCallbackSource;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
|
||||
/**
|
||||
* Represents an entity or mapped superclass configured via annotations/orm-xml.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityClass extends ConfiguredClass {
|
||||
private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId";
|
||||
|
||||
private final InheritanceType inheritanceType;
|
||||
|
||||
private final String explicitEntityName;
|
||||
private final String customLoaderQueryName;
|
||||
private final String[] synchronizedTableNames;
|
||||
private final int batchSize;
|
||||
|
||||
private boolean isImmutable;
|
||||
private boolean isExplicitPolymorphism;
|
||||
private OptimisticLockStyle optimisticLockStyle;
|
||||
private String whereClause;
|
||||
private String rowId;
|
||||
private Caching caching;
|
||||
private Caching naturalIdCaching;
|
||||
private boolean isDynamicInsert;
|
||||
private boolean isDynamicUpdate;
|
||||
private boolean isSelectBeforeUpdate;
|
||||
private String customPersister;
|
||||
|
||||
private final CustomSQL customInsert;
|
||||
private final CustomSQL customUpdate;
|
||||
private final CustomSQL customDelete;
|
||||
|
||||
|
||||
private final String inverseForeignKeyName;
|
||||
private final String explicitForeignKeyName;
|
||||
|
||||
private final OnDeleteAction onDeleteAction;
|
||||
|
||||
private boolean isLazy;
|
||||
private String proxy;
|
||||
|
||||
private String discriminatorMatchValue;
|
||||
|
||||
private List<JpaCallbackSource> jpaCallbacks;
|
||||
private final List<PrimaryKeyJoinColumn> joinedSubclassPrimaryKeyJoinColumnSources;
|
||||
|
||||
/**
|
||||
* Constructor used for entities within a hierarchy (non entity roots)
|
||||
*
|
||||
* @param classInfo the jandex class info this this entity
|
||||
* @param parent the parent entity
|
||||
* @param hierarchyAccessType the default access type
|
||||
* @param inheritanceType the inheritance type this entity
|
||||
* @param context the binding context
|
||||
*/
|
||||
public EntityClass(
|
||||
ClassInfo classInfo,
|
||||
ResolvedTypeWithMembers fullyResolvedType,
|
||||
EntityClass parent,
|
||||
AccessType hierarchyAccessType,
|
||||
InheritanceType inheritanceType,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, fullyResolvedType, hierarchyAccessType, parent, context );
|
||||
this.inheritanceType = inheritanceType;
|
||||
|
||||
this.explicitEntityName = determineExplicitEntityName();
|
||||
this.customLoaderQueryName = determineCustomLoader();
|
||||
this.synchronizedTableNames = determineSynchronizedTableNames();
|
||||
this.batchSize = determineBatchSize();
|
||||
|
||||
this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_INSERT,
|
||||
getClassInfo().annotations(),
|
||||
getClassInfo()
|
||||
);
|
||||
this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_UPDATE,
|
||||
getClassInfo().annotations(),
|
||||
getClassInfo()
|
||||
);
|
||||
this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation(
|
||||
HibernateDotNames.SQL_DELETE,
|
||||
getClassInfo().annotations(),
|
||||
getClassInfo()
|
||||
);
|
||||
|
||||
|
||||
processHibernateEntitySpecificAnnotations();
|
||||
processProxyGeneration();
|
||||
processDiscriminatorValue();
|
||||
|
||||
this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns();
|
||||
// TODO: bind JPA @ForeignKey?
|
||||
explicitForeignKeyName = null;
|
||||
inverseForeignKeyName = null;
|
||||
this.onDeleteAction = determineOnDeleteAction();
|
||||
|
||||
}
|
||||
|
||||
private OnDeleteAction determineOnDeleteAction() {
|
||||
final AnnotationInstance onDeleteAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.ON_DELETE,
|
||||
ClassInfo.class
|
||||
);
|
||||
if ( onDeleteAnnotation != null ) {
|
||||
ensureJoinedSubEntity();
|
||||
return JandexHelper.getEnumValue( onDeleteAnnotation, "action", OnDeleteAction.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ensureJoinedSubEntity() {
|
||||
if ( !( getParent() != null && inheritanceType == InheritanceType.JOINED ) ) {
|
||||
throw getLocalBindingContext().makeMappingException( explicitEntityName + "is not a joined sub entity" );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isExplicitPolymorphism() {
|
||||
return isExplicitPolymorphism;
|
||||
}
|
||||
|
||||
public boolean isMutable() {
|
||||
return !isImmutable;
|
||||
}
|
||||
|
||||
public OptimisticLockStyle getOptimisticLockStyle() {
|
||||
return optimisticLockStyle;
|
||||
}
|
||||
|
||||
public String getWhereClause() {
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
public String getRowId() {
|
||||
return rowId;
|
||||
}
|
||||
|
||||
public Caching getCaching() {
|
||||
return caching;
|
||||
}
|
||||
|
||||
public Caching getNaturalIdCaching() {
|
||||
return naturalIdCaching;
|
||||
}
|
||||
|
||||
public String getExplicitEntityName() {
|
||||
return explicitEntityName;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return getConfiguredClass().getSimpleName();
|
||||
}
|
||||
|
||||
public boolean isDynamicInsert() {
|
||||
return isDynamicInsert;
|
||||
}
|
||||
|
||||
public boolean isDynamicUpdate() {
|
||||
return isDynamicUpdate;
|
||||
}
|
||||
|
||||
public boolean isSelectBeforeUpdate() {
|
||||
return isSelectBeforeUpdate;
|
||||
}
|
||||
|
||||
public String getCustomLoaderQueryName() {
|
||||
return customLoaderQueryName;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomInsert() {
|
||||
return customInsert;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomUpdate() {
|
||||
return customUpdate;
|
||||
}
|
||||
|
||||
public CustomSQL getCustomDelete() {
|
||||
return customDelete;
|
||||
}
|
||||
|
||||
public String[] getSynchronizedTableNames() {
|
||||
return synchronizedTableNames;
|
||||
}
|
||||
|
||||
public List<PrimaryKeyJoinColumn> getJoinedSubclassPrimaryKeyJoinColumnSources() {
|
||||
return joinedSubclassPrimaryKeyJoinColumnSources;
|
||||
}
|
||||
|
||||
public String getCustomPersister() {
|
||||
return customPersister;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return isLazy;
|
||||
}
|
||||
|
||||
public String getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
public boolean isEntityRoot() {
|
||||
return getParent() == null;
|
||||
}
|
||||
|
||||
public String getDiscriminatorMatchValue() {
|
||||
return discriminatorMatchValue;
|
||||
}
|
||||
|
||||
public List<JpaCallbackSource> getJpaCallbacks() {
|
||||
if ( jpaCallbacks == null ) {
|
||||
jpaCallbacks = new JPAListenerHelper( this ).bindJPAListeners();
|
||||
}
|
||||
return jpaCallbacks;
|
||||
}
|
||||
|
||||
public String getInverseForeignKeyName() {
|
||||
return inverseForeignKeyName;
|
||||
}
|
||||
public String getExplicitForeignKeyName(){
|
||||
return explicitForeignKeyName;
|
||||
}
|
||||
public List<MappedSuperclass> getMappedSuperclasses() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public OnDeleteAction getOnDeleteAction() {
|
||||
return onDeleteAction;
|
||||
}
|
||||
|
||||
public boolean definesItsOwnTable() {
|
||||
return !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) || isEntityRoot();
|
||||
}
|
||||
|
||||
private String determineExplicitEntityName() {
|
||||
final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), JPADotNames.ENTITY
|
||||
);
|
||||
return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
protected List<PrimaryKeyJoinColumn> determinePrimaryKeyJoinColumns() {
|
||||
final AnnotationInstance primaryKeyJoinColumns = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
JPADotNames.PRIMARY_KEY_JOIN_COLUMNS,
|
||||
ClassInfo.class
|
||||
);
|
||||
final AnnotationInstance primaryKeyJoinColumn = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
JPADotNames.PRIMARY_KEY_JOIN_COLUMN,
|
||||
ClassInfo.class
|
||||
);
|
||||
|
||||
if ( primaryKeyJoinColumn != null || primaryKeyJoinColumns != null ) {
|
||||
ensureJoinedSubEntity();
|
||||
}
|
||||
|
||||
final List<PrimaryKeyJoinColumn> results;
|
||||
if ( primaryKeyJoinColumns != null ) {
|
||||
AnnotationInstance[] values = primaryKeyJoinColumns.value().asNestedArray();
|
||||
results = new ArrayList<PrimaryKeyJoinColumn>( values.length );
|
||||
for ( final AnnotationInstance annotationInstance : values ) {
|
||||
results.add( new PrimaryKeyJoinColumn( annotationInstance ) );
|
||||
}
|
||||
}
|
||||
else if ( primaryKeyJoinColumn != null ) {
|
||||
results = new ArrayList<PrimaryKeyJoinColumn>( 1 );
|
||||
results.add( new PrimaryKeyJoinColumn( primaryKeyJoinColumn ) );
|
||||
}
|
||||
else {
|
||||
results = null;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
private void processDiscriminatorValue() {
|
||||
final AnnotationInstance discriminatorValueAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), JPADotNames.DISCRIMINATOR_VALUE
|
||||
);
|
||||
if ( discriminatorValueAnnotation != null ) {
|
||||
this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString();
|
||||
}
|
||||
}
|
||||
|
||||
private void processHibernateEntitySpecificAnnotations() {
|
||||
// see HHH-6400
|
||||
PolymorphismType polymorphism = PolymorphismType.IMPLICIT;
|
||||
final AnnotationInstance polymorphismAnnotation = JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.POLYMORPHISM );
|
||||
if ( polymorphismAnnotation != null && polymorphismAnnotation.value( "type" ) != null ) {
|
||||
polymorphism = PolymorphismType.valueOf( polymorphismAnnotation.value( "type" ).asEnum() );
|
||||
}
|
||||
isExplicitPolymorphism = polymorphism == PolymorphismType.EXPLICIT;
|
||||
|
||||
// see HHH-6401
|
||||
OptimisticLockType optimisticLockType = OptimisticLockType.VERSION;
|
||||
final AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.OPTIMISTIC_LOCK,
|
||||
ClassInfo.class
|
||||
);
|
||||
if ( optimisticLockAnnotation != null ) {
|
||||
optimisticLockType = JandexHelper.getEnumValue(
|
||||
optimisticLockAnnotation,
|
||||
"type",
|
||||
OptimisticLockType.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
}
|
||||
optimisticLockStyle = OptimisticLockStyle.valueOf( optimisticLockType.name() );
|
||||
|
||||
final AnnotationInstance hibernateImmutableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.IMMUTABLE,
|
||||
ClassInfo.class
|
||||
);
|
||||
isImmutable = hibernateImmutableAnnotation != null ;
|
||||
final AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.WHERE
|
||||
);
|
||||
whereClause = whereAnnotation != null && whereAnnotation.value( "clause" ) != null ?
|
||||
whereAnnotation.value( "clause" ).asString() : null;
|
||||
|
||||
final AnnotationInstance rowIdAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.ROW_ID
|
||||
);
|
||||
rowId = rowIdAnnotation != null && rowIdAnnotation.value() != null
|
||||
? rowIdAnnotation.value().asString() : null;
|
||||
|
||||
caching = determineCachingSettings();
|
||||
|
||||
naturalIdCaching = determineNaturalIdCachingSettings( caching );
|
||||
|
||||
// see HHH-6397
|
||||
final AnnotationInstance dynamicInsertAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.DYNAMIC_INSERT
|
||||
);
|
||||
if ( dynamicInsertAnnotation != null ) {
|
||||
isDynamicInsert = JandexHelper.getValue( dynamicInsertAnnotation, "value", Boolean.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
// see HHH-6398
|
||||
final AnnotationInstance dynamicUpdateAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.DYNAMIC_UPDATE
|
||||
);
|
||||
if ( dynamicUpdateAnnotation != null ) {
|
||||
isDynamicUpdate = JandexHelper.getValue( dynamicUpdateAnnotation, "value", Boolean.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
|
||||
// see HHH-6399
|
||||
final AnnotationInstance selectBeforeUpdateAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.SELECT_BEFORE_UPDATE
|
||||
);
|
||||
if ( selectBeforeUpdateAnnotation != null ) {
|
||||
isSelectBeforeUpdate = JandexHelper.getValue( selectBeforeUpdateAnnotation, "value", Boolean.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
}
|
||||
|
||||
// Custom persister
|
||||
String entityPersisterClass = null;
|
||||
final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.PERSISTER, ClassInfo.class
|
||||
);
|
||||
if ( persisterAnnotation != null && persisterAnnotation.value( "impl" ) != null ) {
|
||||
entityPersisterClass = persisterAnnotation.value( "impl" ).asString();
|
||||
}
|
||||
this.customPersister = entityPersisterClass;
|
||||
}
|
||||
|
||||
private Caching determineNaturalIdCachingSettings(final Caching entityCache) {
|
||||
final AnnotationInstance naturalIdCacheAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.NATURAL_ID_CACHE
|
||||
);
|
||||
if ( naturalIdCacheAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
final String region;
|
||||
if ( naturalIdCacheAnnotation.value( "region" ) == null || StringHelper.isEmpty(
|
||||
naturalIdCacheAnnotation.value(
|
||||
"region"
|
||||
).asString()
|
||||
) ) {
|
||||
region = entityCache == null ? getEntityName() + NATURAL_ID_CACHE_SUFFIX : entityCache.getRegion() + NATURAL_ID_CACHE_SUFFIX;
|
||||
}
|
||||
else {
|
||||
region = naturalIdCacheAnnotation.value( "region" ).asString();
|
||||
}
|
||||
return new Caching( region, null, false );
|
||||
}
|
||||
|
||||
private Caching determineCachingSettings() {
|
||||
final List<AnnotationInstance> annotationInstanceList = getClassInfo().annotations().get( HibernateDotNames.CACHE );
|
||||
if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) {
|
||||
for ( final AnnotationInstance hibernateCacheAnnotation : annotationInstanceList ) {
|
||||
if ( ClassInfo.class.isInstance( hibernateCacheAnnotation.target() ) ) {
|
||||
final org.hibernate.cache.spi.access.AccessType accessType = hibernateCacheAnnotation.value( "usage" ) == null
|
||||
? getLocalBindingContext().getMappingDefaults().getCacheAccessType()
|
||||
: CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() )
|
||||
.toAccessType();
|
||||
return new Caching(
|
||||
hibernateCacheAnnotation.value( "region" ) == null
|
||||
? getName()
|
||||
: hibernateCacheAnnotation.value( "region" ).asString(),
|
||||
accessType,
|
||||
hibernateCacheAnnotation.value( "include" ) != null
|
||||
&& "all".equals( hibernateCacheAnnotation.value( "include" ).asString() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final AnnotationInstance jpaCacheableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), JPADotNames.CACHEABLE
|
||||
);
|
||||
|
||||
final boolean doCaching;
|
||||
switch ( getLocalBindingContext().getBuildingOptions().getSharedCacheMode() ) {
|
||||
case ALL: {
|
||||
doCaching = true;
|
||||
break;
|
||||
}
|
||||
case ENABLE_SELECTIVE: {
|
||||
doCaching = jpaCacheableAnnotation != null
|
||||
&& JandexHelper.getValue( jpaCacheableAnnotation, "value", Boolean.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
break;
|
||||
}
|
||||
case DISABLE_SELECTIVE: {
|
||||
doCaching = jpaCacheableAnnotation == null
|
||||
|| !JandexHelper.getValue( jpaCacheableAnnotation, "value", Boolean.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// treat both NONE and UNSPECIFIED the same
|
||||
doCaching = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !doCaching ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Caching(
|
||||
getName(),
|
||||
getLocalBindingContext().getMappingDefaults().getCacheAccessType(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public boolean hasMultiTenancySourceInformation() {
|
||||
return JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.MULTI_TENANT ) != null
|
||||
|| JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.TENANT_COLUMN ) != null
|
||||
|| JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.TENANT_FORMULA ) != null;
|
||||
}
|
||||
|
||||
private String determineCustomLoader() {
|
||||
String customLoader = null;
|
||||
// Custom sql loader
|
||||
final AnnotationInstance sqlLoaderAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.LOADER
|
||||
);
|
||||
if ( sqlLoaderAnnotation != null && sqlLoaderAnnotation.target() instanceof ClassInfo) {
|
||||
customLoader = sqlLoaderAnnotation.value( "namedQuery" ).asString();
|
||||
}
|
||||
return customLoader;
|
||||
}
|
||||
|
||||
private String[] determineSynchronizedTableNames() {
|
||||
final AnnotationInstance synchronizeAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.SYNCHRONIZE
|
||||
);
|
||||
if ( synchronizeAnnotation != null ) {
|
||||
return synchronizeAnnotation.value().asStringArray();
|
||||
}
|
||||
else {
|
||||
return StringHelper.EMPTY_STRINGS;
|
||||
}
|
||||
}
|
||||
|
||||
private void processProxyGeneration() {
|
||||
// Proxy generation
|
||||
final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.PROXY
|
||||
);
|
||||
if ( hibernateProxyAnnotation != null ) {
|
||||
isLazy = hibernateProxyAnnotation.value( "lazy" ) == null
|
||||
|| hibernateProxyAnnotation.value( "lazy" ).asBoolean();
|
||||
if ( isLazy ) {
|
||||
final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" );
|
||||
proxy = proxyClassValue == null ? getName() : proxyClassValue.asString();
|
||||
}
|
||||
else {
|
||||
proxy = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
isLazy = true;
|
||||
proxy = getName();
|
||||
}
|
||||
}
|
||||
|
||||
private int determineBatchSize() {
|
||||
final AnnotationInstance batchSizeAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.BATCH_SIZE
|
||||
);
|
||||
return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
|
||||
/**
|
||||
* Represents the information about an entity annotated with {@code @MappedSuperclass}.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class MappedSuperclass extends ConfiguredClass {
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param classInfo the Jandex {@code ClassInfo} for this mapped superclass
|
||||
* @param parent the parent class
|
||||
* @param defaultAccessType the default access type
|
||||
* @param context context
|
||||
*/
|
||||
public MappedSuperclass(
|
||||
ClassInfo classInfo,
|
||||
ResolvedTypeWithMembers fullyResolvedType,
|
||||
ConfiguredClass parent,
|
||||
AccessType defaultAccessType,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, fullyResolvedType, defaultAccessType, parent, context );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.FormulaValue;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
|
||||
/**
|
||||
* Represents an root entity configured via annotations/orm-xml.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class RootEntityClass extends EntityClass {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
RootEntityClass.class.getName()
|
||||
);
|
||||
|
||||
private final IdType idType;
|
||||
private final List<MappedSuperclass> mappedSuperclasses= new ArrayList<MappedSuperclass>();
|
||||
|
||||
// discriminator related fields
|
||||
private Column discriminatorColumnValues;
|
||||
private FormulaValue discriminatorFormula;
|
||||
private Class<?> discriminatorType;
|
||||
|
||||
private boolean isDiscriminatorForced = false;
|
||||
private boolean isDiscriminatorIncludedInSql = true;
|
||||
private boolean needsDiscriminatorColumn = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor used for entity roots
|
||||
*
|
||||
* @param classInfo the jandex class info this this entity
|
||||
* @param mappedSuperclasses a list of class info instances representing the mapped super classes for this root entity
|
||||
* @param hierarchyAccessType the default access type
|
||||
* @param inheritanceType the inheritance type this entity
|
||||
* @param hasSubclasses flag indicating whether this root entity has sub classes
|
||||
* @param context the binding context
|
||||
*/
|
||||
public RootEntityClass(
|
||||
ClassInfo classInfo,
|
||||
Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers,
|
||||
List<ClassInfo> mappedSuperclasses,
|
||||
AccessType hierarchyAccessType,
|
||||
InheritanceType inheritanceType,
|
||||
boolean hasSubclasses,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, resolvedTypeWithMembers.get( classInfo.toString() ), null, hierarchyAccessType, inheritanceType, context );
|
||||
for ( ClassInfo mappedSuperclassInfo : mappedSuperclasses ) {
|
||||
MappedSuperclass configuredClass = new MappedSuperclass(
|
||||
mappedSuperclassInfo,
|
||||
resolvedTypeWithMembers.get( mappedSuperclassInfo.toString() ),
|
||||
null,
|
||||
hierarchyAccessType,
|
||||
context
|
||||
);
|
||||
this.mappedSuperclasses.add( configuredClass );
|
||||
}
|
||||
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) {
|
||||
processDiscriminator();
|
||||
this.needsDiscriminatorColumn = hasSubclasses || isDiscriminatorForced;
|
||||
}
|
||||
|
||||
this.idType = determineIdType();
|
||||
}
|
||||
|
||||
public boolean needsDiscriminatorColumn() {
|
||||
return needsDiscriminatorColumn;
|
||||
}
|
||||
|
||||
public Column getDiscriminatorColumnValues() {
|
||||
return discriminatorColumnValues;
|
||||
}
|
||||
|
||||
public FormulaValue getDiscriminatorFormula() {
|
||||
return discriminatorFormula;
|
||||
}
|
||||
|
||||
public Class<?> getDiscriminatorType() {
|
||||
return discriminatorType;
|
||||
}
|
||||
|
||||
public List<MappedSuperclass> getMappedSuperclasses() {
|
||||
return mappedSuperclasses;
|
||||
}
|
||||
|
||||
public IdType getIdType() {
|
||||
return idType;
|
||||
}
|
||||
|
||||
public boolean isDiscriminatorForced() {
|
||||
return isDiscriminatorForced;
|
||||
}
|
||||
|
||||
public boolean isDiscriminatorIncludedInSql() {
|
||||
return isDiscriminatorIncludedInSql;
|
||||
}
|
||||
|
||||
protected List<PrimaryKeyJoinColumn> determinePrimaryKeyJoinColumns() {
|
||||
List<PrimaryKeyJoinColumn> results = super.determinePrimaryKeyJoinColumns();
|
||||
if ( CollectionHelper.isNotEmpty( results ) ) {
|
||||
LOG.invalidPrimaryKeyJoinColumnAnnotation();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String, BasicAttribute>> simpleAttributes = new ValueHolder<Map<String, BasicAttribute>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String, BasicAttribute>>() {
|
||||
@Override
|
||||
public Map<String, BasicAttribute> initialize() {
|
||||
final Map<String, BasicAttribute> map = new HashMap<String, BasicAttribute>();
|
||||
for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) {
|
||||
map.putAll( mappedSuperclass.getSimpleAttributes() );
|
||||
}
|
||||
map.putAll( RootEntityClass.super.getSimpleAttributes() );
|
||||
return map;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@Override
|
||||
public Map<String,BasicAttribute> getSimpleAttributes() {
|
||||
return simpleAttributes.getValue();
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String, AssociationAttribute>> associationAttributes = new ValueHolder<Map<String, AssociationAttribute>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String, AssociationAttribute>>() {
|
||||
@Override
|
||||
public Map<String, AssociationAttribute> initialize() {
|
||||
Map<String, AssociationAttribute> map = new HashMap<String, AssociationAttribute>();
|
||||
for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) {
|
||||
map.putAll( mappedSuperclass.getAssociationAttributes() );
|
||||
}
|
||||
map.putAll( RootEntityClass.super.getAssociationAttributes() );
|
||||
return map;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@Override
|
||||
public Map<String, AssociationAttribute> getAssociationAttributes() {
|
||||
return associationAttributes.getValue();
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String, AttributeOverride>> attributeOverrideMap = new ValueHolder<Map<String, AttributeOverride>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String, AttributeOverride>>() {
|
||||
@Override
|
||||
public Map<String, AttributeOverride> initialize() {
|
||||
if ( CollectionHelper.isEmpty( getMappedSuperclasses() ) ) {
|
||||
return RootEntityClass.super.getAttributeOverrideMap();
|
||||
}
|
||||
Map<String, AttributeOverride> map = new HashMap<String, AttributeOverride>();
|
||||
for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) {
|
||||
map.putAll( mappedSuperclass.getAttributeOverrideMap() );
|
||||
}
|
||||
map.putAll( RootEntityClass.super.getAttributeOverrideMap() );
|
||||
return map;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private final ValueHolder<Map<String, AssociationOverride>> associationOverrideMap = new ValueHolder<Map<String, AssociationOverride>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String, AssociationOverride>>() {
|
||||
@Override
|
||||
public Map<String, AssociationOverride> initialize() {
|
||||
if ( CollectionHelper.isEmpty( getMappedSuperclasses() ) ) {
|
||||
return RootEntityClass.super.getAssociationOverrideMap();
|
||||
}
|
||||
Map<String, AssociationOverride> map = new HashMap<String, AssociationOverride>();
|
||||
for ( MappedSuperclass mappedSuperclass : getMappedSuperclasses() ) {
|
||||
map.putAll( mappedSuperclass.getAssociationOverrideMap() );
|
||||
}
|
||||
map.putAll( RootEntityClass.super.getAssociationOverrideMap() );
|
||||
return map;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, AssociationOverride> getAssociationOverrideMap() {
|
||||
return associationOverrideMap.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, AttributeOverride> getAttributeOverrideMap() {
|
||||
return attributeOverrideMap.getValue();
|
||||
}
|
||||
|
||||
private final ValueHolder<Map<String,MappedAttribute>> idAttributes = new ValueHolder<Map<String,MappedAttribute>>(
|
||||
new ValueHolder.DeferredInitializer<Map<String,MappedAttribute>>() {
|
||||
@Override
|
||||
public Map<String,MappedAttribute> initialize() {
|
||||
Map<String,MappedAttribute> attributes = new HashMap<String, MappedAttribute>();
|
||||
|
||||
// get all id attributes defined on this entity
|
||||
attributes.putAll( RootEntityClass.super.getIdAttributes() );
|
||||
|
||||
// now mapped super classes
|
||||
for ( MappedSuperclass mappedSuperclass : mappedSuperclasses ) {
|
||||
attributes.putAll( mappedSuperclass.getIdAttributes() );
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public Map<String,MappedAttribute> getIdAttributes() {
|
||||
return idAttributes.getValue();
|
||||
}
|
||||
|
||||
public AnnotationInstance getIdClassAnnotation() {
|
||||
// TODO: refactor
|
||||
final List<AnnotationInstance> idClassAnnotations = findIdAnnotations(
|
||||
JPADotNames.ID_CLASS
|
||||
);
|
||||
|
||||
return ( idClassAnnotations.size() > 0 ) ? idClassAnnotations.get( 0 ) : null;
|
||||
}
|
||||
|
||||
private IdType determineIdType() {
|
||||
Collection<MappedAttribute> idAttributes = getIdAttributes().values();
|
||||
int size = idAttributes.size();
|
||||
switch ( size ){
|
||||
case 0:
|
||||
return IdType.NONE;
|
||||
case 1:
|
||||
MappedAttribute idAttribute = idAttributes.iterator().next();
|
||||
switch ( idAttribute.getNature() ){
|
||||
case BASIC:
|
||||
return IdType.SIMPLE;
|
||||
case EMBEDDED_ID:
|
||||
return IdType.EMBEDDED;
|
||||
}
|
||||
default:
|
||||
return IdType.COMPOSED;
|
||||
}
|
||||
}
|
||||
|
||||
private List<AnnotationInstance> findIdAnnotations(DotName idAnnotationType) {
|
||||
List<AnnotationInstance> idAnnotationList = new ArrayList<AnnotationInstance>();
|
||||
|
||||
// check the class itself
|
||||
if ( getClassInfo().annotations().containsKey( idAnnotationType ) ) {
|
||||
idAnnotationList.addAll( getClassInfo().annotations().get( idAnnotationType ) );
|
||||
}
|
||||
|
||||
// check mapped super classes
|
||||
for ( MappedSuperclass mappedSuperclass : mappedSuperclasses ) {
|
||||
if ( mappedSuperclass.getClassInfo().annotations().containsKey( idAnnotationType ) ) {
|
||||
idAnnotationList.addAll( mappedSuperclass.getClassInfo().annotations().get( idAnnotationType ) );
|
||||
}
|
||||
}
|
||||
|
||||
return idAnnotationList;
|
||||
}
|
||||
|
||||
private void processDiscriminator() {
|
||||
final AnnotationInstance discriminatorColumnAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN
|
||||
);
|
||||
|
||||
final AnnotationInstance discriminatorFormulaAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(),
|
||||
HibernateDotNames.DISCRIMINATOR_FORMULA
|
||||
);
|
||||
|
||||
|
||||
Class<?> type = String.class; // string is the discriminator default
|
||||
if ( discriminatorFormulaAnnotation != null ) {
|
||||
String expression = JandexHelper.getValue( discriminatorFormulaAnnotation, "value", String.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
discriminatorFormula = new FormulaValue( null, expression );
|
||||
}
|
||||
discriminatorColumnValues = new Column( null ); //(stliu) give null here, will populate values below
|
||||
discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null
|
||||
if ( discriminatorColumnAnnotation != null ) {
|
||||
DiscriminatorType discriminatorType = JandexHelper.getEnumValue(
|
||||
discriminatorColumnAnnotation,
|
||||
"discriminatorType", DiscriminatorType.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) );
|
||||
switch ( discriminatorType ) {
|
||||
case STRING: {
|
||||
type = String.class;
|
||||
break;
|
||||
}
|
||||
case CHAR: {
|
||||
type = Character.class;
|
||||
break;
|
||||
}
|
||||
case INTEGER: {
|
||||
type = Integer.class;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType );
|
||||
}
|
||||
}
|
||||
|
||||
discriminatorColumnValues.setName(
|
||||
JandexHelper.getValue(
|
||||
discriminatorColumnAnnotation,
|
||||
"name",
|
||||
String.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
)
|
||||
);
|
||||
discriminatorColumnValues.setLength(
|
||||
JandexHelper.getValue(
|
||||
discriminatorColumnAnnotation,
|
||||
"length",
|
||||
Integer.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
)
|
||||
);
|
||||
discriminatorColumnValues.setColumnDefinition(
|
||||
JandexHelper.getValue(
|
||||
discriminatorColumnAnnotation,
|
||||
"columnDefinition",
|
||||
String.class,
|
||||
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class )
|
||||
)
|
||||
);
|
||||
}
|
||||
discriminatorType = type;
|
||||
|
||||
AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation(
|
||||
getClassInfo(), HibernateDotNames.DISCRIMINATOR_OPTIONS
|
||||
);
|
||||
if ( discriminatorOptionsAnnotation != null ) {
|
||||
isDiscriminatorForced = discriminatorOptionsAnnotation.value( "force" ).asBoolean();
|
||||
isDiscriminatorIncludedInSql = discriminatorOptionsAnnotation.value( "insert" ).asBoolean();
|
||||
}
|
||||
else {
|
||||
isDiscriminatorForced = false;
|
||||
isDiscriminatorIncludedInSql = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
|
||||
/**
|
||||
* Some annotation processing is identical between entity and attribute level (aka you can place the annotation on
|
||||
* entity as well as attribute level. This class tries to avoid code duplication for these cases.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class AnnotationParserHelper {
|
||||
|
||||
// should not be instantiated
|
||||
private AnnotationParserHelper() {
|
||||
|
||||
}
|
||||
|
||||
public static CustomSQL processCustomSqlAnnotation(DotName annotationName,
|
||||
Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
final AnnotationInstance sqlAnnotation = JandexHelper.getSingleAnnotation( annotations, annotationName );
|
||||
|
||||
return createCustomSQL( sqlAnnotation );
|
||||
}
|
||||
|
||||
public static CustomSQL processCustomSqlAnnotation(DotName annotationName,
|
||||
Map<DotName, List<AnnotationInstance>> annotations, ClassInfo target) {
|
||||
final AnnotationInstance sqlAnnotation = JandexHelper.getSingleAnnotation( annotations, annotationName, target );
|
||||
|
||||
return createCustomSQL( sqlAnnotation );
|
||||
}
|
||||
|
||||
public static CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation) {
|
||||
if ( customSqlAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String sql = customSqlAnnotation.value( "sql" ).asString();
|
||||
final boolean isCallable = customSqlAnnotation.value( "callable" ) != null
|
||||
&& customSqlAnnotation.value( "callable" ).asBoolean();
|
||||
|
||||
final ExecuteUpdateResultCheckStyle checkStyle = customSqlAnnotation.value( "check" ) == null
|
||||
? isCallable
|
||||
? ExecuteUpdateResultCheckStyle.NONE
|
||||
: ExecuteUpdateResultCheckStyle.COUNT
|
||||
: ExecuteUpdateResultCheckStyle.valueOf( customSqlAnnotation.value( "check" ).asEnum() );
|
||||
|
||||
return new CustomSQL( sql, isCallable, checkStyle );
|
||||
}
|
||||
|
||||
public static String determineCustomTuplizer(Map<DotName, List<AnnotationInstance>> annotations,
|
||||
AnnotationTarget target, ClassLoaderService classLoaderService){
|
||||
//tuplizer on field
|
||||
final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations, HibernateDotNames.TUPLIZERS, target
|
||||
);
|
||||
final AnnotationInstance tuplizerAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
HibernateDotNames.TUPLIZER,
|
||||
target
|
||||
);
|
||||
return determineCustomTuplizer(
|
||||
tuplizersAnnotation,
|
||||
tuplizerAnnotation,
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
|
||||
public static String determineCustomTuplizer(Map<DotName, List<AnnotationInstance>> annotations,
|
||||
ClassLoaderService classLoaderService){
|
||||
return determineCustomTuplizer( annotations, null, classLoaderService );
|
||||
}
|
||||
|
||||
public static String determineCustomTuplizer(
|
||||
final AnnotationInstance tuplizersAnnotation,
|
||||
final AnnotationInstance tuplizerAnnotation,
|
||||
final ClassLoaderService classLoaderService) {
|
||||
if ( tuplizersAnnotation != null ) {
|
||||
AnnotationInstance[] annotations = JandexHelper.getValue(
|
||||
tuplizersAnnotation,
|
||||
"value",
|
||||
AnnotationInstance[].class,
|
||||
classLoaderService
|
||||
);
|
||||
for ( final AnnotationInstance annotationInstance : annotations ) {
|
||||
final String impl = findTuplizerImpl( annotationInstance );
|
||||
if ( StringHelper.isNotEmpty( impl ) ) {
|
||||
return impl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( tuplizerAnnotation != null ) {
|
||||
final String impl = findTuplizerImpl( tuplizerAnnotation );
|
||||
if ( StringHelper.isNotEmpty( impl ) ) {
|
||||
return impl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String findTuplizerImpl(final AnnotationInstance tuplizerAnnotation) {
|
||||
final EntityMode mode;
|
||||
if ( tuplizerAnnotation.value( "entityModeType" ) != null ) {
|
||||
mode = EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() );
|
||||
}
|
||||
else if ( tuplizerAnnotation.value( "entityMode" ) != null ) {
|
||||
mode = EntityMode.parse( tuplizerAnnotation.value( "entityMode" ).asString() );
|
||||
}
|
||||
else {
|
||||
mode = EntityMode.POJO;
|
||||
}
|
||||
return mode == EntityMode.POJO ? tuplizerAnnotation.value( "impl" ).asString() : null;
|
||||
}
|
||||
|
||||
public static Class<?> resolveCollectionElementType(
|
||||
ResolvedMember resolvedMember, Map<DotName,
|
||||
List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
final AnnotationInstance annotation;
|
||||
final String targetElementName;
|
||||
if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ) ) {
|
||||
annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY );
|
||||
targetElementName = "targetEntity";
|
||||
}
|
||||
else if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) ) {
|
||||
annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY );
|
||||
targetElementName = "targetEntity";
|
||||
}
|
||||
else if ( JandexHelper.containsSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION ) ) {
|
||||
annotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION );
|
||||
targetElementName = "targetClass";
|
||||
}
|
||||
else {
|
||||
annotation = null;
|
||||
targetElementName = null;
|
||||
}
|
||||
if ( annotation != null && annotation.value( targetElementName ) != null ) {
|
||||
return context.locateClassByName(
|
||||
JandexHelper.getValue( annotation, targetElementName, String.class,
|
||||
context.getServiceRegistry().getService( ClassLoaderService.class ) )
|
||||
);
|
||||
}
|
||||
if ( resolvedMember.getType().isArray() ) {
|
||||
return resolvedMember.getType().getArrayElementType().getErasedType();
|
||||
}
|
||||
if ( resolvedMember.getType().getTypeParameters().isEmpty() ) {
|
||||
return null; // no generic at all
|
||||
}
|
||||
Class<?> type = resolvedMember.getType().getErasedType();
|
||||
if ( Collection.class.isAssignableFrom( type ) ) {
|
||||
return resolvedMember.getType().getTypeParameters().get( 0 ).getErasedType();
|
||||
}
|
||||
else if ( Map.class.isAssignableFrom( type ) ) {
|
||||
return resolvedMember.getType().getTypeParameters().get( 1 ).getErasedType();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static SingularAttributeBinding.NaturalIdMutability checkNaturalId(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
final AnnotationInstance naturalIdAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
HibernateDotNames.NATURAL_ID
|
||||
);
|
||||
if ( naturalIdAnnotation == null ) {
|
||||
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
|
||||
}
|
||||
final boolean mutable = naturalIdAnnotation.value( "mutable" ) != null && naturalIdAnnotation.value( "mutable" )
|
||||
.asBoolean();
|
||||
return mutable ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE;
|
||||
}
|
||||
|
||||
public static boolean isPersistentMember(Set<String> transientNames, Set<String> explicitlyConfiguredMemberNames, Member member) {
|
||||
if ( !ReflectHelper.isProperty( member ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( member instanceof Field && Modifier.isStatic( member.getModifiers() ) ) {
|
||||
// static fields are no instance variables! Catches also the case of serialVersionUID
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( member instanceof Method && Method.class.cast( member ).getReturnType().equals( void.class ) ){
|
||||
// not a getter
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( transientNames.contains( member.getName() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !explicitlyConfiguredMemberNames.contains( ReflectHelper.getPropertyName( member ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class ClassmateHelper {
|
||||
/**
|
||||
* @param clazz
|
||||
* @param contextResolveType
|
||||
* @param bindingContext
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, ResolvedTypeWithMembers> resolveClassHierarchyTypesFromAttributeType(
|
||||
final Class<?> clazz,
|
||||
final ResolvedType contextResolveType,
|
||||
final AnnotationBindingContext bindingContext) {
|
||||
if ( clazz == null ) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
final Map<String, ResolvedTypeWithMembers> resolvedTypes = new HashMap<String, ResolvedTypeWithMembers>();
|
||||
ResolvedType resolvedType = resolveClassType( clazz, contextResolveType, bindingContext );
|
||||
// String className = clazz.getName();
|
||||
if ( resolvedType != null ) {
|
||||
//move this out of loop, since it returns all members from the hierarchy
|
||||
final ResolvedTypeWithMembers resolvedTypeWithMembers = bindingContext.getMemberResolver()
|
||||
.resolve( resolvedType, null, null );
|
||||
Class<?> currentClass = clazz;
|
||||
while ( currentClass != null && !Object.class.equals( currentClass ) ) {
|
||||
resolvedTypes.put( currentClass.getName(), resolvedTypeWithMembers );
|
||||
currentClass = currentClass.getSuperclass();
|
||||
|
||||
}
|
||||
|
||||
// while ( resolvedType != null && !Object.class.equals( resolvedType.getErasedType() ) ) {
|
||||
// resolvedTypes.put( className, resolvedTypeWithMembers );
|
||||
// resolvedType = resolvedType.getParentClass();
|
||||
// if ( resolvedType != null ) {
|
||||
// className = resolvedType.getErasedType().getName();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
return resolvedTypes;
|
||||
}
|
||||
|
||||
private static ResolvedType resolveClassType(
|
||||
final Class<?> clazz,
|
||||
final ResolvedType contextResolveType,
|
||||
final AnnotationBindingContext bindingContext) {
|
||||
if ( contextResolveType == null || contextResolveType.isPrimitive() || clazz.isPrimitive() || clazz.getTypeParameters().length == 0 ) {
|
||||
return bindingContext.getTypeResolver().resolve( clazz );
|
||||
}
|
||||
else if ( contextResolveType.canCreateSubtype( clazz ) ) {
|
||||
return bindingContext.getTypeResolver()
|
||||
.resolve(
|
||||
clazz,
|
||||
contextResolveType.getTypeParameters()
|
||||
.toArray( new ResolvedType[contextResolveType.getTypeBindings().size()] )
|
||||
);
|
||||
}
|
||||
else if ( contextResolveType.isArray() ) {
|
||||
return resolveClassType( clazz, contextResolveType.getArrayElementType(), bindingContext );
|
||||
}
|
||||
else if ( contextResolveType.isInstanceOf( Collection.class ) || contextResolveType.isInstanceOf( Map.class ) ) {
|
||||
return resolveClassType( clazz, contextResolveType.getTypeParameters(), bindingContext );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ResolvedType resolveClassType(
|
||||
final Class<?> clazz,
|
||||
final List<ResolvedType> contextResolveTypes,
|
||||
final AnnotationBindingContext bindingContext) {
|
||||
if ( contextResolveTypes != null ) {
|
||||
for ( ResolvedType contextResolveType : contextResolveTypes ) {
|
||||
ResolvedType type = resolveClassType( clazz, contextResolveType, bindingContext );
|
||||
if ( type != null ) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
|
@ -1,497 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.EntityHierarchyImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.JoinedSubclassEntitySourceImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.RootEntitySourceImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.SubclassEntitySourceImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.RootEntityClass;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
|
||||
|
||||
/**
|
||||
* Given a (jandex) annotation index, 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 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
|
||||
* to the metamodel.
|
||||
*
|
||||
* @param bindingContext The binding context, giving access to needed services and information
|
||||
*
|
||||
* @return a set of {@code EntityHierarchy} instances.
|
||||
*/
|
||||
public static Set<EntityHierarchy> createEntityHierarchies(AnnotationBindingContext bindingContext) {
|
||||
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;
|
||||
}
|
||||
if ( !isEntityClass( classInfo ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ClassInfo rootClassInfo = findRootEntityClassInfo( classInfo );
|
||||
List<ClassInfo> rootClassWithAllSubclasses = new ArrayList<ClassInfo>();
|
||||
|
||||
// collect the current root entity and all its subclasses
|
||||
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()
|
||||
);
|
||||
List<ClassInfo> mappedSuperclasses = findMappedSuperclasses( index, rootClassInfo );
|
||||
|
||||
// the root entity might have some mapped super classes which we have to take into consideration
|
||||
// for inheritance type and default access
|
||||
rootClassWithAllSubclasses.addAll( mappedSuperclasses );
|
||||
|
||||
AccessType defaultAccessType = determineDefaultAccessType( rootClassWithAllSubclasses );
|
||||
InheritanceType hierarchyInheritanceType = determineInheritanceType(
|
||||
rootClassInfo,
|
||||
rootClassWithAllSubclasses
|
||||
);
|
||||
|
||||
// create the root entity source
|
||||
RootEntityClass rootEntityClass = new RootEntityClass(
|
||||
rootClassInfo,
|
||||
resolvedTypeWithMembers,
|
||||
mappedSuperclasses,
|
||||
defaultAccessType,
|
||||
hierarchyInheritanceType,
|
||||
hasSubclasses,
|
||||
bindingContext
|
||||
);
|
||||
RootEntitySourceImpl rootSource = new RootEntitySourceImpl( rootEntityClass );
|
||||
|
||||
addSubclassEntitySources(
|
||||
resolvedTypeWithMembers,
|
||||
defaultAccessType,
|
||||
hierarchyInheritanceType,
|
||||
rootEntityClass,
|
||||
rootSource
|
||||
);
|
||||
|
||||
hierarchies.add( new EntityHierarchyImpl( rootSource, hierarchyInheritanceType ) );
|
||||
}
|
||||
return hierarchies;
|
||||
}
|
||||
|
||||
private void addSubclassEntitySources(
|
||||
Map<String, ResolvedTypeWithMembers> resolvedTypeWithMembers,
|
||||
AccessType defaultAccessType,
|
||||
InheritanceType hierarchyInheritanceType,
|
||||
EntityClass entityClass,
|
||||
EntitySource entitySource) {
|
||||
List<ClassInfo> subClassInfoList = classToDirectSubclassMap.get( DotName.createSimple( entitySource.getClassName() ) );
|
||||
if ( subClassInfoList == null ) {
|
||||
return;
|
||||
}
|
||||
for ( ClassInfo subClassInfo : subClassInfoList ) {
|
||||
resolvedTypeWithMembers.putAll( resolveGenerics( subClassInfo.name().toString() ) );
|
||||
ResolvedTypeWithMembers typeWithMembers = resolvedTypeWithMembers.get( subClassInfo.toString() );
|
||||
if ( typeWithMembers == null ) {
|
||||
throw new AssertionFailure( "Missing generic information for " + subClassInfo.toString() );
|
||||
}
|
||||
EntityClass subclassEntityClass = new EntityClass(
|
||||
subClassInfo,
|
||||
typeWithMembers,
|
||||
entityClass,
|
||||
defaultAccessType,
|
||||
hierarchyInheritanceType,
|
||||
bindingContext
|
||||
);
|
||||
SubclassEntitySource subclassEntitySource = hierarchyInheritanceType == InheritanceType.JOINED ?
|
||||
new JoinedSubclassEntitySourceImpl( subclassEntityClass, entitySource )
|
||||
: new SubclassEntitySourceImpl( subclassEntityClass, entitySource );
|
||||
entitySource.add( subclassEntitySource );
|
||||
addSubclassEntitySources(
|
||||
resolvedTypeWithMembers,
|
||||
defaultAccessType,
|
||||
hierarchyInheritanceType,
|
||||
subclassEntityClass,
|
||||
subclassEntitySource
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 info the class info representing an entity
|
||||
*
|
||||
* @return Finds the root entity starting at the entity given by {@code info}
|
||||
*/
|
||||
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 = bindingContext.getIndex().getClassByName( superName );
|
||||
if ( tmpInfo == null && superName != null ) {
|
||||
Class clazz = bindingContext.locateClassByName( superName.toString() );
|
||||
if ( clazz != null ) {
|
||||
throw new AnnotationException(
|
||||
info.name()
|
||||
.toString() + "'s parent class [" + clazz.getName() + "] is not added into Jandex repository"
|
||||
);
|
||||
}else {
|
||||
throw new AnnotationException(
|
||||
info.name()
|
||||
.toString() + "'s parent class [" + superName.toString() + "] doesn't exist in classpath"
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( isEntityClass( tmpInfo ) ) {
|
||||
rootEntity = tmpInfo;
|
||||
}
|
||||
superName = tmpInfo.superName();
|
||||
}
|
||||
return rootEntity;
|
||||
}
|
||||
|
||||
private static List<ClassInfo> findMappedSuperclasses(IndexView index, ClassInfo info) {
|
||||
List<ClassInfo> mappedSuperclasses = new ArrayList<ClassInfo>( );
|
||||
DotName superName = info.superName();
|
||||
// walk up the hierarchy until java.lang.Object
|
||||
while ( !JandexHelper.OBJECT.equals( superName ) ) {
|
||||
ClassInfo tmpInfo = index.getClassByName( superName );
|
||||
if ( isMappedSuperclass( tmpInfo ) ) {
|
||||
mappedSuperclasses.add( tmpInfo );
|
||||
}
|
||||
superName = tmpInfo.superName();
|
||||
}
|
||||
return mappedSuperclasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does several things.
|
||||
* <ul>
|
||||
* <li>Collect all java subclasses (recursive) of {@code classInfo} in {@code rootClassWithAllSubclasses}. </li>
|
||||
* <li>Keeping track of all processed classed annotated with {@code @Entity}</li>
|
||||
* <li>Building up a map of class to direct subclass list</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param classInfo the current class info
|
||||
* @param rootClassWithAllSubclasses used to collect all classes in the hierarchy starting at {@code classInfo}
|
||||
*/
|
||||
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() );
|
||||
|
||||
for ( ClassInfo subClassInfo : subClasses ) {
|
||||
if ( !isEntityClass( subClassInfo ) ) {
|
||||
MappingAssertion.assertSubEntityIsNotEmbeddable( subClassInfo );
|
||||
continue;
|
||||
}
|
||||
addSubClassToSubclassMap( classInfo.name(), subClassInfo, classToDirectSubclassMap );
|
||||
processHierarchy( subClassInfo, rootClassWithAllSubclasses );
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSubClassToSubclassMap(DotName name, ClassInfo subClassInfo, Map<DotName, List<ClassInfo>> classToDirectSubclassMap) {
|
||||
if ( classToDirectSubclassMap.containsKey( name ) ) {
|
||||
classToDirectSubclassMap.get( name ).add( subClassInfo );
|
||||
}
|
||||
else {
|
||||
List<ClassInfo> subclassList = new ArrayList<ClassInfo>();
|
||||
subclassList.add( subClassInfo );
|
||||
classToDirectSubclassMap.put( name, subclassList );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the class info represents an entity.
|
||||
*
|
||||
* @param info the jandex class info
|
||||
*
|
||||
* @return {@code true} if the class represented by {@code info} is annotated with {@code @Entity}, {@code false} otherwise.
|
||||
*/
|
||||
private static boolean isEntityClass(ClassInfo info) {
|
||||
if ( info == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we are only interested in building the class hierarchies for @Entity
|
||||
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.ENTITY );
|
||||
if ( jpaEntityAnnotation == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// some sanity checks
|
||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info, JPADotNames.MAPPED_SUPERCLASS
|
||||
);
|
||||
String className = info.toString();
|
||||
MappingAssertion.assertNotEntityAndMappedSuperClass(
|
||||
jpaEntityAnnotation,
|
||||
mappedSuperClassAnnotation,
|
||||
className
|
||||
);
|
||||
|
||||
AnnotationInstance embeddableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info, JPADotNames.EMBEDDABLE
|
||||
);
|
||||
MappingAssertion.assertNotEntityAndEmbeddable(
|
||||
jpaEntityAnnotation,
|
||||
embeddableAnnotation,
|
||||
className );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the class info represents a mapped superclass.
|
||||
*
|
||||
* @param info the jandex class info
|
||||
*
|
||||
* @return {@code true} if the class represented by {@code info} is annotated with {@code @MappedSuperclass}, {@code false} otherwise.
|
||||
*/
|
||||
private static boolean isMappedSuperclass(ClassInfo info) {
|
||||
if ( info == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we are only interested in building the class hierarchies for @Entity
|
||||
AnnotationInstance mappedSuperclassAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info,
|
||||
JPADotNames.MAPPED_SUPERCLASS
|
||||
);
|
||||
return mappedSuperclassAnnotation != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classes the classes in the hierarchy
|
||||
*
|
||||
* @return Returns the default access type for the configured class hierarchy independent of explicit
|
||||
* {@code AccessType} annotations. The default access type is determined by the placement of the
|
||||
* annotations.
|
||||
*/
|
||||
private static AccessType determineDefaultAccessType(List<ClassInfo> classes) {
|
||||
AccessType accessTypeByEmbeddedIdPlacement = null;
|
||||
AccessType accessTypeByIdPlacement = null;
|
||||
for ( ClassInfo info : classes ) {
|
||||
List<AnnotationInstance> idAnnotations = info.annotations().get( JPADotNames.ID );
|
||||
List<AnnotationInstance> embeddedIdAnnotations = info.annotations().get( JPADotNames.EMBEDDED_ID );
|
||||
|
||||
if ( CollectionHelper.isNotEmpty( embeddedIdAnnotations ) ) {
|
||||
accessTypeByEmbeddedIdPlacement = determineAccessTypeByIdPlacement( embeddedIdAnnotations );
|
||||
}
|
||||
if ( CollectionHelper.isNotEmpty( idAnnotations ) ) {
|
||||
accessTypeByIdPlacement = determineAccessTypeByIdPlacement( idAnnotations );
|
||||
}
|
||||
}
|
||||
if ( accessTypeByEmbeddedIdPlacement != null ) {
|
||||
return accessTypeByEmbeddedIdPlacement;
|
||||
}
|
||||
else if ( accessTypeByIdPlacement != null ) {
|
||||
return accessTypeByIdPlacement;
|
||||
}
|
||||
else {
|
||||
return throwIdNotFoundAnnotationException( classes );
|
||||
}
|
||||
}
|
||||
|
||||
private static AccessType determineAccessTypeByIdPlacement(List<AnnotationInstance> idAnnotations) {
|
||||
AccessType accessType = null;
|
||||
for ( AnnotationInstance annotation : idAnnotations ) {
|
||||
AccessType tmpAccessType;
|
||||
if ( annotation.target() instanceof FieldInfo ) {
|
||||
tmpAccessType = AccessType.FIELD;
|
||||
}
|
||||
else if ( annotation.target() instanceof MethodInfo ) {
|
||||
tmpAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException( "Invalid placement of @Id annotation" );
|
||||
}
|
||||
|
||||
if ( accessType == null ) {
|
||||
accessType = tmpAccessType;
|
||||
}
|
||||
else {
|
||||
if ( !accessType.equals( tmpAccessType ) ) {
|
||||
throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " );
|
||||
}
|
||||
}
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private static InheritanceType determineInheritanceType(ClassInfo rootClassInfo, List<ClassInfo> classes) {
|
||||
if(classes.size() == 1) {
|
||||
return InheritanceType.NO_INHERITANCE;
|
||||
}
|
||||
|
||||
// if we have more than one entity class the default is SINGLE_TABLE
|
||||
InheritanceType inheritanceType = InheritanceType.SINGLE_TABLE;
|
||||
AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation(
|
||||
rootClassInfo, JPADotNames.INHERITANCE
|
||||
);
|
||||
if ( inheritanceAnnotation != null && inheritanceAnnotation.value( "strategy" )!=null) {
|
||||
String enumName = inheritanceAnnotation.value( "strategy" ).asEnum();
|
||||
javax.persistence.InheritanceType jpaInheritanceType = Enum.valueOf(
|
||||
javax.persistence.InheritanceType.class, enumName
|
||||
);
|
||||
inheritanceType = InheritanceType.get( jpaInheritanceType );
|
||||
}
|
||||
|
||||
// sanity check that the is no other @Inheritance annotation in the hierarchy
|
||||
for ( ClassInfo info : classes ) {
|
||||
if ( rootClassInfo.equals( info ) ) {
|
||||
continue;
|
||||
}
|
||||
inheritanceAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info, JPADotNames.INHERITANCE
|
||||
);
|
||||
if ( inheritanceAnnotation != null ) {
|
||||
LOG.warn(
|
||||
String.format(
|
||||
"The inheritance type for %s should be specified only on the root entity %s. Ignoring...",
|
||||
info.name(),
|
||||
rootClassInfo.name().toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return inheritanceType;
|
||||
}
|
||||
|
||||
private static AccessType throwIdNotFoundAnnotationException(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "Unable to determine identifier attribute for class hierarchy consisting of the classe(s) " );
|
||||
builder.append( hierarchyListString( classes ) );
|
||||
throw new AnnotationException( builder.toString() );
|
||||
}
|
||||
|
||||
private static String hierarchyListString(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "[" );
|
||||
|
||||
int count = 0;
|
||||
for ( ClassInfo info : classes ) {
|
||||
builder.append( info.name().toString() );
|
||||
if ( count < classes.size() - 1 ) {
|
||||
builder.append( ", " );
|
||||
}
|
||||
count++;
|
||||
}
|
||||
builder.append( "]" );
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this is incorrect, we should do it from bottom to top, not inverse, since the actual type info should be dedined in the sub class.
|
||||
* we need this info to resolve super class type.
|
||||
*/
|
||||
private 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 );
|
||||
while ( resolvedType!= null && !Object.class.equals( resolvedType.getErasedType() ) ) {
|
||||
final ResolvedTypeWithMembers resolvedTypeWithMembers = bindingContext.getMemberResolver()
|
||||
.resolve( resolvedType, null, null );
|
||||
resolvedTypes.put( className, resolvedTypeWithMembers );
|
||||
|
||||
resolvedType = resolvedType.getParentClass();
|
||||
if ( resolvedType != null ) {
|
||||
className = resolvedType.getErasedType().getName();
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedTypes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.util;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.PostPersist;
|
||||
import javax.persistence.PostRemove;
|
||||
import javax.persistence.PostUpdate;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.PreRemove;
|
||||
import javax.persistence.PreUpdate;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
import org.jboss.jandex.Type;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.JpaCallbackSourceImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.MappedSuperclass;
|
||||
import org.hibernate.metamodel.source.internal.jandex.PseudoJpaDotNames;
|
||||
import org.hibernate.metamodel.spi.source.JpaCallbackSource;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class JPAListenerHelper {
|
||||
private static final Map<Class<?>, DotName> EVENT_TYPE;
|
||||
|
||||
static {
|
||||
EVENT_TYPE = new HashMap<Class<?>, DotName>( 7 );
|
||||
EVENT_TYPE.put( PrePersist.class, JPADotNames.PRE_PERSIST );
|
||||
EVENT_TYPE.put( PreRemove.class, JPADotNames.PRE_REMOVE );
|
||||
EVENT_TYPE.put( PreUpdate.class, JPADotNames.PRE_UPDATE );
|
||||
EVENT_TYPE.put( PostLoad.class, JPADotNames.POST_LOAD );
|
||||
EVENT_TYPE.put( PostPersist.class, JPADotNames.POST_PERSIST );
|
||||
EVENT_TYPE.put( PostRemove.class, JPADotNames.POST_REMOVE );
|
||||
EVENT_TYPE.put( PostUpdate.class, JPADotNames.POST_UPDATE );
|
||||
|
||||
}
|
||||
|
||||
private final EntityClass entityClass;
|
||||
private final EntityBindingContext context;
|
||||
private final List<ConfiguredClass> mappingClassHierarchy;
|
||||
|
||||
public JPAListenerHelper(EntityClass entityClass) {
|
||||
this.entityClass = entityClass;
|
||||
this.context = entityClass.getLocalBindingContext();
|
||||
this.mappingClassHierarchy = buildHierarchy();
|
||||
}
|
||||
|
||||
private List<ConfiguredClass> buildHierarchy() {
|
||||
List<ConfiguredClass> list = new ArrayList<ConfiguredClass>();
|
||||
list.add( entityClass );
|
||||
if ( !excludeSuperClassListeners( entityClass.getClassInfo() ) ) {
|
||||
for ( MappedSuperclass mappedSuperclass : entityClass.getMappedSuperclasses() ) {
|
||||
list.add( mappedSuperclass );
|
||||
if ( excludeSuperClassListeners( mappedSuperclass.getClassInfo() ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<AnnotationInstance> findAllEntityListeners() {
|
||||
List<AnnotationInstance> result = new ArrayList<AnnotationInstance>();
|
||||
for ( final ConfiguredClass configuredClass : mappingClassHierarchy ) {
|
||||
List<AnnotationInstance> list = configuredClass.getClassInfo()
|
||||
.annotations()
|
||||
.get( JPADotNames.ENTITY_LISTENERS );
|
||||
if ( CollectionHelper.isNotEmpty( list ) ) {
|
||||
result.addAll( list );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public List<JpaCallbackSource> bindJPAListeners() {
|
||||
final List<JpaCallbackSource> callbackClassList = new ArrayList<JpaCallbackSource>();
|
||||
bindEntityCallbackEvents( callbackClassList );
|
||||
bindEntityListeners( callbackClassList );
|
||||
bindDefaultListeners( callbackClassList );
|
||||
return callbackClassList;
|
||||
}
|
||||
|
||||
private void bindEntityCallbackEvents(List<JpaCallbackSource> callbackClassList) {
|
||||
Map<String, Void> overrideMethodCheck = new HashMap<String, Void>();
|
||||
for ( final ConfiguredClass configuredClass : mappingClassHierarchy ) {
|
||||
try {
|
||||
internalProcessCallbacks(
|
||||
configuredClass.getClassInfo(),
|
||||
callbackClassList,
|
||||
false,
|
||||
false,
|
||||
overrideMethodCheck
|
||||
);
|
||||
}
|
||||
catch ( PersistenceException error ) {
|
||||
throw new PersistenceException( error.getMessage() + "entity listener " + configuredClass.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindEntityListeners(List<JpaCallbackSource> callbackClassList) {
|
||||
List<AnnotationInstance> entityListenerAnnotations = findAllEntityListeners();
|
||||
for ( AnnotationInstance annotation : entityListenerAnnotations ) {
|
||||
Type[] types = annotation.value().asClassArray();
|
||||
for ( int i = types.length - 1; i >= 0; i-- ) {
|
||||
String callbackClassName = types[i].name().toString();
|
||||
try {
|
||||
processJpaCallbacks( callbackClassName, true, callbackClassList, null );
|
||||
}
|
||||
catch ( PersistenceException error ) {
|
||||
throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processJpaCallbacks(
|
||||
final String instanceCallbackClassName,
|
||||
final boolean isListener,
|
||||
final List<JpaCallbackSource> callbackClassList,
|
||||
final Map<String, Void> overrideMethodCheck) {
|
||||
final ClassInfo callbackClassInfo = findClassInfoByName( instanceCallbackClassName );
|
||||
internalProcessCallbacks( callbackClassInfo, callbackClassList, isListener, false, overrideMethodCheck );
|
||||
}
|
||||
|
||||
|
||||
private void bindDefaultListeners(final List<JpaCallbackSource> callbackClassList) {
|
||||
// Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded)
|
||||
|
||||
Collection<AnnotationInstance> defaultEntityListenerAnnotations = context
|
||||
.getIndex()
|
||||
.getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS );
|
||||
for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) {
|
||||
for ( Type callbackClass : annotation.value().asClassArray() ) {
|
||||
String callbackClassName = callbackClass.name().toString();
|
||||
ClassInfo callbackClassInfo = findClassInfoByName( callbackClassName );
|
||||
try {
|
||||
processDefaultJpaCallbacks( callbackClassInfo, callbackClassList );
|
||||
}
|
||||
catch ( PersistenceException error ) {
|
||||
throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean excludeDefaultListeners(ClassInfo classInfo) {
|
||||
return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_DEFAULT_LISTENERS );
|
||||
}
|
||||
|
||||
private static boolean excludeSuperClassListeners(ClassInfo classInfo) {
|
||||
return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS );
|
||||
}
|
||||
|
||||
private static boolean isNotRootObject(DotName name) {
|
||||
return name != null && !JandexHelper.OBJECT.equals( name );
|
||||
}
|
||||
|
||||
private void processDefaultJpaCallbacks(
|
||||
final ClassInfo callbackClassInfo,
|
||||
final List<JpaCallbackSource> jpaCallbackClassList) {
|
||||
if ( excludeDefaultListeners( callbackClassInfo ) ) {
|
||||
return;
|
||||
}
|
||||
// Process superclass first if available and not excluded
|
||||
if ( !excludeSuperClassListeners( callbackClassInfo ) ) {
|
||||
DotName superName = callbackClassInfo.superName();
|
||||
if ( isNotRootObject( superName ) ) {
|
||||
processDefaultJpaCallbacks( findClassInfoByName( superName.toString() ), jpaCallbackClassList );
|
||||
}
|
||||
}
|
||||
internalProcessCallbacks( callbackClassInfo, jpaCallbackClassList, true, true, null );
|
||||
}
|
||||
|
||||
private ClassInfo findClassInfoByName(String name) {
|
||||
ClassInfo classInfo = context.getClassInfo( name );
|
||||
if ( classInfo == null ) {
|
||||
JandexHelper.throwNotIndexException( name );
|
||||
}
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
private void internalProcessCallbacks(
|
||||
final ClassInfo callbackClassInfo,
|
||||
final List<JpaCallbackSource> callbackClassList,
|
||||
final boolean isListener,
|
||||
final boolean isDefault,
|
||||
final Map<String, Void> overrideMethodCheck) {
|
||||
final Map<Class<?>, String> callbacksByType = new HashMap<Class<?>, String>( 7 );
|
||||
createCallback(
|
||||
PrePersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PreRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PreUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PostLoad.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PostPersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PostRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
createCallback(
|
||||
PostUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck
|
||||
);
|
||||
if ( !callbacksByType.isEmpty() ) {
|
||||
final String name = callbackClassInfo.name().toString();
|
||||
final JpaCallbackSource callbackSource = new JpaCallbackSourceImpl( name, callbacksByType, isListener );
|
||||
callbackClassList.add( 0, callbackSource );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist},
|
||||
* {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad},
|
||||
* {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}.
|
||||
* @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name.
|
||||
* @param callbackClassInfo Jandex ClassInfo of callback method's container, should be either entity/mapped superclass or entity listener class.
|
||||
* @param isListener Is this callback method defined in an entity listener class or not.
|
||||
*/
|
||||
private void createCallback(
|
||||
final Class callbackTypeClass,
|
||||
final Map<Class<?>, String> callbacksByClass,
|
||||
final ClassInfo callbackClassInfo,
|
||||
final boolean isListener,
|
||||
final boolean isDefault,
|
||||
final Map<String, Void> overrideMethodCheck) {
|
||||
|
||||
final Collection<AnnotationInstance> annotationInstances;
|
||||
if ( isDefault ) {
|
||||
annotationInstances = context.getIndex().getAnnotations( EVENT_TYPE.get( callbackTypeClass ) );
|
||||
}
|
||||
else {
|
||||
List<AnnotationInstance> temp = callbackClassInfo.annotations().get( EVENT_TYPE.get( callbackTypeClass ) );
|
||||
annotationInstances = temp != null ? temp : Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
//there should be only one callback method per callbackType, isn't it?
|
||||
//so only one callbackAnnotation?
|
||||
for ( AnnotationInstance callbackAnnotation : annotationInstances ) {
|
||||
MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target();
|
||||
validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener );
|
||||
final String name = methodInfo.name();
|
||||
if ( overrideMethodCheck != null && overrideMethodCheck.containsKey( name ) ) {
|
||||
continue;
|
||||
}
|
||||
else if ( overrideMethodCheck != null ) {
|
||||
overrideMethodCheck.put( name, null );
|
||||
}
|
||||
if ( !isDefault ) {
|
||||
callbacksByClass.put( callbackTypeClass, name );
|
||||
}
|
||||
else if ( methodInfo.declaringClass().name().equals( callbackClassInfo.name() ) ) {
|
||||
if ( methodInfo.args().length != 1 ) {
|
||||
throw new PersistenceException(
|
||||
String.format(
|
||||
"Callback method %s must have exactly one argument defined as either Object or %s in ",
|
||||
name,
|
||||
entityClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
callbacksByClass.put( callbackTypeClass, name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applying JPA Spec rules to validate listener callback method mapping.
|
||||
*
|
||||
* @param methodInfo The lifecycle callback method.
|
||||
* @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist},
|
||||
* {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad},
|
||||
* {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}.
|
||||
* @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name.
|
||||
* @param isListener Is this callback method defined in an entity listener class or not.
|
||||
*/
|
||||
private void validateMethod(
|
||||
MethodInfo methodInfo,
|
||||
Class callbackTypeClass,
|
||||
Map<Class<?>, String> callbacksByClass,
|
||||
boolean isListener) {
|
||||
final String name = methodInfo.name();
|
||||
|
||||
if ( methodInfo.returnType().kind() != Type.Kind.VOID ) {
|
||||
throw new PersistenceException( "Callback method " + name + " must have a void return type in " );
|
||||
}
|
||||
if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) {
|
||||
throw new PersistenceException( "Callback method " + name + " must not be static or final in " );
|
||||
}
|
||||
Type[] argTypes = methodInfo.args();
|
||||
|
||||
if ( isListener ) {
|
||||
if ( argTypes.length != 1 ) {
|
||||
throw new PersistenceException( "Callback method " + name + " must have exactly one argument in " );
|
||||
}
|
||||
String argTypeName = argTypes[0].name().toString();
|
||||
if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( entityClass.getName() ) ) {
|
||||
Class typeClass = entityClass.getLocalBindingContext().locateClassByName( argTypeName );
|
||||
if ( !typeClass.isAssignableFrom( entityClass.getConfiguredClass() ) ) {
|
||||
throw new PersistenceException(
|
||||
"The argument for callback method " + name +
|
||||
" must be defined as either Object or " + entityClass.getName() + " in "
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( argTypes.length != 0 ) {
|
||||
throw new PersistenceException( "Callback method " + name + " must have no arguments in " );
|
||||
}
|
||||
if ( callbacksByClass.containsKey( callbackTypeClass ) ) {
|
||||
throw new PersistenceException(
|
||||
"Only one method may be annotated as a " + callbackTypeClass.getSimpleName() +
|
||||
" callback method in "
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations.util;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
|
||||
/**
|
||||
* Utility class that applying some mapping assertion.
|
||||
*
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class MappingAssertion {
|
||||
/**
|
||||
* Check if a class is wrongly placed both {@link javax.persistence.Entity @Entity} and {@link javax.persistence.MappedSuperclass @MappedSuperclass} annotations.
|
||||
*
|
||||
* @param jpaEntityAnnotation The {@link javax.persistence.Entity @Entity} annotation instance.
|
||||
* @param mappedSuperClassAnnotation The {@link javax.persistence.MappedSuperclass @MappedSuperclass} annotation instance.
|
||||
* @param className Class name that being asserted.
|
||||
*/
|
||||
static void assertNotEntityAndMappedSuperClass(
|
||||
AnnotationInstance jpaEntityAnnotation,
|
||||
AnnotationInstance mappedSuperClassAnnotation,
|
||||
String className) {
|
||||
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
|
||||
throw new AnnotationException(
|
||||
"An entity cannot be annotated with both @Entity and @MappedSuperclass. " + className + " has both annotations."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a class is wrongly placed both {@link javax.persistence.Entity @Entity} and {@link javax.persistence.Embeddable @Embeddable} annotations.
|
||||
*
|
||||
* @param jpaEntityAnnotation The {@link javax.persistence.Entity @Entity} annotation instance.
|
||||
* @param embeddableAnnotation The {@link javax.persistence.Embeddable @Embeddable} annotation instance.
|
||||
* @param className Class name that being asserted.
|
||||
*/
|
||||
static void assertNotEntityAndEmbeddable(AnnotationInstance jpaEntityAnnotation, AnnotationInstance embeddableAnnotation, String className) {
|
||||
if ( jpaEntityAnnotation != null && embeddableAnnotation != null ) {
|
||||
throw new AnnotationException(
|
||||
"An entity cannot be annotated with both @Entity and @Embeddable. " + className + " has both annotations."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the sub-entity has {@link javax.persistence.Embeddable @Embeddable}. From the JPA Spec,
|
||||
* a sub entity class can not has such annotation.
|
||||
*
|
||||
* @param subClassInfo The sub entity {@link ClassInfo class}.
|
||||
*/
|
||||
static void assertSubEntityIsNotEmbeddable(ClassInfo subClassInfo) {
|
||||
if ( JandexHelper.containsSingleAnnotation( subClassInfo, JPADotNames.EMBEDDABLE ) ) {
|
||||
throw new AnnotationException( "An embeddable cannot extend an entity: " + subClassInfo );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.hbm;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.RootEntitySource;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityHierarchyImpl implements EntityHierarchy {
|
||||
private final RootEntitySourceImpl rootEntitySource;
|
||||
private InheritanceType hierarchyInheritanceType = InheritanceType.NO_INHERITANCE;
|
||||
|
||||
public EntityHierarchyImpl(RootEntitySourceImpl rootEntitySource) {
|
||||
this.rootEntitySource = rootEntitySource;
|
||||
this.rootEntitySource.injectHierarchy( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public InheritanceType getHierarchyInheritanceType() {
|
||||
return hierarchyInheritanceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootEntitySource getRootEntitySource() {
|
||||
return rootEntitySource;
|
||||
}
|
||||
|
||||
public void processSubclass(SubclassEntitySourceImpl subclassEntitySource) {
|
||||
final InheritanceType inheritanceType = Helper.interpretInheritanceType( subclassEntitySource.entityElement() );
|
||||
if ( hierarchyInheritanceType == InheritanceType.NO_INHERITANCE ) {
|
||||
hierarchyInheritanceType = inheritanceType;
|
||||
}
|
||||
else if ( hierarchyInheritanceType != inheritanceType ) {
|
||||
throw new MappingException( "Mixed inheritance strategies not supported", subclassEntitySource.getOrigin() );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,29 +25,33 @@ package org.hibernate.metamodel.reflite.internal;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.ArrayDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ArrayDescriptorImpl implements ArrayDescriptor {
|
||||
private final Name name;
|
||||
private final DotName name;
|
||||
private final int modifiers;
|
||||
private JavaTypeDescriptor componentType;
|
||||
|
||||
public ArrayDescriptorImpl(Name name, int modifiers, JavaTypeDescriptor componentType) {
|
||||
public ArrayDescriptorImpl(DotName name, int modifiers, JavaTypeDescriptor componentType) {
|
||||
this.name = name;
|
||||
this.modifiers = modifiers;
|
||||
this.componentType = componentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
public DotName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -66,8 +70,74 @@ public class ArrayDescriptorImpl implements ArrayDescriptor {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
if ( check == null ) {
|
||||
throw new IllegalArgumentException( "Descriptor to check cannot be null" );
|
||||
}
|
||||
|
||||
if ( equals( check ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ArrayDescriptor.class.isInstance( check ) ) {
|
||||
final ArrayDescriptor other = (ArrayDescriptor) check;
|
||||
return getComponentType().isAssignableFrom( other.getComponentType() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getComponentType() {
|
||||
return componentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ArrayDescriptorImpl that = (ArrayDescriptorImpl) o;
|
||||
return name.equals( that.name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.reflite.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -33,9 +34,9 @@ import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
|||
import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
|
@ -43,12 +44,13 @@ import org.jboss.jandex.DotName;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ClassDescriptorImpl implements ClassDescriptor {
|
||||
private final Name name;
|
||||
public class ClassDescriptorImpl extends InternalJavaTypeDescriptor implements ClassDescriptor {
|
||||
private final ClassInfo jandexClassInfo;
|
||||
|
||||
private final int modifiers;
|
||||
private final boolean hasDefaultConstructor;
|
||||
private final Map<DotName,AnnotationInstance> annotationMap;
|
||||
private final Map<DotName,AnnotationInstance> typeAnnotationMap;
|
||||
private final Map<DotName,List<AnnotationInstance>> annotationMap;
|
||||
|
||||
private ClassDescriptor superType;
|
||||
private Collection<InterfaceDescriptor> interfaces;
|
||||
|
@ -58,21 +60,25 @@ public class ClassDescriptorImpl implements ClassDescriptor {
|
|||
private List<JavaTypeDescriptor> typeParameters;
|
||||
|
||||
public ClassDescriptorImpl(
|
||||
Name name,
|
||||
ClassInfo jandexClassInfo,
|
||||
int modifiers,
|
||||
boolean hasDefaultConstructor,
|
||||
Map<DotName,AnnotationInstance> annotationMap) {
|
||||
this.name = name;
|
||||
Map<DotName, AnnotationInstance> typeAnnotationMap,
|
||||
Map<DotName, List<AnnotationInstance>> annotationMap) {
|
||||
this.jandexClassInfo = jandexClassInfo;
|
||||
this.modifiers = modifiers;
|
||||
this.hasDefaultConstructor = hasDefaultConstructor;
|
||||
this.typeAnnotationMap = typeAnnotationMap != null
|
||||
? typeAnnotationMap
|
||||
: Collections.<DotName, AnnotationInstance>emptyMap();
|
||||
this.annotationMap = annotationMap != null
|
||||
? annotationMap
|
||||
: Collections.<DotName, AnnotationInstance>emptyMap();
|
||||
: Collections.<DotName, List<AnnotationInstance>>emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
return name;
|
||||
public DotName getName() {
|
||||
return jandexClassInfo.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,10 +97,77 @@ public class ClassDescriptorImpl implements ClassDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<DotName, AnnotationInstance> getAnnotations() {
|
||||
return annotationMap;
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
final AnnotationInstance localTypeAnnotation = findLocalTypeAnnotation( annotationType );
|
||||
if ( localTypeAnnotation != null ) {
|
||||
return localTypeAnnotation;
|
||||
}
|
||||
|
||||
if ( superType != null ) {
|
||||
return superType.findTypeAnnotation( annotationType );
|
||||
}
|
||||
|
||||
for ( InterfaceDescriptor interfaceDescriptor : interfaces ) {
|
||||
final AnnotationInstance annotationInstance = interfaceDescriptor.findTypeAnnotation( annotationType );
|
||||
if ( annotationInstance != null ) {
|
||||
return annotationInstance;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return typeAnnotationMap.get( annotationType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
final List<AnnotationInstance> annotationInstances = new ArrayList<AnnotationInstance>();
|
||||
|
||||
annotationInstances.addAll( findLocalAnnotations( annotationType ) );
|
||||
|
||||
if ( superType != null ) {
|
||||
annotationInstances.addAll( superType.findAnnotations( annotationType ) );
|
||||
}
|
||||
|
||||
for ( InterfaceDescriptor interfaceDescriptor : interfaces ) {
|
||||
annotationInstances.addAll( interfaceDescriptor.findAnnotations( annotationType ) );
|
||||
}
|
||||
|
||||
return annotationInstances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
final Collection<AnnotationInstance> them = annotationMap.get( annotationType );
|
||||
return them == null ? Collections.<AnnotationInstance>emptyList() : them;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
// if ( check == null ) {
|
||||
// throw new IllegalArgumentException( "Descriptor to check cannot be null" );
|
||||
// }
|
||||
//
|
||||
// if ( equals( check ) ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if ( superType != null && superType.isAssignableFrom( check ) ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// for ( InterfaceDescriptor implementsInterface : getInterfaceTypes() ) {
|
||||
// if ( implementsInterface.isAssignableFrom( check ) ) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
@Override
|
||||
public boolean hasDefaultConstructor() {
|
||||
return hasDefaultConstructor;
|
||||
|
@ -102,17 +175,22 @@ public class ClassDescriptorImpl implements ClassDescriptor {
|
|||
|
||||
@Override
|
||||
public Collection<FieldDescriptor> getDeclaredFields() {
|
||||
return fieldDescriptors;
|
||||
return fieldDescriptors == null ? Collections.<FieldDescriptor>emptyList() : fieldDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MethodDescriptor> getDeclaredMethods() {
|
||||
return methodDescriptors;
|
||||
return methodDescriptors == null ? Collections.<MethodDescriptor>emptyList() : methodDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return jandexClassInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClassDescriptorImpl{" + name.toString() + '}';
|
||||
return "ClassDescriptorImpl{" + getName().toString() + '}';
|
||||
}
|
||||
|
||||
void setSuperType(ClassDescriptor superType) {
|
||||
|
@ -136,7 +214,34 @@ public class ClassDescriptorImpl implements ClassDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<JavaTypeDescriptor> getTypeParameters() {
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return typeParameters;
|
||||
}
|
||||
@Override
|
||||
public ClassDescriptor getSuperclass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<InterfaceDescriptor> getInterfaces() {
|
||||
return getInterfaceTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ClassDescriptorImpl that = (ClassDescriptorImpl) o;
|
||||
return getName().equals( that.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.ParameterizedType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
@ -37,7 +38,7 @@ import org.jboss.jandex.DotName;
|
|||
*/
|
||||
public class FieldDescriptorImpl implements FieldDescriptor {
|
||||
private final String name;
|
||||
private final JavaTypeDescriptor fieldType;
|
||||
private final ParameterizedType fieldType;
|
||||
|
||||
private final int modifiers;
|
||||
|
||||
|
@ -46,7 +47,7 @@ public class FieldDescriptorImpl implements FieldDescriptor {
|
|||
|
||||
public FieldDescriptorImpl(
|
||||
String name,
|
||||
JavaTypeDescriptor fieldType,
|
||||
ParameterizedType fieldType,
|
||||
int modifiers,
|
||||
JavaTypeDescriptor declaringType,
|
||||
Map<DotName, AnnotationInstance> annotationMap) {
|
||||
|
@ -65,7 +66,7 @@ public class FieldDescriptorImpl implements FieldDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getType() {
|
||||
public ParameterizedType getType() {
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,16 @@ public class FieldDescriptorImpl implements FieldDescriptor {
|
|||
return annotationMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLoggableForm() {
|
||||
return declaringType.getName().toString() + '#' + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSignatureForm() {
|
||||
return fieldType.getErasedType().getName().toString() + ' ' + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FieldDescriptorImpl{" + declaringType.getName().toString() + '#' + name + '}';
|
||||
|
|
|
@ -23,27 +23,30 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.reflite.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class InterfaceDescriptorImpl implements InterfaceDescriptor {
|
||||
private final Name name;
|
||||
public class InterfaceDescriptorImpl extends InternalJavaTypeDescriptor implements InterfaceDescriptor {
|
||||
private final ClassInfo classInfo;
|
||||
private final int modifiers;
|
||||
private final Map<DotName, AnnotationInstance> annotationMap;
|
||||
private final Map<DotName, AnnotationInstance> typeAnnotationMap;
|
||||
private final Map<DotName,List<AnnotationInstance>> annotationMap;
|
||||
|
||||
private Collection<InterfaceDescriptor> extendedInterfaceTypes;
|
||||
|
||||
|
@ -52,19 +55,23 @@ public class InterfaceDescriptorImpl implements InterfaceDescriptor {
|
|||
private List<JavaTypeDescriptor> typeParameters;
|
||||
|
||||
public InterfaceDescriptorImpl(
|
||||
Name name,
|
||||
ClassInfo classInfo,
|
||||
int modifiers,
|
||||
Map<DotName, AnnotationInstance> annotationMap) {
|
||||
this.name = name;
|
||||
Map<DotName, AnnotationInstance> typeAnnotationMap,
|
||||
Map<DotName,List<AnnotationInstance>> annotationMap) {
|
||||
this.classInfo = classInfo;
|
||||
this.modifiers = modifiers;
|
||||
this.typeAnnotationMap = typeAnnotationMap != null
|
||||
? typeAnnotationMap
|
||||
: Collections.<DotName, AnnotationInstance>emptyMap();
|
||||
this.annotationMap = annotationMap != null
|
||||
? annotationMap
|
||||
: Collections.<DotName, AnnotationInstance>emptyMap();
|
||||
: Collections.<DotName, List<AnnotationInstance>>emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
return name;
|
||||
public DotName getName() {
|
||||
return classInfo.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,23 +85,58 @@ public class InterfaceDescriptorImpl implements InterfaceDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<DotName, AnnotationInstance> getAnnotations() {
|
||||
return annotationMap;
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
final AnnotationInstance localTypeAnnotation = findLocalTypeAnnotation( annotationType );
|
||||
if ( localTypeAnnotation != null ) {
|
||||
return localTypeAnnotation;
|
||||
}
|
||||
|
||||
for ( InterfaceDescriptor extended : extendedInterfaceTypes ) {
|
||||
final AnnotationInstance annotationInstance = extended.findTypeAnnotation( annotationType );
|
||||
if ( annotationInstance != null ) {
|
||||
return annotationInstance;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return typeAnnotationMap.get( annotationType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
final List<AnnotationInstance> annotationInstances = new ArrayList<AnnotationInstance>();
|
||||
annotationInstances.addAll( findLocalAnnotations( annotationType ) );
|
||||
|
||||
for ( InterfaceDescriptor extended : extendedInterfaceTypes ) {
|
||||
annotationInstances.addAll( extended.findAnnotations( annotationType ) );
|
||||
}
|
||||
|
||||
return annotationInstances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
final Collection<AnnotationInstance> them = annotationMap.get( annotationType );
|
||||
return them == null ? Collections.<AnnotationInstance>emptyList() : them;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FieldDescriptor> getDeclaredFields() {
|
||||
return fields;
|
||||
return fields == null ? Collections.<FieldDescriptor>emptyList() : fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MethodDescriptor> getDeclaredMethods() {
|
||||
return methods;
|
||||
return methods == null ? Collections.<MethodDescriptor>emptyList() : methods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterfaceDescriptorImpl{" + name.toString() + '}';
|
||||
return "InterfaceDescriptorImpl{" + getName().toString() + '}';
|
||||
}
|
||||
|
||||
void setExtendedInterfaceTypes(Collection<InterfaceDescriptor> extendedInterfaceTypes) {
|
||||
|
@ -109,11 +151,44 @@ public class InterfaceDescriptorImpl implements InterfaceDescriptor {
|
|||
this.methods = methods;
|
||||
}
|
||||
|
||||
public List<JavaTypeDescriptor> getTypeParameters() {
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
public void setTypeParameters(List<JavaTypeDescriptor> typeParameters) {
|
||||
this.typeParameters = typeParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getSuperclass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<InterfaceDescriptor> getInterfaces() {
|
||||
return getExtendedInterfaceTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final InterfaceDescriptorImpl that = (InterfaceDescriptorImpl) o;
|
||||
return this.getName().equals( that.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.reflite.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class InternalJavaTypeDescriptor implements JavaTypeDescriptor {
|
||||
public abstract ClassDescriptor getSuperclass();
|
||||
public abstract Collection<InterfaceDescriptor> getInterfaces();
|
||||
|
||||
@Override
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
if ( check == null ) {
|
||||
throw new IllegalArgumentException( "Descriptor to check cannot be null" );
|
||||
}
|
||||
|
||||
if ( equals( check ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if ( InternalJavaTypeDescriptor.class.isInstance( check ) ) {
|
||||
return ( (InternalJavaTypeDescriptor) check ).isAssignableTo( this );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAssignableTo(InternalJavaTypeDescriptor check) {
|
||||
ClassDescriptor superClass = getSuperclass();
|
||||
if ( check.equals( superClass ) ) {
|
||||
return true;
|
||||
}
|
||||
if ( superClass instanceof InternalJavaTypeDescriptor ) {
|
||||
if ( ( (InternalJavaTypeDescriptor) superClass ).isAssignableTo( check ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<InterfaceDescriptor> interfaces = getInterfaces();
|
||||
if ( interfaces != null ) {
|
||||
for ( InterfaceDescriptor interfaceDescriptor : interfaces ) {
|
||||
if ( check.equals( interfaceDescriptor ) ) {
|
||||
return true;
|
||||
}
|
||||
if ( interfaceDescriptor instanceof InternalJavaTypeDescriptor ) {
|
||||
if ( ( (InternalJavaTypeDescriptor) interfaceDescriptor ).isAssignableTo( check ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -25,23 +25,27 @@ package org.hibernate.metamodel.reflite.internal;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.reflite.spi.ArrayDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
import org.hibernate.metamodel.reflite.spi.ParameterizedType;
|
||||
import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.VoidDescriptor;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
|
@ -58,6 +62,9 @@ import com.fasterxml.classmate.MemberResolver;
|
|||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
|
||||
/**
|
||||
* This is the "interim" implementation of JavaTypeDescriptorRepository that loads Classes to ascertain this
|
||||
|
@ -77,7 +84,12 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
private final TypeResolver classmateTypeResolver;
|
||||
private final MemberResolver classmateMemberResolver;
|
||||
|
||||
private Map<Name,JavaTypeDescriptor> typeDescriptorMap = new HashMap<Name, JavaTypeDescriptor>();
|
||||
private Map<DotName,JavaTypeDescriptor> typeDescriptorMap = new HashMap<DotName, JavaTypeDescriptor>();
|
||||
|
||||
private final InterfaceDescriptor jdkCollectionDescriptor;
|
||||
private final InterfaceDescriptor jdkListDescriptor;
|
||||
private final InterfaceDescriptor jdkSetDescriptor;
|
||||
private final InterfaceDescriptor jdkMapDescriptor;
|
||||
|
||||
public JavaTypeDescriptorRepositoryImpl(
|
||||
IndexView jandexIndex,
|
||||
|
@ -96,24 +108,29 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
|
||||
this.classmateTypeResolver = new TypeResolver();
|
||||
this.classmateMemberResolver = new MemberResolver( classmateTypeResolver );
|
||||
|
||||
this.jdkCollectionDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Collection.class.getName() ) );
|
||||
this.jdkListDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( List.class.getName() ) );
|
||||
this.jdkSetDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Set.class.getName() ) );
|
||||
this.jdkMapDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Map.class.getName() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name buildName(String name) {
|
||||
return new DotNameAdapter( name );
|
||||
public DotName buildName(String name) {
|
||||
return DotName.createSimple( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getType(Name typeName) {
|
||||
if ( typeName == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String typeNameString = typeName.fullName();
|
||||
public JavaTypeDescriptor getType(DotName typeName) {
|
||||
final String typeNameString = typeName.toString();
|
||||
if ( "void".equals( typeNameString ) ) {
|
||||
return VoidDescriptor.INSTANCE;
|
||||
}
|
||||
|
||||
if ( typeNameString.startsWith( "[" ) ) {
|
||||
return decipherArrayTypeRequest( typeNameString );
|
||||
}
|
||||
|
||||
JavaTypeDescriptor descriptor = typeDescriptorMap.get( typeName );
|
||||
if ( descriptor == null ) {
|
||||
descriptor = Primitives.resolveByName( typeName );
|
||||
|
@ -127,8 +144,86 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
protected JavaTypeDescriptor makeTypeDescriptor(Name typeName) {
|
||||
final String classNameToLoad = typeName.fullName();
|
||||
private JavaTypeDescriptor decipherArrayTypeRequest(String typeNameString) {
|
||||
final String componentTypeNameString = typeNameString.substring( 1 );
|
||||
final JavaTypeDescriptor componentType = resolveArrayComponent( componentTypeNameString );
|
||||
if ( componentType == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not interpret requested array component to descriptor : " + typeNameString
|
||||
);
|
||||
}
|
||||
|
||||
return new ArrayDescriptorImpl(
|
||||
DotName.createSimple( typeNameString ),
|
||||
Modifier.PUBLIC,
|
||||
componentType
|
||||
);
|
||||
}
|
||||
|
||||
private JavaTypeDescriptor resolveArrayComponent(String componentTypeName) {
|
||||
if ( componentTypeName.startsWith( "[" ) ) {
|
||||
// the component itself is an array (multiple dimension array)
|
||||
return decipherArrayTypeRequest( componentTypeName );
|
||||
}
|
||||
|
||||
final char arrayComponentCode = componentTypeName.charAt( 0 );
|
||||
if ( arrayComponentCode == 'L' ) {
|
||||
// the array component is an object.. we need to strip
|
||||
// off the leading 'L' and the trailing ';' and resolve
|
||||
// the component descriptor
|
||||
final String componentClassName = componentTypeName.substring( 1, componentTypeName.length() - 1 );
|
||||
return getType( DotName.createSimple( componentClassName ) );
|
||||
}
|
||||
else {
|
||||
// should indicate we have a primitive array
|
||||
// ask the Primitives class to help us decipher it
|
||||
return Primitives.decipherArrayComponentCode( arrayComponentCode );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayDescriptor arrayType(JavaTypeDescriptor componentType) {
|
||||
if ( PrimitiveTypeDescriptor.class.isInstance( componentType ) ) {
|
||||
return Primitives.primitiveArrayDescriptor( (PrimitiveTypeDescriptor) componentType );
|
||||
}
|
||||
|
||||
final String componentTypeName = componentType.getName().toString();
|
||||
final String arrayTypeName;
|
||||
if ( ArrayDescriptor.class.isInstance( componentType ) ) {
|
||||
arrayTypeName = '[' + componentTypeName;
|
||||
}
|
||||
else {
|
||||
arrayTypeName = "[L" + componentTypeName + ';';
|
||||
}
|
||||
return new ArrayDescriptorImpl(
|
||||
DotName.createSimple( arrayTypeName ),
|
||||
Modifier.PUBLIC,
|
||||
componentType
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceDescriptor jdkCollectionDescriptor() {
|
||||
return jdkCollectionDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceDescriptor jdkListDescriptor() {
|
||||
return jdkListDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceDescriptor jdkSetDescriptor() {
|
||||
return jdkSetDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceDescriptor jdkMapDescriptor() {
|
||||
return jdkMapDescriptor;
|
||||
}
|
||||
|
||||
protected JavaTypeDescriptor makeTypeDescriptor(DotName typeName) {
|
||||
final String classNameToLoad = typeName.toString();
|
||||
|
||||
if ( isSafeClass( typeName ) ) {
|
||||
return makeTypeDescriptor( typeName, classLoaderService.classForName( classNameToLoad ) );
|
||||
|
@ -168,8 +263,8 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isSafeClass(Name className) {
|
||||
final String classNameString = className.fullName();
|
||||
private boolean isSafeClass(DotName className) {
|
||||
final String classNameString = className.toString();
|
||||
// classes in any of these packages are safe to load through the "live" ClassLoader
|
||||
return classNameString.startsWith( "java." )
|
||||
|| classNameString.startsWith( "javax." )
|
||||
|
@ -177,14 +272,15 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
|
||||
}
|
||||
|
||||
private JavaTypeDescriptor makeTypeDescriptor(Name typeName, Class clazz) {
|
||||
final JandexPivot jandexPivot = pivotAnnotations( toJandexName( typeName ) );
|
||||
private JavaTypeDescriptor makeTypeDescriptor(DotName typeName, Class clazz) {
|
||||
final JandexPivot jandexPivot = pivotAnnotations( typeName );
|
||||
|
||||
if ( clazz.isInterface() ) {
|
||||
final InterfaceDescriptorImpl typeDescriptor = new InterfaceDescriptorImpl(
|
||||
typeName,
|
||||
jandexPivot.classInfo,
|
||||
clazz.getModifiers(),
|
||||
jandexPivot.typeAnnotations
|
||||
jandexPivot.typeAnnotations,
|
||||
jandexPivot.allAnnotations
|
||||
);
|
||||
typeDescriptorMap.put( typeName, typeDescriptor );
|
||||
|
||||
|
@ -192,31 +288,38 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
|
||||
final ResolvedType resolvedType = classmateTypeResolver.resolve( clazz );
|
||||
typeDescriptor.setTypeParameters( extractTypeParameters( resolvedType ) );
|
||||
// final ResolvedTypeWithMembers resolvedTypeWithMembers = classmateMemberResolver.resolve( resolvedType, null, null );
|
||||
final ResolvedTypeWithMembers resolvedTypeWithMembers = classmateMemberResolver.resolve( resolvedType, null, null );
|
||||
|
||||
typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot ) );
|
||||
typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot ) );
|
||||
//interface fields would need to be static, and we don't care about static fields
|
||||
//we exclude the statics in extractFields but why even bother iterating them as here
|
||||
//we will exclude them all
|
||||
//typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) );
|
||||
typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) );
|
||||
|
||||
|
||||
return typeDescriptor;
|
||||
}
|
||||
else {
|
||||
final ClassDescriptorImpl typeDescriptor = new ClassDescriptorImpl(
|
||||
typeName,
|
||||
jandexPivot.classInfo,
|
||||
clazz.getModifiers(),
|
||||
hasDefaultCtor( clazz ),
|
||||
jandexPivot.typeAnnotations
|
||||
jandexPivot.typeAnnotations,
|
||||
jandexPivot.allAnnotations
|
||||
);
|
||||
typeDescriptorMap.put( typeName, typeDescriptor );
|
||||
|
||||
typeDescriptor.setSuperType( extractSuper( clazz ) );
|
||||
typeDescriptor.setInterfaces( extractInterfaces( clazz ) );
|
||||
|
||||
final ResolvedType resolvedType = classmateTypeResolver.resolve( clazz );
|
||||
typeDescriptor.setTypeParameters( extractTypeParameters( resolvedType ) );
|
||||
if ( !Object.class.equals( clazz ) ) {
|
||||
final ResolvedType resolvedType = classmateTypeResolver.resolve( clazz );
|
||||
typeDescriptor.setTypeParameters( extractTypeParameters( resolvedType ) );
|
||||
final ResolvedTypeWithMembers resolvedTypeWithMembers = classmateMemberResolver.resolve( resolvedType, null, null );
|
||||
|
||||
typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot ) );
|
||||
typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot ) );
|
||||
typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) );
|
||||
typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) );
|
||||
}
|
||||
|
||||
return typeDescriptor;
|
||||
}
|
||||
|
@ -234,16 +337,7 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
return result;
|
||||
}
|
||||
|
||||
private DotName toJandexName(Name typeName) {
|
||||
if ( DotNameAdapter.class.isInstance( typeName ) ) {
|
||||
return ( (DotNameAdapter) typeName ).jandexName();
|
||||
}
|
||||
else {
|
||||
return DotName.createSimple( typeName.fullName() );
|
||||
}
|
||||
}
|
||||
|
||||
private static final JandexPivot NO_JANDEX_PIVOT = new JandexPivot();
|
||||
private static final JandexPivot NO_JANDEX_PIVOT = new JandexPivot( null );
|
||||
|
||||
private JandexPivot pivotAnnotations(DotName typeName) {
|
||||
if ( jandexIndex == null ) {
|
||||
|
@ -252,11 +346,19 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
|
||||
final ClassInfo jandexClassInfo = jandexIndex.getClassByName( typeName );
|
||||
if ( jandexClassInfo == null ) {
|
||||
return NO_JANDEX_PIVOT;
|
||||
return new JandexPivot(
|
||||
ClassInfo.create(
|
||||
typeName,
|
||||
null,
|
||||
(short)0,
|
||||
new DotName[0],
|
||||
Collections.<DotName, List<AnnotationInstance>>emptyMap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final Map<DotName, List<AnnotationInstance>> annotations = jandexClassInfo.annotations();
|
||||
final JandexPivot pivot = new JandexPivot();
|
||||
final JandexPivot pivot = new JandexPivot( jandexClassInfo );
|
||||
for ( Map.Entry<DotName, List<AnnotationInstance>> annotationInstances : annotations.entrySet() ) {
|
||||
for ( AnnotationInstance annotationInstance : annotationInstances.getValue() ) {
|
||||
if ( MethodParameterInfo.class.isInstance( annotationInstance.target() ) ) {
|
||||
|
@ -336,10 +438,6 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
return buff.append( ')' ).toString();
|
||||
}
|
||||
|
||||
private Collection<AnnotationInstance> getAnnotations(DotName dotName) {
|
||||
return jandexIndex.getAnnotations( dotName );
|
||||
}
|
||||
|
||||
private ClassDescriptor extractSuper(Class clazz) {
|
||||
final Class superclass = clazz.getSuperclass();
|
||||
if ( superclass == null ) {
|
||||
|
@ -365,7 +463,8 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
private Collection<FieldDescriptor> extractFields(
|
||||
Class clazz,
|
||||
JavaTypeDescriptor declaringType,
|
||||
JandexPivot jandexPivot) {
|
||||
JandexPivot jandexPivot,
|
||||
ResolvedTypeWithMembers resolvedTypeWithMembers) {
|
||||
final Field[] declaredFields = clazz.getDeclaredFields();
|
||||
final Field[] fields = clazz.getFields();
|
||||
|
||||
|
@ -373,13 +472,22 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final ResolvedField[] resolvedFields = resolvedTypeWithMembers.getMemberFields();
|
||||
final List<FieldDescriptor> fieldDescriptors = CollectionHelper.arrayList( fields.length );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// first, extract declared fields
|
||||
for ( Field field : declaredFields ) {
|
||||
if ( Modifier.isStatic( field.getModifiers() ) ) {
|
||||
continue;
|
||||
}
|
||||
fieldDescriptors.add(
|
||||
new FieldDescriptorImpl(
|
||||
field.getName(),
|
||||
toTypeDescriptor( field.getType() ),
|
||||
makeParameterizedType(
|
||||
toTypeDescriptor( field.getType() ),
|
||||
findResolvedFieldInfo( field, resolvedFields )
|
||||
),
|
||||
field.getModifiers(),
|
||||
declaringType,
|
||||
jandexPivot.fieldAnnotations.get( field.getName() )
|
||||
|
@ -387,25 +495,76 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
);
|
||||
}
|
||||
|
||||
for ( Field field : fields ) {
|
||||
if ( clazz.equals( field.getDeclaringClass() ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final JavaTypeDescriptor fieldDeclarer = getType( buildName( field.getDeclaringClass().getName() ) );
|
||||
fieldDescriptors.add(
|
||||
new FieldDescriptorImpl(
|
||||
field.getName(),
|
||||
toTypeDescriptor( field.getType() ),
|
||||
field.getModifiers(),
|
||||
fieldDeclarer,
|
||||
jandexPivot.fieldAnnotations.get( field.getName() )
|
||||
)
|
||||
);
|
||||
}
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// then, extract all fields
|
||||
// for ( Field field : fields ) {
|
||||
// if ( clazz.equals( field.getDeclaringClass() ) ) {
|
||||
// // skip declared fields, since we already processed them above
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// if ( Modifier.isStatic( field.getModifiers() ) ) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// final JavaTypeDescriptor fieldDeclarer = getType( buildName( field.getDeclaringClass().getName() ) );
|
||||
// fieldDescriptors.add(
|
||||
// new FieldDescriptorImpl(
|
||||
// field.getName(),
|
||||
// makeParameterizedType(
|
||||
// toTypeDescriptor( field.getType() ),
|
||||
// findResolvedFieldInfo( field, resolvedFields )
|
||||
// ),
|
||||
// field.getModifiers(),
|
||||
// fieldDeclarer,
|
||||
// jandexPivot.fieldAnnotations.get( field.getName() )
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
return fieldDescriptors;
|
||||
}
|
||||
|
||||
private ResolvedField findResolvedFieldInfo(Field field, ResolvedField[] resolvedFields) {
|
||||
for ( ResolvedField resolvedField : resolvedFields ) {
|
||||
if ( resolvedField.getName().equals( field.getName() ) ) {
|
||||
return resolvedField;
|
||||
}
|
||||
}
|
||||
// throw new AssertionFailure(
|
||||
// String.format(
|
||||
// "Unable to resolve type information of field : %s",
|
||||
// field.toGenericString()
|
||||
// )
|
||||
// );
|
||||
return null;
|
||||
}
|
||||
|
||||
private ParameterizedType makeParameterizedType(
|
||||
JavaTypeDescriptor erasedTypeDescriptor,
|
||||
ResolvedMember resolvedMember) {
|
||||
if ( resolvedMember == null
|
||||
|| resolvedMember.getType() == null ) {
|
||||
return new ParameterizedTypeImpl(
|
||||
erasedTypeDescriptor,
|
||||
Collections.<JavaTypeDescriptor>emptyList()
|
||||
);
|
||||
}
|
||||
|
||||
List<ResolvedType> classmateResolvedTypes = resolvedMember.getType().getTypeParameters();
|
||||
if ( classmateResolvedTypes.isEmpty() ) {
|
||||
return new ParameterizedTypeImpl( erasedTypeDescriptor, Collections.<JavaTypeDescriptor>emptyList() );
|
||||
}
|
||||
|
||||
List<JavaTypeDescriptor> resolvedTypeDescriptors = new ArrayList<JavaTypeDescriptor>();
|
||||
for ( ResolvedType classmateResolvedType : classmateResolvedTypes ) {
|
||||
resolvedTypeDescriptors.add(
|
||||
toTypeDescriptor( classmateResolvedType.getErasedType() )
|
||||
);
|
||||
}
|
||||
return new ParameterizedTypeImpl( erasedTypeDescriptor, resolvedTypeDescriptors );
|
||||
}
|
||||
|
||||
|
||||
private JavaTypeDescriptor toTypeDescriptor(Class clazz) {
|
||||
final JavaTypeDescriptor fieldTypeDescriptor;
|
||||
if ( clazz.isArray() ) {
|
||||
|
@ -431,7 +590,7 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
}
|
||||
else {
|
||||
return new ArrayDescriptorImpl(
|
||||
buildName( "[" + type.getName() ),
|
||||
buildName( "[L" + type.getName() + ";" ),
|
||||
type.getModifiers(),
|
||||
getType( buildName( type.getName() ) )
|
||||
);
|
||||
|
@ -441,7 +600,8 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
private Collection<MethodDescriptor> extractMethods(
|
||||
Class clazz,
|
||||
JavaTypeDescriptor declaringType,
|
||||
JandexPivot jandexPivot) {
|
||||
JandexPivot jandexPivot,
|
||||
ResolvedTypeWithMembers resolvedTypeWithMembers) {
|
||||
final Method[] declaredMethods = clazz.getDeclaredMethods();
|
||||
final Method[] methods = clazz.getMethods();
|
||||
|
||||
|
@ -449,28 +609,41 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final ResolvedMethod[] resolvedMethods = resolvedTypeWithMembers.getMemberMethods();
|
||||
final List<MethodDescriptor> methodDescriptors = CollectionHelper.arrayList( methods.length );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// first, extract declared methods
|
||||
for ( Method method : declaredMethods ) {
|
||||
methodDescriptors.add( fromMethod( method, declaringType, jandexPivot ) );
|
||||
}
|
||||
|
||||
for ( Method method : methods ) {
|
||||
if ( clazz.equals( method.getDeclaringClass() ) ) {
|
||||
if ( Modifier.isStatic( method.getModifiers() ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final JavaTypeDescriptor methodDeclarer = getType( buildName( method.getDeclaringClass().getName() ) );
|
||||
methodDescriptors.add( fromMethod( method, methodDeclarer, jandexPivot ) );
|
||||
methodDescriptors.add( fromMethod( method, declaringType, jandexPivot, resolvedMethods ) );
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// then, extract all methods
|
||||
// for ( Method method : methods ) {
|
||||
// if ( clazz.equals( method.getDeclaringClass() ) ) {
|
||||
// // skip declared methods, since we already processed them above
|
||||
// continue;
|
||||
// }
|
||||
// if ( Modifier.isStatic( method.getModifiers() ) ) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// final JavaTypeDescriptor methodDeclarer = getType( buildName( method.getDeclaringClass().getName() ) );
|
||||
// methodDescriptors.add( fromMethod( method, methodDeclarer, jandexPivot, resolvedMethods ) );
|
||||
// }
|
||||
|
||||
return methodDescriptors;
|
||||
}
|
||||
|
||||
private MethodDescriptor fromMethod(
|
||||
Method method,
|
||||
JavaTypeDescriptor declaringType,
|
||||
JandexPivot jandexPivot) {
|
||||
JandexPivot jandexPivot,
|
||||
ResolvedMethod[] resolvedMethods) {
|
||||
final Class[] parameterTypes = method.getParameterTypes();
|
||||
final Collection<JavaTypeDescriptor> argumentTypes;
|
||||
if ( parameterTypes.length == 0 ) {
|
||||
|
@ -487,15 +660,35 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
method.getName(),
|
||||
declaringType,
|
||||
method.getModifiers(),
|
||||
toTypeDescriptor( method.getReturnType() ),
|
||||
makeParameterizedType(
|
||||
toTypeDescriptor( method.getReturnType() ),
|
||||
findResolvedMethodInfo( method, resolvedMethods )
|
||||
),
|
||||
argumentTypes,
|
||||
jandexPivot.methodAnnotations.get( buildMethodAnnotationsKey( method ) )
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedMethod findResolvedMethodInfo(Method method, ResolvedMethod[] resolvedMethods) {
|
||||
for ( ResolvedMethod resolvedMethod : resolvedMethods ) {
|
||||
if ( resolvedMethod.getName().equals( method.getName() ) ) {
|
||||
// todo : we really need to check signatures too
|
||||
return resolvedMethod;
|
||||
}
|
||||
}
|
||||
// throw new AssertionFailure(
|
||||
// String.format(
|
||||
// "Unable to resolve type information of method : %s",
|
||||
// method.toGenericString()
|
||||
// )
|
||||
// );
|
||||
return null;
|
||||
}
|
||||
|
||||
private String buildMethodAnnotationsKey(Method method) {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
buff.append( method.getReturnType().getName() )
|
||||
.append( ' ' )
|
||||
.append( method.getName() )
|
||||
.append( '(' );
|
||||
for ( int i = 0; i < method.getParameterTypes().length; i++ ) {
|
||||
|
@ -519,14 +712,14 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
}
|
||||
|
||||
private static class NoSuchClassTypeDescriptor implements JavaTypeDescriptor {
|
||||
private final Name name;
|
||||
private final DotName name;
|
||||
|
||||
private NoSuchClassTypeDescriptor(Name name) {
|
||||
private NoSuchClassTypeDescriptor(DotName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
public DotName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -544,15 +737,58 @@ public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepos
|
|||
public Collection<MethodDescriptor> getDeclaredMethods() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class JandexPivot {
|
||||
private Map<DotName,AnnotationInstance> typeAnnotations
|
||||
= new HashMap<DotName, AnnotationInstance>();
|
||||
private Map<String,Map<DotName,AnnotationInstance>> fieldAnnotations
|
||||
= new HashMap<String, Map<DotName, AnnotationInstance>>();
|
||||
private Map<String,Map<DotName,AnnotationInstance>> methodAnnotations
|
||||
= new HashMap<String, Map<DotName, AnnotationInstance>>();
|
||||
private final ClassInfo classInfo;
|
||||
|
||||
private Map<DotName,List<AnnotationInstance>> allAnnotations;
|
||||
private Map<DotName,AnnotationInstance> typeAnnotations = new HashMap<DotName, AnnotationInstance>();
|
||||
private Map<String,Map<DotName,AnnotationInstance>> fieldAnnotations = new HashMap<String, Map<DotName, AnnotationInstance>>();
|
||||
private Map<String,Map<DotName,AnnotationInstance>> methodAnnotations = new HashMap<String, Map<DotName, AnnotationInstance>>();
|
||||
|
||||
private JandexPivot(ClassInfo classInfo) {
|
||||
this.classInfo = classInfo;
|
||||
this.allAnnotations = classInfo == null
|
||||
? Collections.<DotName, List<AnnotationInstance>>emptyMap()
|
||||
: classInfo.annotations();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.ParameterizedType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
@ -40,22 +41,22 @@ public class MethodDescriptorImpl implements MethodDescriptor {
|
|||
private final String name;
|
||||
private final JavaTypeDescriptor declaringType;
|
||||
private final int modifiers;
|
||||
private final JavaTypeDescriptor returnType;
|
||||
private final Collection<JavaTypeDescriptor> parameterTypes;
|
||||
private final ParameterizedType returnType;
|
||||
private final Collection<JavaTypeDescriptor> argumentTypes;
|
||||
private final Map<DotName, AnnotationInstance> annotationMap;
|
||||
|
||||
public MethodDescriptorImpl(
|
||||
String name,
|
||||
JavaTypeDescriptor declaringType,
|
||||
int modifiers,
|
||||
JavaTypeDescriptor returnType,
|
||||
Collection<JavaTypeDescriptor> parameterTypes,
|
||||
ParameterizedType returnType,
|
||||
Collection<JavaTypeDescriptor> argumentTypes,
|
||||
Map<DotName, AnnotationInstance> annotationMap) {
|
||||
this.name = name;
|
||||
this.declaringType = declaringType;
|
||||
this.modifiers = modifiers;
|
||||
this.returnType = returnType;
|
||||
this.parameterTypes = parameterTypes;
|
||||
this.argumentTypes = argumentTypes;
|
||||
this.annotationMap = annotationMap != null
|
||||
? annotationMap
|
||||
: Collections.<DotName, AnnotationInstance>emptyMap();
|
||||
|
@ -66,6 +67,11 @@ public class MethodDescriptorImpl implements MethodDescriptor {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterizedType getType() {
|
||||
return getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getDeclaringType() {
|
||||
return declaringType;
|
||||
|
@ -77,13 +83,13 @@ public class MethodDescriptorImpl implements MethodDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getReturnType() {
|
||||
public ParameterizedType getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<JavaTypeDescriptor> getParameterTypes() {
|
||||
return parameterTypes;
|
||||
public Collection<JavaTypeDescriptor> getArgumentTypes() {
|
||||
return argumentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,6 +97,36 @@ public class MethodDescriptorImpl implements MethodDescriptor {
|
|||
return annotationMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLoggableForm() {
|
||||
return declaringType.getName().toString() + '#' + name;
|
||||
}
|
||||
|
||||
private String signatureForm;
|
||||
|
||||
@Override
|
||||
public String toSignatureForm() {
|
||||
if ( signatureForm == null ) {
|
||||
signatureForm = buildSignatureForm();
|
||||
}
|
||||
return signatureForm;
|
||||
}
|
||||
|
||||
private String buildSignatureForm() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( returnType.getErasedType().getName().toString() );
|
||||
sb.append( ' ' );
|
||||
sb.append( name ).append( '(' );
|
||||
String delimiter = "";
|
||||
for ( JavaTypeDescriptor argumentType : argumentTypes ) {
|
||||
sb.append( delimiter );
|
||||
sb.append( argumentType.getName().toString() );
|
||||
delimiter = ", ";
|
||||
}
|
||||
sb.append( ')' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodDescriptorImpl{" + declaringType.getName().toString() + '#' + name + '}';
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.reflite.internal;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MemberDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
|
||||
/**
|
||||
* Fills-in non-public aspects of the {@link java.lang.reflect.Modifier} class
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ModifierUtils {
|
||||
|
||||
private static final int BRIDGE = 0x00000040;
|
||||
private static final int ENUM = 0x00004000;
|
||||
private static final int SYNTHETIC = 0x00001000;
|
||||
|
||||
/**
|
||||
* Disallow instantiation. This is a utility class, use statically.
|
||||
*/
|
||||
private ModifierUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given method is a bridge.
|
||||
*
|
||||
* @param methodDescriptor The method descriptor to check
|
||||
*
|
||||
* @return {@code true} if the method is a bridge , {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isBridge(MethodDescriptor methodDescriptor) {
|
||||
return (methodDescriptor.getModifiers() & BRIDGE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given Java type is an enum.
|
||||
*
|
||||
* @param javaType The descriptor of the Java type to check
|
||||
*
|
||||
* @return {@code true} if the Java type is an enum, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isEnum(JavaTypeDescriptor javaType) {
|
||||
return (javaType.getModifiers() & ENUM) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine is the given member (field/method) is synthetic
|
||||
*
|
||||
* @param memberDescriptor The descriptor for the member to check
|
||||
*
|
||||
* @return {@code true} if the member is synthetic, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isSynthetic(MemberDescriptor memberDescriptor) {
|
||||
return (memberDescriptor.getModifiers() & SYNTHETIC) != 0;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* 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.
|
||||
|
@ -21,39 +21,36 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.spi.domain;
|
||||
package org.hibernate.metamodel.reflite.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.ParameterizedType;
|
||||
|
||||
/**
|
||||
* Models the concept class in the hierarchy with no persistent attributes.
|
||||
* Implementation of the ParameterizedType contract
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonEntity extends AbstractAttributeContainer {
|
||||
/**
|
||||
* Constructor for the non-entity
|
||||
*
|
||||
* @param entityName The name of the non-entity
|
||||
* @param typeDescriptor The descriptor for this non-entity's {@link Class}
|
||||
* @param superType The super type for this non-entity. If there is not super type {@code null} needs to be passed.
|
||||
*/
|
||||
public NonEntity(String entityName, JavaTypeDescriptor typeDescriptor, Hierarchical superType) {
|
||||
super( entityName, typeDescriptor, superType );
|
||||
public class ParameterizedTypeImpl implements ParameterizedType {
|
||||
private final JavaTypeDescriptor erasedType;
|
||||
private final List<JavaTypeDescriptor> resolvedParameterTypes;
|
||||
|
||||
public ParameterizedTypeImpl(
|
||||
JavaTypeDescriptor erasedType,
|
||||
List<JavaTypeDescriptor> resolvedParameterTypes) {
|
||||
this.erasedType = erasedType;
|
||||
this.resolvedParameterTypes = resolvedParameterTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssociation() {
|
||||
return true;
|
||||
public JavaTypeDescriptor getErasedType() {
|
||||
return erasedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAggregate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRoleBaseName() {
|
||||
return getName();
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return resolvedParameterTypes;
|
||||
}
|
||||
}
|
|
@ -25,15 +25,19 @@ package org.hibernate.metamodel.reflite.internal;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.reflite.spi.ArrayDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.FieldDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.MethodDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.Name;
|
||||
import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor;
|
||||
import org.hibernate.metamodel.reflite.spi.PrimitiveWrapperTypeDescriptor;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -53,7 +57,7 @@ public class Primitives {
|
|||
this.primitiveWrapperType = new WrapperDescriptorImpl( wrapperClass, this );
|
||||
|
||||
this.primitiveArrayType = new ArrayDescriptorImpl(
|
||||
new DotNameAdapter( primitiveArrayClass.getName() ),
|
||||
DotName.createSimple( primitiveArrayClass.getName() ),
|
||||
primitiveArrayClass.getModifiers(),
|
||||
this.primitiveType
|
||||
);
|
||||
|
@ -69,10 +73,10 @@ public class Primitives {
|
|||
public static final PrimitiveGroup FLOAT = new PrimitiveGroup( float.class, float[].class, Float.class );
|
||||
public static final PrimitiveGroup DOUBLE = new PrimitiveGroup( double.class, double[].class, Double.class );
|
||||
|
||||
public static JavaTypeDescriptor resolveByName(Name name) {
|
||||
public static JavaTypeDescriptor resolveByName(DotName name) {
|
||||
assert name != null;
|
||||
|
||||
final String typeNameString = name.fullName();
|
||||
final String typeNameString = name.toString();
|
||||
|
||||
if ( char.class.getName().equals( typeNameString ) ) {
|
||||
return CHAR.primitiveType;
|
||||
|
@ -133,50 +137,100 @@ public class Primitives {
|
|||
final String typeNameString = type.getName();
|
||||
|
||||
if ( char.class.getName().equals( typeNameString ) ) {
|
||||
return CHAR.primitiveType;
|
||||
return CHAR.primitiveArrayType;
|
||||
}
|
||||
else if ( boolean.class.getName().equals( typeNameString ) ) {
|
||||
return BOOLEAN.primitiveType;
|
||||
return BOOLEAN.primitiveArrayType;
|
||||
}
|
||||
else if ( byte.class.getName().equals( typeNameString ) ) {
|
||||
return BYTE.primitiveType;
|
||||
return BYTE.primitiveArrayType;
|
||||
}
|
||||
else if ( short.class.getName().equals( typeNameString ) ) {
|
||||
return SHORT.primitiveType;
|
||||
return SHORT.primitiveArrayType;
|
||||
}
|
||||
else if ( int.class.getName().equals( typeNameString ) ) {
|
||||
return INTEGER.primitiveType;
|
||||
return INTEGER.primitiveArrayType;
|
||||
}
|
||||
else if ( long.class.getName().equals( typeNameString ) ) {
|
||||
return LONG.primitiveType;
|
||||
return LONG.primitiveArrayType;
|
||||
}
|
||||
else if ( float.class.getName().equals( typeNameString ) ) {
|
||||
return FLOAT.primitiveType;
|
||||
return FLOAT.primitiveArrayType;
|
||||
}
|
||||
else if ( double.class.getName().equals( typeNameString ) ) {
|
||||
return DOUBLE.primitiveType;
|
||||
}
|
||||
else if ( double.class.getName().equals( typeNameString ) ) {
|
||||
return DOUBLE.primitiveWrapperType;
|
||||
return DOUBLE.primitiveArrayType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ArrayDescriptor primitiveArrayDescriptor(PrimitiveTypeDescriptor componentType) {
|
||||
if ( componentType == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ( (PrimitiveDescriptorImpl) componentType ).group.primitiveArrayType;
|
||||
}
|
||||
|
||||
public static JavaTypeDescriptor decipherArrayComponentCode(char arrayComponentCode) {
|
||||
switch ( arrayComponentCode ) {
|
||||
case 'C': {
|
||||
return CHAR.primitiveType;
|
||||
}
|
||||
case 'Z': {
|
||||
return BOOLEAN.primitiveType;
|
||||
}
|
||||
case 'B': {
|
||||
return BYTE.primitiveType;
|
||||
}
|
||||
case 'S': {
|
||||
return SHORT.primitiveType;
|
||||
}
|
||||
case 'I': {
|
||||
return INTEGER.primitiveType;
|
||||
}
|
||||
case 'J': {
|
||||
return LONG.primitiveType;
|
||||
}
|
||||
case 'F': {
|
||||
return FLOAT.primitiveType;
|
||||
}
|
||||
case 'D': {
|
||||
return DOUBLE.primitiveType;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected character passed in as primitive array component code : "
|
||||
+ arrayComponentCode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
System.out.println( " char : " + char[].class );
|
||||
System.out.println( "boolean : " + boolean[].class );
|
||||
System.out.println( " byte : " + byte[].class );
|
||||
System.out.println( " short : " + short[].class );
|
||||
System.out.println( " int : " + int[].class );
|
||||
System.out.println( " long : " + long[].class );
|
||||
System.out.println( " float : " + float[].class );
|
||||
System.out.println( " double : " + double[].class );
|
||||
}
|
||||
|
||||
private static class PrimitiveDescriptorImpl implements PrimitiveTypeDescriptor {
|
||||
private final Name name;
|
||||
private final DotName name;
|
||||
private final int modifiers;
|
||||
private final PrimitiveGroup group;
|
||||
|
||||
protected PrimitiveDescriptorImpl(Class clazz, PrimitiveGroup group) {
|
||||
this.name = new DotNameAdapter( clazz.getName() );
|
||||
this.name = DotName.createSimple( clazz.getName() );
|
||||
this.modifiers = clazz.getModifiers();
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
public DotName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -195,6 +249,56 @@ public class Primitives {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
if ( check == null ) {
|
||||
throw new IllegalArgumentException( "Descriptor to check cannot be null" );
|
||||
}
|
||||
|
||||
if ( equals( check ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if ( PrimitiveWrapperTypeDescriptor.class.isInstance( check ) ) {
|
||||
// final PrimitiveWrapperTypeDescriptor wrapper = (PrimitiveWrapperTypeDescriptor) check;
|
||||
// if ( equals( wrapper.getPrimitiveTypeDescriptor() ) ) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveWrapperTypeDescriptor getWrapperTypeDescriptor() {
|
||||
return group.primitiveWrapperType;
|
||||
|
@ -202,18 +306,18 @@ public class Primitives {
|
|||
}
|
||||
|
||||
private static class WrapperDescriptorImpl implements PrimitiveWrapperTypeDescriptor {
|
||||
private final Name name;
|
||||
private final DotName name;
|
||||
private final int modifiers;
|
||||
private final PrimitiveGroup group;
|
||||
|
||||
private WrapperDescriptorImpl(Class clazz, PrimitiveGroup group) {
|
||||
this.name = new DotNameAdapter( clazz.getName() );
|
||||
this.name = DotName.createSimple( clazz.getName() );
|
||||
this.modifiers = clazz.getModifiers();
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name getName() {
|
||||
public DotName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -232,6 +336,56 @@ public class Primitives {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check) {
|
||||
if ( check == null ) {
|
||||
throw new IllegalArgumentException( "Descriptor to check cannot be null" );
|
||||
}
|
||||
|
||||
if ( equals( check ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if ( PrimitiveTypeDescriptor.class.isInstance( check ) ) {
|
||||
// final PrimitiveTypeDescriptor primitive = (PrimitiveTypeDescriptor) check;
|
||||
// if ( equals( primitive.getWrapperTypeDescriptor() ) ) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getJandexClassInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveTypeDescriptor getPrimitiveTypeDescriptor() {
|
||||
return group.primitiveType;
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Describes a java type that represents a class definition.
|
||||
|
@ -56,18 +51,4 @@ public interface ClassDescriptor extends JavaTypeDescriptor {
|
|||
* @return The implemented interfaces
|
||||
*/
|
||||
public Collection<InterfaceDescriptor> getInterfaceTypes();
|
||||
|
||||
/**
|
||||
* Get the annotations defined on this type.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public Map<DotName, AnnotationInstance> getAnnotations();
|
||||
|
||||
/**
|
||||
* Get any parameters defined on the type.
|
||||
*
|
||||
* @return Any type parameters.
|
||||
*/
|
||||
public List<JavaTypeDescriptor> getTypeParameters();
|
||||
}
|
||||
|
|
|
@ -23,44 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Describes a field in a java type
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FieldDescriptor {
|
||||
/**
|
||||
* The field name
|
||||
*
|
||||
* @return The field name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* The type of the field.
|
||||
*
|
||||
* @return The type of the field.
|
||||
*/
|
||||
public JavaTypeDescriptor getType();
|
||||
|
||||
public int getModifiers();
|
||||
|
||||
/**
|
||||
* The declaring type
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public JavaTypeDescriptor getDeclaringType();
|
||||
|
||||
/**
|
||||
* Get the annotations defined on this field.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public Map<DotName, AnnotationInstance> getAnnotations();
|
||||
public interface FieldDescriptor extends MemberDescriptor {
|
||||
}
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Describes a java type that represents an interface definition.
|
||||
|
@ -42,18 +37,4 @@ public interface InterfaceDescriptor extends JavaTypeDescriptor {
|
|||
* @return The implemented interfaces
|
||||
*/
|
||||
public Collection<InterfaceDescriptor> getExtendedInterfaceTypes();
|
||||
|
||||
/**
|
||||
* Get the annotations defined on this type.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public Map<DotName, AnnotationInstance> getAnnotations();
|
||||
|
||||
/**
|
||||
* Get any parameters defined on the type.
|
||||
*
|
||||
* @return Any type parameters.
|
||||
*/
|
||||
public List<JavaTypeDescriptor> getTypeParameters();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Describes information about a Java type. Might (more concretely) be any of:<ul>
|
||||
|
@ -43,7 +48,7 @@ public interface JavaTypeDescriptor {
|
|||
*
|
||||
* @return The type name
|
||||
*/
|
||||
public Name getName();
|
||||
public DotName getName();
|
||||
|
||||
/**
|
||||
* Access the type's modifiers. See {@link java.lang.reflect.Modifier}
|
||||
|
@ -65,4 +70,75 @@ public interface JavaTypeDescriptor {
|
|||
* @return All fields declared by this type
|
||||
*/
|
||||
public Collection<MethodDescriptor> getDeclaredMethods();
|
||||
|
||||
/**
|
||||
* Get the resolved type descriptors for any parameterized type arguments defined on the type.
|
||||
* <p/>
|
||||
* For example, given a JavaTypeDescriptor describing a parameterized Java type resolved to
|
||||
* be {@code List<Person>}, this method would return JavaTypeDescriptor for {@code Person}
|
||||
*
|
||||
* @return The resolved parameter type descriptors
|
||||
*/
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes();
|
||||
|
||||
/**
|
||||
* Get the Jandex ClassInfo object for this type.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public ClassInfo getJandexClassInfo();
|
||||
|
||||
/**
|
||||
* Get the annotation of the named type, if one, defined on this type
|
||||
* or any of its super-types
|
||||
*
|
||||
* @param annotationType DotName of the type of annotation to find.
|
||||
*
|
||||
* @return The annotation.
|
||||
*/
|
||||
public AnnotationInstance findTypeAnnotation(DotName annotationType);
|
||||
|
||||
/**
|
||||
* Get the annotation of the named type, if one, defined on this type.
|
||||
*
|
||||
* @param annotationType DotName of the type of annotation to find.
|
||||
*
|
||||
* @return The annotation.
|
||||
*/
|
||||
public AnnotationInstance findLocalTypeAnnotation(DotName annotationType);
|
||||
|
||||
/**
|
||||
* Locate all annotations of the given type within the bounds of this type.
|
||||
* "Within bounds" means on the type itself, on its fields and on its
|
||||
* methods.
|
||||
* <p/>
|
||||
* This form (as opposed to {@link #findLocalAnnotations}) also checks super
|
||||
* types.
|
||||
*
|
||||
* @param annotationType DotName of the type of annotation to find.
|
||||
*
|
||||
* @return The annotations found.
|
||||
*/
|
||||
public Collection<AnnotationInstance> findAnnotations(DotName annotationType);
|
||||
|
||||
/**
|
||||
* Locate all annotations of the given type within the bounds of this type.
|
||||
* "Within bounds" means on the type itself, on its fields and on its
|
||||
* methods.
|
||||
*
|
||||
* @param annotationType DotName of the type of annotation to find.
|
||||
*
|
||||
* @return The annotations found.
|
||||
*/
|
||||
public Collection<AnnotationInstance> findLocalAnnotations(DotName annotationType);
|
||||
|
||||
/**
|
||||
* Same function as the {@link Class#isAssignableFrom(Class)} method.
|
||||
*
|
||||
* @param check The type to be checked
|
||||
*
|
||||
* @return the {@code boolean} value indicating whether objects of the
|
||||
* type {@code cls} can be assigned to references of this type
|
||||
*/
|
||||
public boolean isAssignableFrom(JavaTypeDescriptor check);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* The repository of reflite JavaTypeDescriptor info.
|
||||
*
|
||||
|
@ -36,7 +38,7 @@ public interface JavaTypeDescriptorRepository {
|
|||
*
|
||||
* @return The type-safe wrapper.
|
||||
*/
|
||||
public Name buildName(String name);
|
||||
public DotName buildName(String name);
|
||||
|
||||
/**
|
||||
* Obtain the reflite JavaTypeDescriptor for the given name
|
||||
|
@ -45,5 +47,43 @@ public interface JavaTypeDescriptorRepository {
|
|||
*
|
||||
* @return The descriptor
|
||||
*/
|
||||
public JavaTypeDescriptor getType(Name typeName);
|
||||
public JavaTypeDescriptor getType(DotName typeName);
|
||||
|
||||
/**
|
||||
* Create a reflite JavaTypeDescriptor representing an array of the
|
||||
* given type
|
||||
*
|
||||
* @param componentType The array component (element) type
|
||||
*
|
||||
* @return The array descriptor
|
||||
*/
|
||||
public ArrayDescriptor arrayType(JavaTypeDescriptor componentType);
|
||||
|
||||
/**
|
||||
* Convenient access to the descriptor for the JDK {@link java.util.Collection} type
|
||||
*
|
||||
* @return The descriptor for the JDK {@link java.util.Collection} type
|
||||
*/
|
||||
public InterfaceDescriptor jdkCollectionDescriptor();
|
||||
|
||||
/**
|
||||
* Convenient access to the descriptor for the JDK {@link java.util.List} type
|
||||
*
|
||||
* @return The descriptor for the JDK {@link java.util.List} type
|
||||
*/
|
||||
public InterfaceDescriptor jdkListDescriptor();
|
||||
|
||||
/**
|
||||
* Convenient access to the descriptor for the JDK {@link java.util.Set} type
|
||||
*
|
||||
* @return The descriptor for the JDK {@link java.util.Set} type
|
||||
*/
|
||||
public InterfaceDescriptor jdkSetDescriptor();
|
||||
|
||||
/**
|
||||
* Convenient access to the descriptor for the JDK {@link java.util.Map} type
|
||||
*
|
||||
* @return The descriptor for the JDK {@link java.util.Map} type
|
||||
*/
|
||||
public InterfaceDescriptor jdkMapDescriptor();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.reflite.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Common contract for method and field descriptors.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface MemberDescriptor {
|
||||
/**
|
||||
* The member name
|
||||
*
|
||||
* @return The member name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* The member type. For fields, this is the field type. For methods,
|
||||
* this is the method return type.
|
||||
*
|
||||
* @return The member type.
|
||||
*/
|
||||
public ParameterizedType getType();
|
||||
|
||||
/**
|
||||
* Access to the modifiers for the member.
|
||||
*
|
||||
* @return The modifiers.
|
||||
*/
|
||||
public int getModifiers();
|
||||
|
||||
/**
|
||||
* The declaring type
|
||||
*
|
||||
* @return The declaring type
|
||||
*/
|
||||
public JavaTypeDescriptor getDeclaringType();
|
||||
|
||||
/**
|
||||
* Get the annotations defined on this field.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public Map<DotName, AnnotationInstance> getAnnotations();
|
||||
|
||||
/**
|
||||
* Get a String representation this member that is usable in logging. In
|
||||
* general this is in the form {declaringType}#{name}
|
||||
*
|
||||
* @return The loggable representation
|
||||
*/
|
||||
public String toLoggableForm();
|
||||
|
||||
/**
|
||||
* Get the String representation of this members signature.
|
||||
*
|
||||
* @return The signature representation
|
||||
*/
|
||||
public String toSignatureForm();
|
||||
}
|
|
@ -24,57 +24,25 @@
|
|||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* Describes a method in a java type
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface MethodDescriptor {
|
||||
/**
|
||||
* The name of the method
|
||||
*
|
||||
* @return The name of the method
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* The type declaring this method
|
||||
*
|
||||
* @return The type declaring this method
|
||||
*/
|
||||
public JavaTypeDescriptor getDeclaringType();
|
||||
|
||||
/**
|
||||
* The modifiers for this method. See {@link java.lang.reflect.Modifier}
|
||||
*
|
||||
* @return The modifiers for this method
|
||||
*/
|
||||
public int getModifiers();
|
||||
|
||||
public interface MethodDescriptor extends MemberDescriptor {
|
||||
/**
|
||||
* The descriptor of the method's return type
|
||||
*
|
||||
* @return The descriptor of the method's return type
|
||||
*/
|
||||
public JavaTypeDescriptor getReturnType();
|
||||
public ParameterizedType getReturnType();
|
||||
|
||||
/**
|
||||
* The descriptor of the method's argument types
|
||||
*
|
||||
* @return The descriptor of the method's argument types
|
||||
*/
|
||||
public Collection<JavaTypeDescriptor> getParameterTypes();
|
||||
|
||||
/**
|
||||
* Get the annotations defined on this method.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public Map<DotName, AnnotationInstance> getAnnotations();
|
||||
public Collection<JavaTypeDescriptor> getArgumentTypes();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* 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.
|
||||
|
@ -21,15 +21,14 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
package org.hibernate.metamodel.reflite.spi;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UnknownInheritanceTypeException extends HibernateException {
|
||||
public UnknownInheritanceTypeException(String message) {
|
||||
super( message );
|
||||
}
|
||||
public interface ParameterizedType {
|
||||
public JavaTypeDescriptor getErasedType();
|
||||
public List<JavaTypeDescriptor> getResolvedParameterTypes();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue