mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-10 13:14:50 +00:00
HHH-7076 - Split 'type resolution' back out into separate class
This commit is contained in:
parent
9adb996520
commit
f5679281e0
@ -23,9 +23,6 @@
|
||||
*/
|
||||
package org.hibernate.metamodel.internal.source;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@ -45,12 +42,9 @@
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||
import org.hibernate.metamodel.internal.source.hbm.Helper;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||
@ -58,7 +52,6 @@
|
||||
import org.hibernate.metamodel.spi.binding.CompositionAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
|
||||
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.IdGenerator;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
@ -67,18 +60,15 @@
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.TypeDefinition;
|
||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||
import org.hibernate.metamodel.spi.domain.Composition;
|
||||
import org.hibernate.metamodel.spi.domain.Entity;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttribute;
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.AbstractValue;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.JdbcDataType;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
@ -95,7 +85,6 @@
|
||||
import org.hibernate.metamodel.spi.source.DiscriminatorSource;
|
||||
import org.hibernate.metamodel.spi.source.EntityHierarchy;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
@ -123,7 +112,6 @@
|
||||
import org.hibernate.service.config.spi.ConfigurationService;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
|
||||
/**
|
||||
* The common binder shared between annotations and {@code hbm.xml} processing.
|
||||
@ -132,6 +120,7 @@
|
||||
*
|
||||
* @todo Really need to chop this up. The class is doing so many different things right now.
|
||||
* @todo And really need to come up with consistent method naming.
|
||||
* @todo This class really should live in the o.h.metamodel.internal package
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Hardy Ferentschik
|
||||
@ -140,6 +129,8 @@ public class Binder {
|
||||
private final MetadataImplementor metadata;
|
||||
private final ArrayList<String> processedEntityNames = new ArrayList<String>();
|
||||
|
||||
private HibernateTypeHelper typeHelper = new HibernateTypeHelper( this );
|
||||
|
||||
private final ObjectNameNormalizer NAME_NORMALIZER = new ObjectNameNormalizer() {
|
||||
@Override
|
||||
protected boolean isUseQuotedIdentifiersGlobally() {
|
||||
@ -161,6 +152,14 @@ public Binder( MetadataImplementor metadata ) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
MetadataImplementor getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
LocalBindingContext getCurrentBindingContext() {
|
||||
return currentBindingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an entity hierarchy.
|
||||
*
|
||||
@ -537,9 +536,9 @@ private void bindDiscriminator(RootEntitySource entitySource, EntityBinding enti
|
||||
entityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator );
|
||||
entityBinding.setDiscriminatorMatchValue( entitySource.getDiscriminatorMatchValue() );
|
||||
|
||||
Type resolvedType = determineHibernateTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() );
|
||||
Type resolvedType = typeHelper.determineHibernateTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() );
|
||||
if ( resolvedType != null ) {
|
||||
pushHibernateTypeInformationDownIfNeeded( resolvedType, relationalValue );
|
||||
typeHelper.pushHibernateTypeInformationDown( resolvedType, relationalValue );
|
||||
}
|
||||
}
|
||||
|
||||
@ -636,7 +635,7 @@ else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) {
|
||||
attributeSource.getReferencedEntityAttributeName(),
|
||||
relationalValueBindings
|
||||
);
|
||||
resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
|
||||
typeHelper.bindSingularAttributeTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
|
||||
resolveToOneInformation(
|
||||
attributeSource,
|
||||
(ManyToOneAttributeBinding) attributeBinding
|
||||
@ -810,7 +809,7 @@ else if ( attributeSource.isVirtualAttribute() ) {
|
||||
metaAttributeContext,
|
||||
attributeSource.getGeneration()
|
||||
);
|
||||
resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
|
||||
typeHelper.bindSingularAttributeTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
|
||||
return attributeBinding;
|
||||
}
|
||||
|
||||
@ -1138,17 +1137,18 @@ private void bindCollectionElement(
|
||||
AbstractPluralAttributeBinding pluralAttributeBinding) {
|
||||
final PluralAttributeElementSource elementSource = attributeSource.getElementSource();
|
||||
if ( elementSource.getNature() == org.hibernate.metamodel.spi.source.PluralAttributeElementNature.BASIC ) {
|
||||
final BasicPluralAttributeElementSource basicElementSource = (BasicPluralAttributeElementSource) elementSource;
|
||||
final BasicPluralAttributeElementBinding basicCollectionElement = (BasicPluralAttributeElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding();
|
||||
resolveTypeInformation(
|
||||
basicElementSource.getExplicitHibernateTypeSource(),
|
||||
pluralAttributeBinding.getAttribute(),
|
||||
basicCollectionElement
|
||||
);
|
||||
final BasicPluralAttributeElementSource basicElementSource =
|
||||
(BasicPluralAttributeElementSource) elementSource;
|
||||
final BasicPluralAttributeElementBinding basicCollectionElement =
|
||||
(BasicPluralAttributeElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding();
|
||||
bindBasicPluralElementRelationalValues(
|
||||
basicElementSource,
|
||||
basicCollectionElement
|
||||
);
|
||||
typeHelper.bindPluralAttributeTypeInformation(
|
||||
attributeSource,
|
||||
pluralAttributeBinding
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1232,350 +1232,6 @@ private EntityBinding getEntityBinding(String entityName) {
|
||||
return binding;
|
||||
}
|
||||
|
||||
private final Properties EMPTY_PROPERTIES = new Properties();
|
||||
|
||||
private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, SingularAttributeBinding attributeBinding) {
|
||||
final Class<?> attributeJavaType = determineJavaType( attributeBinding.getAttribute() );
|
||||
if ( attributeJavaType != null ) {
|
||||
attributeBinding.getAttribute()
|
||||
.resolveType( currentBindingContext.makeJavaType( attributeJavaType.getName() ) );
|
||||
}
|
||||
|
||||
resolveTypeInformation( typeSource, attributeBinding.getHibernateTypeDescriptor(), attributeJavaType );
|
||||
resolveSingularAttributeTypeInformation( attributeBinding );
|
||||
}
|
||||
|
||||
// perform any needed type resolutions for SingularAttributeBinding
|
||||
private void resolveSingularAttributeTypeInformation(SingularAttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we can determine the Hibernate Type if either:
|
||||
// 1) the user explicitly named a Type in a HibernateTypeDescriptor
|
||||
// 2) we know the java type of the attribute
|
||||
Type resolvedType = determineHibernateTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() );
|
||||
if ( resolvedType == null ) {
|
||||
if ( ! attributeBinding.getAttribute().isSingular() ) {
|
||||
throw new AssertionFailure( "SingularAttributeBinding object has a plural attribute: " + attributeBinding.getAttribute().getName() );
|
||||
}
|
||||
final SingularAttribute singularAttribute = attributeBinding.getAttribute();
|
||||
if ( singularAttribute.getSingularAttributeType() != null ) {
|
||||
resolvedType = getHeuristicType(
|
||||
singularAttribute.getSingularAttributeType().getClassName(),
|
||||
EMPTY_PROPERTIES
|
||||
);
|
||||
}
|
||||
} else {
|
||||
attributeBinding.getHibernateTypeDescriptor().setResolvedTypeMapping( resolvedType );
|
||||
pushHibernateTypeInformationDownIfNeeded( attributeBinding, resolvedType );
|
||||
}
|
||||
}
|
||||
|
||||
private Type determineHibernateTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) {
|
||||
return hibernateTypeDescriptor.getResolvedTypeMapping();
|
||||
}
|
||||
String typeName = determineTypeName( hibernateTypeDescriptor );
|
||||
Properties typeParameters = getTypeParameters( hibernateTypeDescriptor );
|
||||
Type type = getHeuristicType( typeName, typeParameters );
|
||||
hibernateTypeDescriptor.setResolvedTypeMapping( type );
|
||||
return type;
|
||||
}
|
||||
|
||||
private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
return hibernateTypeDescriptor.getExplicitTypeName() != null
|
||||
? hibernateTypeDescriptor.getExplicitTypeName()
|
||||
: hibernateTypeDescriptor.getJavaTypeName();
|
||||
}
|
||||
|
||||
private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
Properties typeParameters = new Properties( );
|
||||
if ( hibernateTypeDescriptor.getTypeParameters() != null ) {
|
||||
typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() );
|
||||
}
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
private void resolvePluralAttributeTypeInformation(AbstractPluralAttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) {
|
||||
return;
|
||||
}
|
||||
Type resolvedType;
|
||||
// do NOT look at java type...
|
||||
//String typeName = determineTypeName( attributeBinding.getHibernateTypeDescriptor() );
|
||||
String typeName = attributeBinding.getHibernateTypeDescriptor().getExplicitTypeName();
|
||||
if ( typeName != null ) {
|
||||
resolvedType =
|
||||
metadata.getTypeResolver()
|
||||
.getTypeFactory()
|
||||
.customCollection(
|
||||
typeName,
|
||||
getTypeParameters( attributeBinding.getHibernateTypeDescriptor() ),
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() ==
|
||||
PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
else {
|
||||
resolvedType = determineDefaultCollectionInformation( attributeBinding );
|
||||
}
|
||||
if ( resolvedType != null ) {
|
||||
// todo : what exactly is getting pushed down here? and to what/where?
|
||||
// pushHibernateTypeInformationDownIfNeeded(
|
||||
// attributeBinding.getHibernateTypeDescriptor(),
|
||||
// null,
|
||||
// resolvedType
|
||||
// );
|
||||
}
|
||||
resolveCollectionElementTypeInformation( attributeBinding.getPluralAttributeElementBinding() );
|
||||
}
|
||||
|
||||
private Type determineDefaultCollectionInformation(AbstractPluralAttributeBinding attributeBinding) {
|
||||
final TypeFactory typeFactory = metadata.getTypeResolver().getTypeFactory();
|
||||
switch ( attributeBinding.getAttribute().getNature() ) {
|
||||
case SET: {
|
||||
return typeFactory.set(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
case BAG: {
|
||||
return typeFactory.bag(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding()
|
||||
.getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
default: {
|
||||
throw new UnsupportedOperationException(
|
||||
"Collection type not supported yet:" + attributeBinding.getAttribute().getNature()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveCollectionElementTypeInformation(AbstractPluralAttributeElementBinding pluralAttributeElementBinding) {
|
||||
switch ( pluralAttributeElementBinding.getPluralAttributeElementNature() ) {
|
||||
case BASIC: {
|
||||
resolveBasicCollectionElement( BasicPluralAttributeElementBinding.class.cast(
|
||||
pluralAttributeElementBinding
|
||||
) );
|
||||
break;
|
||||
}
|
||||
case COMPOSITE:
|
||||
case ONE_TO_MANY:
|
||||
case MANY_TO_MANY:
|
||||
case MANY_TO_ANY: {
|
||||
throw new UnsupportedOperationException( "Collection element nature not supported yet: " + pluralAttributeElementBinding
|
||||
.getPluralAttributeElementNature() );
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure( "Unknown collection element nature : " + pluralAttributeElementBinding.getPluralAttributeElementNature() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveBasicCollectionElement(BasicPluralAttributeElementBinding basicCollectionElement) {
|
||||
Type resolvedHibernateType = determineHibernateTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() );
|
||||
if ( resolvedHibernateType != null ) {
|
||||
pushHibernateTypeInformationDownIfNeeded(
|
||||
basicCollectionElement.getHibernateTypeDescriptor(),
|
||||
basicCollectionElement.getRelationalValueBindings(),
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Type getHeuristicType(String typeName, Properties typeParameters) {
|
||||
if ( typeName != null ) {
|
||||
try {
|
||||
return metadata.getTypeResolver().heuristicType( typeName, typeParameters );
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDownIfNeeded(
|
||||
SingularAttributeBinding attributeBinding,
|
||||
Type resolvedHibernateType) {
|
||||
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
|
||||
|
||||
|
||||
// sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
pushHibernateTypeInformationDownIfNeeded(
|
||||
hibernateTypeDescriptor,
|
||||
(BasicAttributeBinding) attributeBinding,
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
else if ( CompositionAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
pushHibernateTypeInformationDownIfNeeded(
|
||||
hibernateTypeDescriptor,
|
||||
(CompositionAttributeBinding) attributeBinding
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDownIfNeeded(
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
CompositionAttributeBinding attributeBinding) {
|
||||
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
|
||||
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
|
||||
singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
|
||||
}
|
||||
|
||||
for ( AttributeBinding subAttributeBinding : attributeBinding.attributeBindings() ) {
|
||||
if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) {
|
||||
resolveSingularAttributeTypeInformation(
|
||||
SingularAttributeBinding.class.cast( subAttributeBinding )
|
||||
);
|
||||
}
|
||||
else if ( AbstractPluralAttributeBinding.class.isInstance( subAttributeBinding ) ) {
|
||||
resolvePluralAttributeTypeInformation(
|
||||
AbstractPluralAttributeBinding.class.cast( subAttributeBinding )
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDownIfNeeded(
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
BasicAttributeBinding attributeBinding,
|
||||
Type resolvedHibernateType) {
|
||||
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
|
||||
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
|
||||
singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
|
||||
}
|
||||
pushHibernateTypeInformationDownIfNeeded(
|
||||
hibernateTypeDescriptor,
|
||||
attributeBinding.getRelationalValueBindings(),
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDownIfNeeded(
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
Type resolvedHibernateType) {
|
||||
if ( resolvedHibernateType == null ) {
|
||||
return;
|
||||
}
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) {
|
||||
hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType );
|
||||
}
|
||||
|
||||
// java type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
|
||||
hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() );
|
||||
}
|
||||
|
||||
// todo : this can be made a lot smarter, but for now this will suffice. currently we only handle single value bindings
|
||||
|
||||
if ( relationalValueBindings.size() > 1 ) {
|
||||
return;
|
||||
}
|
||||
final Value value = relationalValueBindings.get( 0 ).getValue();
|
||||
pushHibernateTypeInformationDownIfNeeded( resolvedHibernateType, value );
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDownIfNeeded(Type resolvedHibernateType, Value value) {
|
||||
if ( value.getJdbcDataType() == null ) {
|
||||
if ( AbstractValue.class.isInstance( value ) ) {
|
||||
( (AbstractValue) value ).setJdbcDataType(
|
||||
new JdbcDataType(
|
||||
resolvedHibernateType.sqlTypes( metadata )[0],
|
||||
resolvedHibernateType.getName(),
|
||||
resolvedHibernateType.getReturnedClass()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveTypeInformation(
|
||||
ExplicitHibernateTypeSource typeSource,
|
||||
PluralAttribute attribute,
|
||||
BasicPluralAttributeElementBinding collectionElement) {
|
||||
final Class<?> attributeJavaType = determineJavaType( attribute );
|
||||
resolveTypeInformation( typeSource, collectionElement.getHibernateTypeDescriptor(), attributeJavaType );
|
||||
}
|
||||
|
||||
private void resolveTypeInformation(
|
||||
ExplicitHibernateTypeSource typeSource,
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
Class<?> discoveredJavaType) {
|
||||
if ( discoveredJavaType != null ) {
|
||||
hibernateTypeDescriptor.setJavaTypeName( discoveredJavaType.getName() );
|
||||
}
|
||||
|
||||
final String explicitTypeName = typeSource.getName();
|
||||
if ( explicitTypeName != null ) {
|
||||
final TypeDefinition typeDefinition = currentBindingContext.getMetadataImplementor()
|
||||
.getTypeDefinition( explicitTypeName );
|
||||
if ( typeDefinition != null ) {
|
||||
hibernateTypeDescriptor.setExplicitTypeName( typeDefinition.getTypeImplementorClass().getName() );
|
||||
hibernateTypeDescriptor.getTypeParameters().putAll( typeDefinition.getParameters() );
|
||||
}
|
||||
else {
|
||||
hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName );
|
||||
}
|
||||
final Map<String, String> parameters = typeSource.getParameters();
|
||||
if ( parameters != null ) {
|
||||
hibernateTypeDescriptor.getTypeParameters().putAll( parameters );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( discoveredJavaType == null ) {
|
||||
// we will have problems later determining the Hibernate Type to use. Should we throw an
|
||||
// exception now? Might be better to get better contextual info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attribute the domain attribute
|
||||
*
|
||||
* @return Returns the Java type of the attribute using reflection or {@code null} if the type cannot be discovered
|
||||
*/
|
||||
private Class<?> determineJavaType(final SingularAttribute attribute) {
|
||||
try {
|
||||
final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference();
|
||||
return ReflectHelper.reflectedPropertyClass( ownerClass, attribute.getName() );
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
// todo : log it?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Class<?> determineJavaType(PluralAttribute attribute) {
|
||||
try {
|
||||
final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference();
|
||||
PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate(
|
||||
ownerClass,
|
||||
attribute.getName()
|
||||
);
|
||||
BeanInfoHelper.visitBeanInfo( ownerClass, delegate );
|
||||
return delegate.javaType;
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
// todo : log it?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void resolveToOneInformation(ToOneAttributeSource attributeSource, ManyToOneAttributeBinding attributeBinding) {
|
||||
final String referencedEntityName = attributeSource.getReferencedEntityName() != null
|
||||
? attributeSource.getReferencedEntityName()
|
||||
@ -1827,55 +1483,4 @@ private void processFetchProfiles(EntitySource entitySource, EntityBinding entit
|
||||
// todo : process the entity-local fetch-profile declaration
|
||||
}
|
||||
|
||||
private class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate {
|
||||
private final Class<?> ownerClass;
|
||||
private final String attributeName;
|
||||
private Class<?> javaType = null;
|
||||
|
||||
private PluralAttributeJavaTypeDeterminerDelegate(Class<?> ownerClass, String attributeName) {
|
||||
this.ownerClass = ownerClass;
|
||||
this.attributeName = attributeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBeanInfo(BeanInfo beanInfo) throws Exception {
|
||||
java.lang.reflect.Type collectionAttributeType = null;
|
||||
if ( beanInfo.getPropertyDescriptors() == null || beanInfo.getPropertyDescriptors().length == 0 ) {
|
||||
// we need to look for the field and look at it...
|
||||
collectionAttributeType = ownerClass.getField( attributeName ).getGenericType();
|
||||
}
|
||||
else {
|
||||
for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) {
|
||||
if ( propertyDescriptor.getName().equals( attributeName ) ) {
|
||||
if ( propertyDescriptor.getReadMethod() != null ) {
|
||||
collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType();
|
||||
}
|
||||
else if ( propertyDescriptor.getWriteMethod() != null ) {
|
||||
collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( collectionAttributeType != null ) {
|
||||
if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) {
|
||||
final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments();
|
||||
if ( types == null ) {
|
||||
return;
|
||||
}
|
||||
else if ( types.length == 1 ) {
|
||||
javaType = (Class<?>) types[0];
|
||||
}
|
||||
else if ( types.length == 2 ) {
|
||||
// Map<K,V>
|
||||
javaType = (Class<?>) types[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
javaType = (Class<?>) collectionAttributeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,569 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositionAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementNature;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.TypeDefinition;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttribute;
|
||||
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.ExplicitHibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
|
||||
/**
|
||||
* Serves 2 roles:<ol>
|
||||
* <li>
|
||||
* Takes information about an attribute mapping and determines the appropriate Hibernate
|
||||
* {@link org.hibernate.type.Type} to use, if possible.
|
||||
* </li>
|
||||
* <li>
|
||||
* Given a Hibernate {@link org.hibernate.type.Type}, it pushes the jdbc and java type information
|
||||
* reported the {@link org.hibernate.type.Type} into parts of the metamodel that may be missing it
|
||||
* </li>
|
||||
* </ol>
|
||||
* <p/>
|
||||
* Methods intended as entry points are:<ul>
|
||||
* <li>{@link #bindSingularAttributeTypeInformation}</li>
|
||||
* <li>{@link #bindPluralAttributeTypeInformation}</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* Currently the following methods are also required to be non-private because of handling discriminators which
|
||||
* are currently not modeled using attributes:<ul>
|
||||
* <li>{@link #determineHibernateTypeFromDescriptor}</li>
|
||||
* <li>{@link #pushHibernateTypeInformationDown(org.hibernate.type.Type, org.hibernate.metamodel.spi.relational.Value)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class HibernateTypeHelper {
|
||||
private static final Logger log = Logger.getLogger( HibernateTypeHelper.class );
|
||||
|
||||
private final Binder binder;
|
||||
|
||||
public HibernateTypeHelper(Binder binder) {
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
private org.hibernate.metamodel.spi.domain.Type makeJavaType(String name) {
|
||||
return binder.getCurrentBindingContext().makeJavaType( name );
|
||||
}
|
||||
|
||||
private MetadataImplementor metadata() {
|
||||
return binder.getMetadata();
|
||||
}
|
||||
|
||||
public void bindSingularAttributeTypeInformation(
|
||||
ExplicitHibernateTypeSource typeSource,
|
||||
SingularAttributeBinding attributeBinding) {
|
||||
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
|
||||
|
||||
final Class<?> attributeJavaType = determineJavaType( attributeBinding.getAttribute() );
|
||||
if ( attributeJavaType != null ) {
|
||||
attributeBinding.getAttribute().resolveType( makeJavaType( attributeJavaType.getName() ) );
|
||||
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
|
||||
hibernateTypeDescriptor.setJavaTypeName( attributeJavaType.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
bindHibernateTypeInformation( typeSource, hibernateTypeDescriptor );
|
||||
|
||||
processSingularAttributeTypeInformation( attributeBinding );
|
||||
}
|
||||
|
||||
public void bindPluralAttributeTypeInformation(
|
||||
PluralAttributeSource attributeSource,
|
||||
PluralAttributeBinding attributeBinding) {
|
||||
final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes = determineJavaType( attributeBinding.getAttribute() );
|
||||
|
||||
if ( reflectedCollectionJavaTypes != null ) {
|
||||
if ( reflectedCollectionJavaTypes.collectionType != null ) {
|
||||
if ( attributeBinding.getHibernateTypeDescriptor().getJavaTypeName() == null ) {
|
||||
attributeBinding.getHibernateTypeDescriptor().setJavaTypeName(
|
||||
reflectedCollectionJavaTypes.collectionType.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( reflectedCollectionJavaTypes.collectionElementType != null ) {
|
||||
if ( attributeBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeName() == null ) {
|
||||
attributeBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().setJavaTypeName(
|
||||
reflectedCollectionJavaTypes.collectionElementType.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( reflectedCollectionJavaTypes.collectionIndexType != null
|
||||
&& IndexedPluralAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
final PluralAttributeIndexBinding indexBinding
|
||||
= ( (IndexedPluralAttributeBinding) attributeBinding ).getPluralAttributeIndexBinding();
|
||||
if ( indexBinding.getHibernateTypeDescriptor().getJavaTypeName() == null ) {
|
||||
indexBinding.getHibernateTypeDescriptor().setJavaTypeName(
|
||||
reflectedCollectionJavaTypes.collectionIndexType.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//todo : we need to support type descriptors at multiple levels
|
||||
bindHibernateTypeInformation( attributeSource.getTypeInformation(), attributeBinding.getHibernateTypeDescriptor() );
|
||||
processPluralAttributeTypeInformation( attributeBinding );
|
||||
}
|
||||
|
||||
private Class<?> determineJavaType(final SingularAttribute attribute) {
|
||||
try {
|
||||
final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference();
|
||||
return ReflectHelper.reflectedPropertyClass( ownerClass, attribute.getName() );
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
log.debugf(
|
||||
"Unable to locate attribute [%s] on class [%s]",
|
||||
attribute.getName(),
|
||||
attribute.getAttributeContainer().getClassName()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ReflectedCollectionJavaTypes determineJavaType(PluralAttribute attribute) {
|
||||
try {
|
||||
final Class<?> ownerClass = attribute.getAttributeContainer().getClassReference();
|
||||
PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate(
|
||||
ownerClass,
|
||||
attribute.getName()
|
||||
);
|
||||
BeanInfoHelper.visitBeanInfo( ownerClass, delegate );
|
||||
return delegate.collectionJavaTypes;
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
log.debugf(
|
||||
"Unable to locate attribute [%s] on class [%s]",
|
||||
attribute.getName(),
|
||||
attribute.getAttributeContainer().getClassName()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes explicit source type information and applies it to the binding model.
|
||||
*
|
||||
* @param typeSource The source (user supplied) hibernate type information
|
||||
* @param hibernateTypeDescriptor The binding model hibernate type information
|
||||
*/
|
||||
private void bindHibernateTypeInformation(
|
||||
ExplicitHibernateTypeSource typeSource,
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
final String explicitTypeName = typeSource.getName();
|
||||
if ( explicitTypeName != null ) {
|
||||
final TypeDefinition typeDefinition = metadata().getTypeDefinition( explicitTypeName );
|
||||
if ( typeDefinition != null ) {
|
||||
hibernateTypeDescriptor.setExplicitTypeName( typeDefinition.getTypeImplementorClass().getName() );
|
||||
hibernateTypeDescriptor.getTypeParameters().putAll( typeDefinition.getParameters() );
|
||||
}
|
||||
else {
|
||||
hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName );
|
||||
}
|
||||
final Map<String, String> parameters = typeSource.getParameters();
|
||||
if ( parameters != null ) {
|
||||
hibernateTypeDescriptor.getTypeParameters().putAll( parameters );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an attribute, process all of its type information. This includes resolving the actual
|
||||
* {@link Type} instance and pushing JDBC/java information from that type down.
|
||||
*
|
||||
* @param attributeBinding The attribute.
|
||||
*/
|
||||
private void processSingularAttributeTypeInformation(SingularAttributeBinding attributeBinding) {
|
||||
Type resolvedType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
|
||||
if ( resolvedType == null ) {
|
||||
// we can determine the Hibernate Type if either:
|
||||
// 1) the user explicitly named a Type in a HibernateTypeDescriptor
|
||||
// 2) we know the java type of the attribute
|
||||
resolvedType = determineHibernateTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() );
|
||||
if ( resolvedType == null ) {
|
||||
resolvedType = determineHibernateTypeFromAttributeJavaType( attributeBinding.getAttribute() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( resolvedType != null ) {
|
||||
pushHibernateTypeInformationDown( attributeBinding, resolvedType );
|
||||
}
|
||||
}
|
||||
|
||||
public Type determineHibernateTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) {
|
||||
return hibernateTypeDescriptor.getResolvedTypeMapping();
|
||||
}
|
||||
String typeName = determineTypeName( hibernateTypeDescriptor );
|
||||
Properties typeParameters = getTypeParameters( hibernateTypeDescriptor );
|
||||
Type type = getHeuristicType( typeName, typeParameters );
|
||||
hibernateTypeDescriptor.setResolvedTypeMapping( type );
|
||||
return type;
|
||||
}
|
||||
|
||||
private Type getHeuristicType(String typeName, Properties typeParameters) {
|
||||
if ( typeName != null ) {
|
||||
try {
|
||||
return metadata().getTypeResolver().heuristicType( typeName, typeParameters );
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private final Properties EMPTY_PROPERTIES = new Properties();
|
||||
|
||||
private Type determineHibernateTypeFromAttributeJavaType(SingularAttribute singularAttribute) {
|
||||
if ( singularAttribute.getSingularAttributeType() != null ) {
|
||||
return getHeuristicType(
|
||||
singularAttribute.getSingularAttributeType().getClassName(),
|
||||
EMPTY_PROPERTIES
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
return hibernateTypeDescriptor.getExplicitTypeName() != null
|
||||
? hibernateTypeDescriptor.getExplicitTypeName()
|
||||
: hibernateTypeDescriptor.getJavaTypeName();
|
||||
}
|
||||
|
||||
private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
Properties typeParameters = new Properties( );
|
||||
if ( hibernateTypeDescriptor.getTypeParameters() != null ) {
|
||||
typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() );
|
||||
}
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDown(
|
||||
SingularAttributeBinding attributeBinding,
|
||||
Type resolvedHibernateType) {
|
||||
|
||||
// sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
pushHibernateTypeInformationDown(
|
||||
(BasicAttributeBinding) attributeBinding,
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
else if ( CompositionAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
pushHibernateTypeInformationDown(
|
||||
(CompositionAttributeBinding) attributeBinding,
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDown(
|
||||
BasicAttributeBinding attributeBinding,
|
||||
Type resolvedHibernateType) {
|
||||
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
|
||||
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
|
||||
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
|
||||
singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
|
||||
}
|
||||
pushHibernateTypeInformationDown(
|
||||
hibernateTypeDescriptor,
|
||||
attributeBinding.getRelationalValueBindings(),
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"UnusedParameters"})
|
||||
private void pushHibernateTypeInformationDown(
|
||||
CompositionAttributeBinding attributeBinding,
|
||||
Type resolvedHibernateType) {
|
||||
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
|
||||
final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
|
||||
if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
|
||||
singularAttribute.resolveType( makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
|
||||
}
|
||||
|
||||
for ( AttributeBinding subAttributeBinding : attributeBinding.attributeBindings() ) {
|
||||
if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) {
|
||||
processSingularAttributeTypeInformation(
|
||||
SingularAttributeBinding.class.cast( subAttributeBinding )
|
||||
);
|
||||
}
|
||||
else if ( AbstractPluralAttributeBinding.class.isInstance( subAttributeBinding ) ) {
|
||||
processPluralAttributeTypeInformation(
|
||||
AbstractPluralAttributeBinding.class.cast( subAttributeBinding )
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pushHibernateTypeInformationDown(
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
Type resolvedHibernateType) {
|
||||
if ( resolvedHibernateType == null ) {
|
||||
return;
|
||||
}
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) {
|
||||
hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType );
|
||||
}
|
||||
|
||||
// java type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if ( hibernateTypeDescriptor.getJavaTypeName() == null ) {
|
||||
hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() );
|
||||
}
|
||||
|
||||
// todo : this can be made a lot smarter, but for now this will suffice. currently we only handle single value bindings
|
||||
|
||||
if ( relationalValueBindings.size() > 1 ) {
|
||||
return;
|
||||
}
|
||||
final Value value = relationalValueBindings.get( 0 ).getValue();
|
||||
pushHibernateTypeInformationDown( resolvedHibernateType, value );
|
||||
}
|
||||
|
||||
public void pushHibernateTypeInformationDown(Type resolvedHibernateType, Value value) {
|
||||
if ( value.getJdbcDataType() == null ) {
|
||||
if ( AbstractValue.class.isInstance( value ) ) {
|
||||
( (AbstractValue) value ).setJdbcDataType(
|
||||
new JdbcDataType(
|
||||
resolvedHibernateType.sqlTypes( metadata() )[0],
|
||||
resolvedHibernateType.getName(),
|
||||
resolvedHibernateType.getReturnedClass()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processPluralAttributeTypeInformation(PluralAttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Type resolvedType;
|
||||
// do NOT look at java type...
|
||||
//String typeName = determineTypeName( attributeBinding.getHibernateTypeDescriptor() );
|
||||
String typeName = attributeBinding.getHibernateTypeDescriptor().getExplicitTypeName();
|
||||
if ( typeName != null ) {
|
||||
resolvedType =
|
||||
metadata().getTypeResolver()
|
||||
.getTypeFactory()
|
||||
.customCollection(
|
||||
typeName,
|
||||
getTypeParameters( attributeBinding.getHibernateTypeDescriptor() ),
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() ==
|
||||
PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
else {
|
||||
resolvedType = determineHibernateTypeFromCollectionType( attributeBinding );
|
||||
}
|
||||
if ( resolvedType != null ) {
|
||||
// todo : what exactly is getting pushed down here? and to what/where?
|
||||
// pushHibernateTypeInformationDownIfNeeded(
|
||||
// attributeBinding.getHibernateTypeDescriptor(),
|
||||
// null,
|
||||
// resolvedType
|
||||
// );
|
||||
}
|
||||
bindCollectionElementTypeInformation( attributeBinding.getPluralAttributeElementBinding() );
|
||||
}
|
||||
|
||||
private Type determineHibernateTypeFromCollectionType(PluralAttributeBinding attributeBinding) {
|
||||
final TypeFactory typeFactory = metadata().getTypeResolver().getTypeFactory();
|
||||
switch ( attributeBinding.getAttribute().getNature() ) {
|
||||
case SET: {
|
||||
return typeFactory.set(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
case BAG: {
|
||||
return typeFactory.bag(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeBinding.getReferencedPropertyName(),
|
||||
attributeBinding.getPluralAttributeElementBinding()
|
||||
.getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE
|
||||
);
|
||||
}
|
||||
default: {
|
||||
throw new UnsupportedOperationException(
|
||||
"Collection type not supported yet:" + attributeBinding.getAttribute().getNature()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindCollectionElementTypeInformation(PluralAttributeElementBinding pluralAttributeElementBinding) {
|
||||
switch ( pluralAttributeElementBinding.getPluralAttributeElementNature() ) {
|
||||
case BASIC: {
|
||||
bindBasicCollectionElementTypeInformation(
|
||||
BasicPluralAttributeElementBinding.class.cast(
|
||||
pluralAttributeElementBinding
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case COMPOSITE:
|
||||
case ONE_TO_MANY:
|
||||
case MANY_TO_MANY:
|
||||
case MANY_TO_ANY: {
|
||||
throw new UnsupportedOperationException( "Collection element nature not supported yet: " + pluralAttributeElementBinding
|
||||
.getPluralAttributeElementNature() );
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure( "Unknown collection element nature : " + pluralAttributeElementBinding.getPluralAttributeElementNature() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindBasicCollectionElementTypeInformation(BasicPluralAttributeElementBinding basicCollectionElement) {
|
||||
Type resolvedHibernateType = determineHibernateTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() );
|
||||
if ( resolvedHibernateType != null ) {
|
||||
pushHibernateTypeInformationDown(
|
||||
basicCollectionElement.getHibernateTypeDescriptor(),
|
||||
basicCollectionElement.getRelationalValueBindings(),
|
||||
resolvedHibernateType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HibernateTypeHelper#determineJavaType(PluralAttribute)
|
||||
*/
|
||||
private class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate {
|
||||
private final Class<?> ownerClass;
|
||||
private final String attributeName;
|
||||
|
||||
private ReflectedCollectionJavaTypes collectionJavaTypes;
|
||||
|
||||
private PluralAttributeJavaTypeDeterminerDelegate(Class<?> ownerClass, String attributeName) {
|
||||
this.ownerClass = ownerClass;
|
||||
this.attributeName = attributeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBeanInfo(BeanInfo beanInfo) throws Exception {
|
||||
Class<?> collectionType = null;
|
||||
Class<?> elementJavaType = null;
|
||||
Class<?> indexJavaType = null;
|
||||
|
||||
java.lang.reflect.Type collectionAttributeType = null;
|
||||
if ( beanInfo.getPropertyDescriptors() == null || beanInfo.getPropertyDescriptors().length == 0 ) {
|
||||
// we need to look for the field and look at it...
|
||||
collectionAttributeType = ownerClass.getField( attributeName ).getGenericType();
|
||||
}
|
||||
else {
|
||||
for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) {
|
||||
if ( propertyDescriptor.getName().equals( attributeName ) ) {
|
||||
if ( propertyDescriptor.getReadMethod() != null ) {
|
||||
collectionType = propertyDescriptor.getReadMethod().getReturnType();
|
||||
collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType();
|
||||
}
|
||||
else if ( propertyDescriptor.getWriteMethod() != null ) {
|
||||
collectionType = propertyDescriptor.getWriteMethod().getParameterTypes()[0];
|
||||
collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( collectionAttributeType != null ) {
|
||||
if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) {
|
||||
final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments();
|
||||
if ( types == null ) {
|
||||
}
|
||||
else if ( types.length == 1 ) {
|
||||
elementJavaType = (Class<?>) types[0];
|
||||
}
|
||||
else if ( types.length == 2 ) {
|
||||
// Map<K,V>
|
||||
indexJavaType = (Class<?>) types[0];
|
||||
elementJavaType = (Class<?>) types[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
collectionJavaTypes = new ReflectedCollectionJavaTypes( collectionType, elementJavaType, indexJavaType );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -289,6 +289,7 @@ public void setBatchSize(int batchSize) {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getReferencedPropertyName() {
|
||||
return referencedPropertyName;
|
||||
}
|
||||
|
@ -86,4 +86,6 @@ public interface PluralAttributeBinding extends AttributeBinding, Fetchable {
|
||||
java.util.Map getFilterMap();
|
||||
|
||||
String getOrderBy();
|
||||
|
||||
String getReferencedPropertyName();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user