Package org.hibernate.metamodel.source.internal

Source Code of org.hibernate.metamodel.source.internal.HibernateTypeResolver

/*
* 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.source.internal;

import java.util.Properties;

import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.binding.AbstractCollectionElement;
import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.BasicCollectionElement;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.EntityDiscriminator;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.SingularAttributeBinding;
import org.hibernate.metamodel.domain.SingularAttribute;
import org.hibernate.metamodel.relational.Datatype;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.Value;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;

/**
* This is a TEMPORARY way to initialize Hibernate types.
* This class will be removed when types are resolved properly.
*
* @author Gail Badner
*/
class HibernateTypeResolver {

  private final MetadataImplementor metadata;

  HibernateTypeResolver(MetadataImplementor metadata) {
    this.metadata = metadata;
  }

  void resolve() {
    for ( EntityBinding entityBinding : metadata.getEntityBindings() ) {
      if ( entityBinding.getHierarchyDetails().getEntityDiscriminator() != null ) {
        resolveDiscriminatorTypeInformation( entityBinding.getHierarchyDetails().getEntityDiscriminator() );
      }
      for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) {
        if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
          resolveSingularAttributeTypeInformation(
              SingularAttributeBinding.class.cast( attributeBinding  )
          );
        }
        else if ( AbstractPluralAttributeBinding.class.isInstance( attributeBinding ) ) {
          resolvePluralAttributeTypeInformation(
              AbstractPluralAttributeBinding.class.cast( attributeBinding )
          );
        }
        else {
          throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() );
        }
      }
    }
  }

  // perform any needed type resolutions for discriminator
  private void resolveDiscriminatorTypeInformation(EntityDiscriminator discriminator) {
    // perform any needed type resolutions for discriminator
    Type resolvedHibernateType = determineSingularTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() );
    if ( resolvedHibernateType != null ) {
      pushHibernateTypeInformationDownIfNeeded(
          discriminator.getExplicitHibernateTypeDescriptor(),
          discriminator.getBoundValue(),
          resolvedHibernateType
      );
    }
  }

  private Type determineSingularTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) {
    if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) {
      return hibernateTypeDescriptor.getResolvedTypeMapping();
    }
    String typeName = determineTypeName( hibernateTypeDescriptor );
    Properties typeParameters = getTypeParameters( hibernateTypeDescriptor );
    return getHeuristicType( typeName, typeParameters );
  }

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

  // 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;
    resolvedType = determineSingularTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() );
    if ( resolvedType == null ) {
      if ( ! attributeBinding.getAttribute().isSingular() ) {
        throw new AssertionFailure( "SingularAttributeBinding object has a plural attribute: " + attributeBinding.getAttribute().getName() );
      }
      final SingularAttribute singularAttribute = ( SingularAttribute ) attributeBinding.getAttribute();
      if ( singularAttribute.getSingularAttributeType() != null ) {
        resolvedType = getHeuristicType(
            singularAttribute.getSingularAttributeType().getClassName(), new Properties()
        );
      }
    }
    if ( resolvedType != null ) {
      pushHibernateTypeInformationDownIfNeeded( attributeBinding, resolvedType );
    }
  }

  // perform any needed type resolutions for PluralAttributeBinding
  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()
              );
    }
    else {
      resolvedType = determineDefaultCollectionInformation( attributeBinding );
    }
    if ( resolvedType != null ) {
      pushHibernateTypeInformationDownIfNeeded(
          attributeBinding.getHibernateTypeDescriptor(),
          null,
          resolvedType );
    }
    resolveCollectionElementTypeInformation( attributeBinding.getCollectionElement() );
  }

  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()
        );
      }
      case BAG: {
        return typeFactory.bag(
            attributeBinding.getAttribute().getName(),
            attributeBinding.getReferencedPropertyName()
        );
      }
      default: {
        throw new UnsupportedOperationException(
            "Collection type not supported yet:" + attributeBinding.getAttribute().getNature()
        );
      }
    }
  }

  private void resolveCollectionElementTypeInformation(AbstractCollectionElement collectionElement) {
    switch ( collectionElement.getCollectionElementNature() ) {
      case BASIC: {
        resolveBasicCollectionElement( BasicCollectionElement.class.cast( collectionElement ) );
        break;
      }
      case COMPOSITE:
      case ONE_TO_MANY:
      case MANY_TO_MANY:
      case MANY_TO_ANY: {
        throw new UnsupportedOperationException( "Collection element nature not supported yet: " + collectionElement.getCollectionElementNature() );
      }
      default: {
        throw new AssertionFailure( "Unknown collection element nature : " + collectionElement.getCollectionElementNature() );
      }
    }
  }

  private void resolveBasicCollectionElement(BasicCollectionElement basicCollectionElement) {
    Type resolvedHibernateType = determineSingularTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() );
    if ( resolvedHibernateType != null ) {
      pushHibernateTypeInformationDownIfNeeded(
          basicCollectionElement.getHibernateTypeDescriptor(),
          basicCollectionElement.getElementValue(),
          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();
    final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() );
    final Value value = attributeBinding.getValue();
    if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) {
      singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) );
    }

    // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    this.pushHibernateTypeInformationDownIfNeeded(
        hibernateTypeDescriptor, value, resolvedHibernateType
    );
  }

  private void pushHibernateTypeInformationDownIfNeeded(
      HibernateTypeDescriptor hibernateTypeDescriptor,
      Value value,
      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 ( SimpleValue.class.isInstance( value ) ) {
       SimpleValue simpleValue = ( SimpleValue ) value;
       if ( simpleValue.getDatatype() == null ) {
         simpleValue.setDatatype(
             new Datatype(
                 resolvedHibernateType.sqlTypes( metadata )[0],
                 resolvedHibernateType.getName(),
                 resolvedHibernateType.getReturnedClass()
             )
         );
       }
     }
  }
}
TOP

Related Classes of org.hibernate.metamodel.source.internal.HibernateTypeResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.