HHH-7893 - Refactoring Binder code

This commit is contained in:
Strong Liu 2012-12-27 13:36:09 +08:00
parent 0ddb9b914a
commit 288823d2dd
2 changed files with 2572 additions and 2191 deletions

View File

@ -33,15 +33,20 @@ import java.util.Properties;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.internal.util.beans.BeanInfoHelper; import org.hibernate.internal.util.beans.BeanInfoHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.binding.TypeDefinition; import org.hibernate.metamodel.spi.binding.TypeDefinition;
@ -51,62 +56,334 @@ import org.hibernate.metamodel.spi.relational.AbstractValue;
import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.JdbcDataType;
import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.metamodel.spi.source.AttributeSource; 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.ComponentAttributeSource;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
import org.hibernate.metamodel.spi.source.SingularAttributeSource; import org.hibernate.metamodel.spi.source.SingularAttributeSource;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
/** /**
* Delegate for handling:<ol> * Delegate for handling:<ol>
* <li> * <li>
* binding of Hibernate type information ({@link ExplicitHibernateTypeSource} -> * binding of Hibernate type information ({@link ExplicitHibernateTypeSource} ->
* {@link HibernateTypeDescriptor} * {@link HibernateTypeDescriptor}
* </li> * </li>
* <li> * <li>
* attempt to resolve the actual {@link Type} instance * attempt to resolve the actual {@link Type} instance
* </li> * </li>
* <li> * <li>
* push java type and JDBC type information reported by the {@link Type} instance to relational/ * push java type and JDBC type information reported by the {@link Type} instance to relational/
* domain models. * domain models.
* </li> * </li>
* </ol> * </ol>
* <p/> * <p/>
* Methods intended as entry points are:<ul> * Methods intended as entry points are:<ul>
* <li>{@link #bindSingularAttributeTypeInformation}</li> * <li>{@link #bindSingularAttributeTypeInformation}</li>
* </ul> * </ul>
* <p/> * <p/>
* Currently the following methods are also required to be non-private because of handling discriminators which * Currently the following methods are also required to be non-private because of handling discriminators which
* are currently not modeled using attributes:<ul> * are currently not modeled using attributes:<ul>
* <li>{@link #bindJdbcDataType(org.hibernate.type.Type, org.hibernate.metamodel.spi.relational.Value)}</li> * <li>{@link #bindJdbcDataType(org.hibernate.type.Type, org.hibernate.metamodel.spi.relational.Value)}</li>
* </ul> * </ul>
* *
* @author Steve Ebersole * @author Steve Ebersole
* @author Gail Badner * @author Gail Badner
* @author Brett Meyer * @author Brett Meyer
*/ */
public class HibernateTypeHelper { class HibernateTypeHelper {
private static final Logger log = Logger.getLogger( HibernateTypeHelper.class ); private static final Logger log = Logger.getLogger( HibernateTypeHelper.class );
/* package-protected */
static class ReflectedCollectionJavaTypes {
private final String collectionTypeName;
private final String collectionElementTypeName;
private final String collectionIndexTypeName;
private ReflectedCollectionJavaTypes(
Class<?> collectionType,
Class<?> collectionElementType,
Class<?> collectionIndexType) {
this.collectionTypeName = collectionType != null ? collectionType.getName() : null;
this.collectionElementTypeName = collectionElementType != null ? collectionElementType.getName() : null;
this.collectionIndexTypeName = collectionIndexType != null ? collectionIndexType.getName() : null;
}
String getCollectionElementTypeName() {
return collectionElementTypeName;
}
String getCollectionIndexTypeName() {
return collectionIndexTypeName;
}
String getCollectionTypeName() {
return collectionTypeName;
}
}
static String defaultCollectionElementJavaTypeName(
final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) {
return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionElementTypeName() : null;
}
static String defaultCollectionIndexJavaTypeName(
final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) {
return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionIndexTypeName() : null;
}
static String defaultCollectionJavaTypeName(
final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes,
final PluralAttributeSource attributeSource) {
return reflectedCollectionJavaTypes != null ? reflectedCollectionJavaTypes.getCollectionTypeName() : attributeSource
.getNature()
.reportedJavaType()
.getName();
}
static void bindHibernateResolvedType(
final HibernateTypeDescriptor hibernateTypeDescriptor,
final Type resolvedType) {
// Configure relational value JDBC type from Hibernate type descriptor now that its configured
if ( resolvedType != null ) {
hibernateTypeDescriptor.setResolvedTypeMapping( resolvedType );
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
hibernateTypeDescriptor.setJavaTypeName( resolvedType.getReturnedClass().getName() );
}
hibernateTypeDescriptor.setToOne( resolvedType.isEntityType() );
}
}
private final Binder binder; private final Binder binder;
private final MetadataImplementor metadata; private final MetadataImplementor metadata;
public HibernateTypeHelper( Binder binder, //package scope methods
MetadataImplementor metadata ) { HibernateTypeHelper(Binder binder,
MetadataImplementor metadata) {
this.binder = binder; this.binder = binder;
this.metadata = metadata; this.metadata = metadata;
} }
private org.hibernate.metamodel.spi.domain.Type makeJavaType(String name) { /**
return binder.bindingContext().makeJavaType( name ); * Bind relational types using hibernate type just resolved.
*
* @param resolvedHibernateType The hibernate type resolved from metadata.
* @param value The relational value to be binded.
*/
void bindJdbcDataType(
final Type resolvedHibernateType,
final Value value) {
if ( value.getJdbcDataType() == null && resolvedHibernateType != null && value != null ) {
final Type resolvedRelationalType =
resolvedHibernateType.isEntityType()
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata )
: resolvedHibernateType;
if ( AbstractValue.class.isInstance( value ) ) {
( (AbstractValue) value ).setJdbcDataType(
new JdbcDataType(
resolvedRelationalType.sqlTypes( metadata )[0],
resolvedRelationalType.getName(),
resolvedRelationalType.getReturnedClass()
)
);
}
}
} }
public void bindSingularAttributeTypeInformation( void bindJdbcDataType(
SingularAttributeSource attributeSource, final Type resolvedHibernateType,
SingularAttributeBinding attributeBinding) { final List<RelationalValueBinding> relationalValueBindings) {
if ( relationalValueBindings.size() <= 1 ) {
bindJdbcDataType( resolvedHibernateType, relationalValueBindings.get( 0 ).getValue() );
return;
}
final Type resolvedRelationalType =
resolvedHibernateType.isEntityType()
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata )
: resolvedHibernateType;
if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) {
throw binder.bindingContext()
.makeMappingException( "Column number mismatch" ); // todo refine the exception message
}
Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes();
for ( int i = 0; i < subTypes.length; i++ ) {
bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() );
}
}
void bindBasicCollectionElementType(
final BasicPluralAttributeElementBinding elementBinding,
final BasicPluralAttributeElementSource elementSource,
final String defaultElementJavaTypeName) {
bindHibernateTypeDescriptor(
elementBinding.getHibernateTypeDescriptor(),
elementSource.getExplicitHibernateTypeSource(),
defaultElementJavaTypeName
);
Type resolvedElementType = heuristicType( elementBinding.getHibernateTypeDescriptor() );
bindHibernateResolvedType( elementBinding.getHibernateTypeDescriptor(), resolvedElementType );
bindJdbcDataType(
resolvedElementType,
elementBinding.getRelationalValueBindings()
);
}
Type resolvePluralType(
final PluralAttributeBinding pluralAttributeBinding,
final PluralAttributeSource pluralAttributeSource,
final PluralAttributeSource.Nature nature) {
if ( pluralAttributeBinding.getHibernateTypeDescriptor().getExplicitTypeName() != null ) {
return resolveCustomCollectionType( pluralAttributeBinding );
}
else {
final TypeFactory typeFactory = metadata.getTypeResolver().getTypeFactory();
final String role = pluralAttributeBinding.getAttribute().getRole();
final String propertyRef = getReferencedPropertyNameIfNotId( pluralAttributeBinding );
final boolean embedded = pluralAttributeBinding.getPluralAttributeElementBinding()
.getNature() == PluralAttributeElementBinding.Nature.AGGREGATE;
switch ( nature ) {
case BAG:
return typeFactory.bag( role, propertyRef, embedded );
case LIST:
return typeFactory.list( role, propertyRef, embedded );
case ARRAY:
return typeFactory.array(
role,
propertyRef,
embedded,
pluralAttributeSource.getElementClassReference().getValue()
);
case MAP:
if ( pluralAttributeBinding.isSorted() ) {
return typeFactory.sortedMap(
role,
propertyRef,
embedded,
pluralAttributeBinding.getComparator()
);
}
// TODO: else if ( pluralAttributeBinding.hasOrder() ) { orderedMap... }
else {
return typeFactory.map( role, propertyRef, embedded );
}
case SET:
if ( pluralAttributeBinding.isSorted() ) {
return typeFactory.sortedSet(
role,
propertyRef,
embedded,
pluralAttributeBinding.getComparator()
);
}
// TODO: else if ( pluralAttributeBinding.hasOrder() ) { orderedSet... }
else {
return typeFactory.set( role, propertyRef, embedded );
}
default:
throw new NotYetImplementedException( nature + " is to be implemented" );
}
}
}
Type heuristicType(
final HibernateTypeDescriptor hibernateTypeDescriptor) {
final String typeName =
hibernateTypeDescriptor.getExplicitTypeName() != null
? hibernateTypeDescriptor.getExplicitTypeName()
: hibernateTypeDescriptor.getJavaTypeName();
final Properties properties = new Properties();
properties.putAll( hibernateTypeDescriptor.getTypeParameters() );
return metadata.getTypeResolver().heuristicType( typeName, properties );
}
// TODO: The following 3 methods should eventually be replaced w/
// typeHelper use.
void bindHibernateTypeDescriptor(
final HibernateTypeDescriptor hibernateTypeDescriptor,
final ExplicitHibernateTypeSource explicitTypeSource,
final ValueHolder<Class<?>> defaultJavaType) {
// if there is an explicit type name specified, then there's no reason to
// initialize the default Java type name; simply pass a null default instead.
bindHibernateTypeDescriptor(
hibernateTypeDescriptor,
explicitTypeSource,
explicitTypeSource == null || explicitTypeSource.getName() == null
? defaultJavaType.getValue().getName()
: null
);
}
void bindHibernateTypeDescriptor(
final HibernateTypeDescriptor hibernateTypeDescriptor,
final ExplicitHibernateTypeSource explicitTypeSource,
final String defaultJavaTypeName) {
if ( explicitTypeSource == null ) {
bindHibernateTypeDescriptor(
hibernateTypeDescriptor, null, null, defaultJavaTypeName
);
}
else {
bindHibernateTypeDescriptor(
hibernateTypeDescriptor,
explicitTypeSource.getName(),
explicitTypeSource.getParameters(),
defaultJavaTypeName
);
}
}
void bindHibernateTypeDescriptor(
final HibernateTypeDescriptor hibernateTypeDescriptor,
final String explicitTypeName,
final Map<String, String> explictTypeParameters,
final String defaultJavaTypeName) {
if ( explicitTypeName == null ) {
if ( hibernateTypeDescriptor.getJavaTypeName() != null ) {
throw binder.bindingContext().makeMappingException(
String.format(
"Attempt to re-initialize (non-explicit) Java type name; current=%s new=%s",
hibernateTypeDescriptor.getJavaTypeName(),
defaultJavaTypeName
)
);
}
hibernateTypeDescriptor.setJavaTypeName( defaultJavaTypeName );
}
else {
// Check if user-specified name is of a User-Defined Type (UDT)
final TypeDefinition typeDef = metadata.getTypeDefinition( explicitTypeName );
if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) {
throw binder.bindingContext().makeMappingException(
String.format(
"Attempt to re-initialize explicity-mapped Java type name; current=%s new=%s",
hibernateTypeDescriptor.getExplicitTypeName(),
explicitTypeName
)
);
}
if ( typeDef == null ) {
hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName );
}
else {
hibernateTypeDescriptor.setExplicitTypeName( typeDef.getTypeImplementorClass().getName() );
// Don't use set() -- typeDef#parameters is unmodifiable
hibernateTypeDescriptor.getTypeParameters().putAll( typeDef.getParameters() );
}
if ( explictTypeParameters != null ) {
hibernateTypeDescriptor.getTypeParameters().putAll( explictTypeParameters );
}
}
}
void bindSingularAttributeTypeInformation(
final SingularAttributeSource attributeSource,
final SingularAttributeBinding attributeBinding) {
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding
.getHibernateTypeDescriptor(); .getHibernateTypeDescriptor();
@ -117,26 +394,35 @@ public class HibernateTypeHelper {
attributeBinding.getAttribute() attributeBinding.getAttribute()
) : null; ) : null;
if ( attributeJavaType != null ) { if ( attributeJavaType != null ) {
attributeBinding.getAttribute().resolveType( makeJavaType( attributeBinding.getAttribute().resolveType(
attributeJavaType.getName() ) ); makeJavaType(
attributeJavaType.getName()
)
);
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) { if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
hibernateTypeDescriptor.setJavaTypeName( hibernateTypeDescriptor.setJavaTypeName(
attributeJavaType.getName() ); attributeJavaType.getName()
);
} }
} }
bindHibernateTypeInformation( attributeSource.getTypeInformation(), bindHibernateTypeInformation(
hibernateTypeDescriptor ); attributeSource.getTypeInformation(),
hibernateTypeDescriptor
);
processSingularAttributeTypeInformation( attributeSource, processSingularAttributeTypeInformation(
attributeBinding ); attributeSource,
attributeBinding
);
} }
public ReflectedCollectionJavaTypes getReflectedCollectionJavaTypes( ReflectedCollectionJavaTypes getReflectedCollectionJavaTypes(
PluralAttributeBinding attributeBinding) { final PluralAttributeBinding attributeBinding) {
return determineJavaType( attributeBinding.getAttribute() ); return determineJavaType( attributeBinding.getAttribute() );
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private scope methods
private Class<?> determineJavaType(final SingularAttribute attribute) { private Class<?> determineJavaType(final SingularAttribute attribute) {
try { try {
final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference(); final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference();
@ -181,29 +467,33 @@ public class HibernateTypeHelper {
private void bindHibernateTypeInformation( private void bindHibernateTypeInformation(
final ExplicitHibernateTypeSource typeSource, final ExplicitHibernateTypeSource typeSource,
final HibernateTypeDescriptor hibernateTypeDescriptor) { final HibernateTypeDescriptor hibernateTypeDescriptor) {
final String explicitTypeName = typeSource.getName(); final String explicitTypeName = typeSource.getName();
if ( explicitTypeName != null ) { if ( explicitTypeName != null ) {
final TypeDefinition typeDefinition = metadata.getTypeDefinition( final TypeDefinition typeDefinition = metadata.getTypeDefinition(
explicitTypeName ); explicitTypeName
);
if ( typeDefinition != null ) { if ( typeDefinition != null ) {
hibernateTypeDescriptor.setExplicitTypeName( hibernateTypeDescriptor.setExplicitTypeName(
typeDefinition.getTypeImplementorClass().getName() ); typeDefinition.getTypeImplementorClass().getName()
);
// Don't use set() -- typeDef#parameters is unmodifiable // Don't use set() -- typeDef#parameters is unmodifiable
hibernateTypeDescriptor.getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters().putAll(
typeDefinition.getParameters() ); typeDefinition.getParameters()
);
} }
else { else {
hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName ); hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName );
} }
// TODO: Should type parameters be used for @TypeDefs? // TODO: Should type parameters be used for @TypeDefs?
final Map<String, String> parameters = typeSource.getParameters(); final Map<String, String> parameters = typeSource.getParameters();
if ( parameters != null ) { if ( parameters != null ) {
// Don't use set() -- typeDef#parameters is unmodifiable // Don't use set() -- typeDef#parameters is unmodifiable
hibernateTypeDescriptor.getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters().putAll(
parameters ); parameters
);
} }
} }
} }
@ -216,8 +506,8 @@ public class HibernateTypeHelper {
* @param attributeBinding The attribute. * @param attributeBinding The attribute.
*/ */
private void processSingularAttributeTypeInformation( private void processSingularAttributeTypeInformation(
SingularAttributeSource attributeSource, final SingularAttributeSource attributeSource,
SingularAttributeBinding attributeBinding) { final SingularAttributeBinding attributeBinding) {
Type resolvedType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); Type resolvedType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
if ( resolvedType == null ) { if ( resolvedType == null ) {
@ -235,7 +525,8 @@ public class HibernateTypeHelper {
} }
} }
private Type determineHibernateTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { private Type determineHibernateTypeFromDescriptor(
final HibernateTypeDescriptor hibernateTypeDescriptor) {
if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) {
return hibernateTypeDescriptor.getResolvedTypeMapping(); return hibernateTypeDescriptor.getResolvedTypeMapping();
} }
@ -246,12 +537,14 @@ public class HibernateTypeHelper {
return type; return type;
} }
private Type getHeuristicType(String typeName, Properties typeParameters) { private Type getHeuristicType(
final String typeName,
final Properties typeParameters) {
if ( typeName != null ) { if ( typeName != null ) {
try { try {
return metadata.getTypeResolver().heuristicType( typeName, typeParameters ); return metadata.getTypeResolver().heuristicType( typeName, typeParameters );
} }
catch (Exception ignore) { catch ( Exception ignore ) {
} }
} }
@ -260,7 +553,8 @@ public class HibernateTypeHelper {
private static final Properties EMPTY_PROPERTIES = new Properties(); private static final Properties EMPTY_PROPERTIES = new Properties();
private Type determineHibernateTypeFromAttributeJavaType(SingularAttribute singularAttribute) { private Type determineHibernateTypeFromAttributeJavaType(
final SingularAttribute singularAttribute) {
if ( singularAttribute.getSingularAttributeType() != null ) { if ( singularAttribute.getSingularAttributeType() != null ) {
return getHeuristicType( return getHeuristicType(
singularAttribute.getSingularAttributeType().getClassName(), singularAttribute.getSingularAttributeType().getClassName(),
@ -270,27 +564,10 @@ public class HibernateTypeHelper {
return null; return null;
} }
private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) {
return hibernateTypeDescriptor.getExplicitTypeName() != null
? hibernateTypeDescriptor.getExplicitTypeName()
: hibernateTypeDescriptor.getJavaTypeName();
}
private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) {
if ( CollectionHelper.isEmpty( hibernateTypeDescriptor.getTypeParameters() ) ) {
return EMPTY_PROPERTIES;
}
else {
Properties typeParameters = new Properties();
typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() );
return typeParameters;
}
}
private void pushHibernateTypeInformationDown( private void pushHibernateTypeInformationDown(
SingularAttributeSource attributeSource, final SingularAttributeSource attributeSource,
SingularAttributeBinding attributeBinding, final SingularAttributeBinding attributeBinding,
Type resolvedHibernateType) { final Type resolvedHibernateType) {
// sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) { if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) {
@ -309,14 +586,14 @@ public class HibernateTypeHelper {
} }
private void pushHibernateTypeInformationDown( private void pushHibernateTypeInformationDown(
BasicAttributeBinding attributeBinding, final BasicAttributeBinding attributeBinding,
Type resolvedHibernateType) { final Type resolvedHibernateType) {
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null && hibernateTypeDescriptor.getJavaTypeName() == null ) { if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null && hibernateTypeDescriptor.getJavaTypeName() == null ) {
hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() ); hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() );
} }
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
} }
pushHibernateTypeInformationDown( pushHibernateTypeInformationDown(
@ -326,14 +603,14 @@ public class HibernateTypeHelper {
); );
} }
@SuppressWarnings( {"UnusedParameters"}) @SuppressWarnings({ "UnusedParameters" })
private void pushHibernateTypeInformationDown( private void pushHibernateTypeInformationDown(
ComponentAttributeSource attributeSource, final ComponentAttributeSource attributeSource,
CompositeAttributeBinding attributeBinding, final CompositeAttributeBinding attributeBinding,
Type resolvedHibernateType) { final Type resolvedHibernateType) {
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
} }
@ -342,20 +619,23 @@ public class HibernateTypeHelper {
AttributeSource subAttributeSource = subAttributeSourceIterator.next(); AttributeSource subAttributeSource = subAttributeSourceIterator.next();
if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) {
processSingularAttributeTypeInformation( processSingularAttributeTypeInformation(
( SingularAttributeSource ) subAttributeSource, (SingularAttributeSource) subAttributeSource,
SingularAttributeBinding.class.cast( subAttributeBinding ) SingularAttributeBinding.class.cast( subAttributeBinding )
); );
} }
else { else {
throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() ); throw new AssertionFailure(
"Unknown type of AttributeBinding: " + attributeBinding.getClass()
.getName()
);
} }
} }
} }
private void pushHibernateTypeInformationDown( private void pushHibernateTypeInformationDown(
HibernateTypeDescriptor hibernateTypeDescriptor, final HibernateTypeDescriptor hibernateTypeDescriptor,
List<RelationalValueBinding> relationalValueBindings, final List<RelationalValueBinding> relationalValueBindings,
Type resolvedHibernateType) { final Type resolvedHibernateType) {
if ( resolvedHibernateType == null ) { if ( resolvedHibernateType == null ) {
return; return;
} }
@ -368,84 +648,66 @@ public class HibernateTypeHelper {
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) { if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() ); hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() );
} }
hibernateTypeDescriptor.setToOne( resolvedHibernateType.isEntityType() ); hibernateTypeDescriptor.setToOne( resolvedHibernateType.isEntityType() );
bindJdbcDataType( resolvedHibernateType, relationalValueBindings ); bindJdbcDataType( resolvedHibernateType, relationalValueBindings );
} }
/** private org.hibernate.metamodel.spi.domain.Type makeJavaType(String name) {
* Bind relational types using hibernate type just resolved. return binder.bindingContext().makeJavaType( name );
* }
* @param resolvedHibernateType The hibernate type resolved from metadata.
* @param value The relational value to be binded. private Type resolveCustomCollectionType(
*/ final PluralAttributeBinding pluralAttributeBinding) {
public void bindJdbcDataType(Type resolvedHibernateType, Value value) { final HibernateTypeDescriptor hibernateTypeDescriptor = pluralAttributeBinding.getHibernateTypeDescriptor();
if ( value.getJdbcDataType() == null && resolvedHibernateType != null && value != null ) { Properties typeParameters = new Properties();
final Type resolvedRelationalType = typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() );
resolvedHibernateType.isEntityType() return metadata.getTypeResolver().getTypeFactory().customCollection(
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata ) hibernateTypeDescriptor.getExplicitTypeName(),
: resolvedHibernateType; typeParameters,
if ( AbstractValue.class.isInstance( value ) ) { pluralAttributeBinding.getAttribute().getName(),
( (AbstractValue) value ).setJdbcDataType( getReferencedPropertyNameIfNotId( pluralAttributeBinding ),
new JdbcDataType( pluralAttributeBinding.getPluralAttributeElementBinding()
resolvedRelationalType.sqlTypes( metadata )[0], .getNature() == PluralAttributeElementBinding.Nature.AGGREGATE
resolvedRelationalType.getName(), );
resolvedRelationalType.getReturnedClass() }
)
); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private static methods
} private static String determineTypeName(
final HibernateTypeDescriptor hibernateTypeDescriptor) {
return hibernateTypeDescriptor.getExplicitTypeName() != null
? hibernateTypeDescriptor.getExplicitTypeName()
: hibernateTypeDescriptor.getJavaTypeName();
}
private static Properties getTypeParameters(
final HibernateTypeDescriptor hibernateTypeDescriptor) {
if ( CollectionHelper.isEmpty( hibernateTypeDescriptor.getTypeParameters() ) ) {
return EMPTY_PROPERTIES;
}
else {
Properties typeParameters = new Properties();
typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() );
return typeParameters;
} }
} }
public void bindJdbcDataType(Type resolvedHibernateType, List<RelationalValueBinding> relationalValueBindings) { private static String getReferencedPropertyNameIfNotId(
if ( relationalValueBindings.size() <= 1 ) { final PluralAttributeBinding pluralAttributeBinding) {
bindJdbcDataType( resolvedHibernateType, relationalValueBindings.get( 0 ).getValue() ); EntityIdentifier entityIdentifier =
return; pluralAttributeBinding.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
} final String idAttributeName =
final Type resolvedRelationalType = entityIdentifier.getAttributeBinding().getAttribute().getName();
resolvedHibernateType.isEntityType() return pluralAttributeBinding.getReferencedPropertyName().equals( idAttributeName ) ?
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata ) null :
: resolvedHibernateType; pluralAttributeBinding.getReferencedPropertyName();
if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) {
throw binder.bindingContext().makeMappingException( "Column number mismatch" ); // todo refine the exception message
}
Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes();
for ( int i = 0; i < subTypes.length; i++ ) {
bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() );
}
}
/* package-protected */
static class ReflectedCollectionJavaTypes {
private final Class<?> collectionType;
private final Class<?> collectionElementType;
private final Class<?> collectionIndexType;
private ReflectedCollectionJavaTypes(
Class<?> collectionType,
Class<?> collectionElementType,
Class<?> collectionIndexType) {
this.collectionType = collectionType;
this.collectionElementType = collectionElementType;
this.collectionIndexType = collectionIndexType;
}
public Class<?> getCollectionType() {
return collectionType;
}
public Class<?> getCollectionElementType() {
return collectionElementType;
}
public Class<?> getCollectionIndexType() {
return collectionIndexType;
}
} }
/** /**
* @see HibernateTypeHelper#determineJavaType(PluralAttribute) * @see HibernateTypeHelper#determineJavaType(PluralAttribute)
*/ */
private class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { private static class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate {
private final Class<?> ownerClass; private final Class<?> ownerClass;
private final String attributeName; private final String attributeName;