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:
Steve Ebersole 2014-03-17 13:06:32 -05:00
parent 0329f37d99
commit c06a45a636
522 changed files with 19500 additions and 12439 deletions

View File

@ -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 );
}
}

View File

@ -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;

View File

@ -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 {};
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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()

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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()
)
)
);
}
}
}

View File

@ -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() );
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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.
*

View File

@ -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 ) );
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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" );
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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 );
}
}
}

View File

@ -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 );
}
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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 {
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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()
)
);
}

View File

@ -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) {

View File

@ -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()

View File

@ -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
);

View File

@ -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 );

View File

@ -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();
}
}

View File

@ -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?

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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
)

View File

@ -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 );
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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 );
// }
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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()
)
);
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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 );
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 );
}
}

View File

@ -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;
}
}
}

View File

@ -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 ) );
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 "
);
}
}
}

View File

@ -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 );
}
}
}

View File

@ -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() );
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 + '}';

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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 + '}';

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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