Package org.hibernate.metamodel.source.binder

Source Code of org.hibernate.metamodel.source.binder.Binder

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

import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.beans.BeanInfoHelper;
import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.CollectionElementNature;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.InheritanceType;
import org.hibernate.metamodel.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.binding.MetaAttribute;
import org.hibernate.metamodel.binding.SimpleSingularAttributeBinding;
import org.hibernate.metamodel.binding.SimpleValueBinding;
import org.hibernate.metamodel.binding.SingularAttributeBinding;
import org.hibernate.metamodel.binding.TypeDef;
import org.hibernate.metamodel.domain.Attribute;
import org.hibernate.metamodel.domain.Entity;
import org.hibernate.metamodel.domain.PluralAttribute;
import org.hibernate.metamodel.domain.SingularAttribute;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.Identifier;
import org.hibernate.metamodel.relational.Schema;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.metamodel.relational.Tuple;
import org.hibernate.metamodel.source.LocalBindingContext;
import org.hibernate.metamodel.source.MetaAttributeContext;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.metamodel.source.hbm.Helper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.entity.EntityTuplizer;

/**
* The common binder shared between annotations and {@code hbm.xml} processing.
* <p/>
* The API consists of {@link #Binder} and {@link #processEntityHierarchy}
*
* @author Steve Ebersole
*/
public class Binder {
  private final MetadataImplementor metadata;
  private final List<String> processedEntityNames;

  private InheritanceType currentInheritanceType;
  private EntityMode currentHierarchyEntityMode;
  private LocalBindingContext currentBindingContext;

  public Binder(MetadataImplementor metadata, List<String> processedEntityNames) {
    this.metadata = metadata;
    this.processedEntityNames = processedEntityNames;
  }

  /**
   * Process an entity hierarchy.
   *
   * @param entityHierarchy THe hierarchy to process.
   */
  public void processEntityHierarchy(EntityHierarchy entityHierarchy) {
    currentInheritanceType = entityHierarchy.getHierarchyInheritanceType();
    EntityBinding rootEntityBinding = createEntityBinding( entityHierarchy.getRootEntitySource(), null );
    if ( currentInheritanceType != InheritanceType.NO_INHERITANCE ) {
      processHierarchySubEntities( entityHierarchy.getRootEntitySource(), rootEntityBinding );
    }
    currentHierarchyEntityMode = null;
  }

  private void processHierarchySubEntities(SubclassEntityContainer subclassEntitySource, EntityBinding superEntityBinding) {
    for ( SubclassEntitySource subEntity : subclassEntitySource.subclassEntitySources() ) {
      EntityBinding entityBinding = createEntityBinding( subEntity, superEntityBinding );
      processHierarchySubEntities( subEntity, entityBinding );
    }
  }


  // Entities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  private EntityBinding createEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) {
    if ( processedEntityNames.contains( entitySource.getEntityName() ) ) {
      return metadata.getEntityBinding( entitySource.getEntityName() );
    }

    currentBindingContext = entitySource.getBindingContext();
    try {
      final EntityBinding entityBinding = doCreateEntityBinding( entitySource, superEntityBinding );

      metadata.addEntity( entityBinding );
      processedEntityNames.add( entityBinding.getEntity().getName() );

      processFetchProfiles( entitySource, entityBinding );

      return entityBinding;
    }
    finally {
      currentBindingContext = null;
    }
  }

  private EntityBinding doCreateEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) {
    final EntityBinding entityBinding = createBasicEntityBinding( entitySource, superEntityBinding );

    bindSecondaryTables( entitySource, entityBinding );
    bindAttributes( entitySource, entityBinding );

    bindTableUniqueConstraints( entitySource, entityBinding );

    return entityBinding;
  }

  private EntityBinding createBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) {
    if ( superEntityBinding == null ) {
      return makeRootEntityBinding( (RootEntitySource) entitySource );
    }
    else {
      if ( currentInheritanceType == InheritanceType.SINGLE_TABLE ) {
        return makeDiscriminatedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding );
      }
      else if ( currentInheritanceType == InheritanceType.JOINED ) {
        return makeJoinedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding );
      }
      else if ( currentInheritanceType == InheritanceType.TABLE_PER_CLASS ) {
        return makeUnionedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding );
      }
      else {
        // extreme internal error!
        throw new AssertionFailure( "Internal condition failure" );
      }
    }
  }

  private EntityBinding makeRootEntityBinding(RootEntitySource entitySource) {
    currentHierarchyEntityMode = entitySource.getEntityMode();

    final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, null );

    bindPrimaryTable( entitySource, entityBinding );

    bindIdentifier( entitySource, entityBinding );
    bindVersion( entityBinding, entitySource );
    bindDiscriminator( entitySource, entityBinding );

    entityBinding.setMutable( entitySource.isMutable() );
    entityBinding.setExplicitPolymorphism( entitySource.isExplicitPolymorphism() );
    entityBinding.setWhereFilter( entitySource.getWhere() );
    entityBinding.setRowId( entitySource.getRowId() );
    entityBinding.setOptimisticLockStyle( entitySource.getOptimisticLockStyle() );
    entityBinding.setCaching( entitySource.getCaching() );

    return entityBinding;
  }


  private EntityBinding buildBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) {
    final EntityBinding entityBinding = new EntityBinding();
    entityBinding.setSuperEntityBinding( superEntityBinding );
    entityBinding.setInheritanceType( currentInheritanceType );

    entityBinding.setEntityMode( currentHierarchyEntityMode );

    final String entityName = entitySource.getEntityName();
    final String className = currentHierarchyEntityMode == EntityMode.POJO ? entitySource.getClassName() : null;

    final Entity entity = new Entity(
        entityName,
        className,
        currentBindingContext.makeClassReference( className ),
        null
    );
    entityBinding.setEntity( entity );

    entityBinding.setJpaEntityName( entitySource.getJpaEntityName() );

    if ( entityBinding.getEntityMode() == EntityMode.POJO ) {
      final String proxy = entitySource.getProxy();
      if ( proxy != null ) {
        entityBinding.setProxyInterfaceType(
            currentBindingContext.makeClassReference(
                currentBindingContext.qualifyClassName( proxy )
            )
        );
        entityBinding.setLazy( true );
      }
      else if ( entitySource.isLazy() ) {
        entityBinding.setProxyInterfaceType( entityBinding.getEntity().getClassReferenceUnresolved() );
        entityBinding.setLazy( true );
      }
    }
    else {
      entityBinding.setProxyInterfaceType( null );
      entityBinding.setLazy( entitySource.isLazy() );
    }

    final String customTuplizerClassName = entitySource.getCustomTuplizerClassName();
    if ( customTuplizerClassName != null ) {
      entityBinding.setCustomEntityTuplizerClass( currentBindingContext.<EntityTuplizer>locateClassByName( customTuplizerClassName ) );
    }

    final String customPersisterClassName = entitySource.getCustomPersisterClassName();
    if ( customPersisterClassName != null ) {
      entityBinding.setCustomEntityPersisterClass( currentBindingContext.<EntityPersister>locateClassByName( customPersisterClassName ) );
    }

    entityBinding.setMetaAttributeContext( buildMetaAttributeContext( entitySource ) );

    entityBinding.setDynamicUpdate( entitySource.isDynamicUpdate() );
    entityBinding.setDynamicInsert( entitySource.isDynamicInsert() );
    entityBinding.setBatchSize( entitySource.getBatchSize() );
    entityBinding.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() );
    entityBinding.setAbstract( entitySource.isAbstract() );

    entityBinding.setCustomLoaderName( entitySource.getCustomLoaderName() );
    entityBinding.setCustomInsert( entitySource.getCustomSqlInsert() );
    entityBinding.setCustomUpdate( entitySource.getCustomSqlUpdate() );
    entityBinding.setCustomDelete( entitySource.getCustomSqlDelete() );

    if ( entitySource.getSynchronizedTableNames() != null ) {
      entityBinding.addSynchronizedTableNames( entitySource.getSynchronizedTableNames() );
    }

    return entityBinding;
  }

  private EntityBinding makeDiscriminatedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) {
    final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding );

    entityBinding.setBaseTable( superEntityBinding.getBaseTable() );

    bindDiscriminatorValue( entitySource, entityBinding );

    return entityBinding;
  }

  private EntityBinding makeJoinedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) {
    final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding );

    bindPrimaryTable( entitySource, entityBinding );

    // todo : join

    return entityBinding;
  }

  private EntityBinding makeUnionedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) {
    final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding );

    bindPrimaryTable( entitySource, entityBinding );

    // todo : ??

    return entityBinding;
  }


  // Attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  private void bindIdentifier(RootEntitySource entitySource, EntityBinding entityBinding) {
    if ( entitySource.getIdentifierSource() == null ) {
      throw new AssertionFailure( "Expecting identifier information on root entity descriptor" );
    }
    switch ( entitySource.getIdentifierSource().getNature() ) {
      case SIMPLE: {
        bindSimpleIdentifier( (SimpleIdentifierSource) entitySource.getIdentifierSource(), entityBinding );
      }
      case AGGREGATED_COMPOSITE: {
        // composite id with an actual component class
      }
      case COMPOSITE: {
        // what we used to term an "embedded composite identifier", which is not tobe confused with the JPA
        // term embedded. Specifically a composite id where there is no component class, though there may
        // be a @IdClass :/
      }
    }
  }

  private void bindSimpleIdentifier(SimpleIdentifierSource identifierSource, EntityBinding entityBinding) {
    final SimpleSingularAttributeBinding idAttributeBinding = doBasicSingularAttributeBindingCreation(
        identifierSource.getIdentifierAttributeSource(), entityBinding
    );

    entityBinding.getEntityIdentifier().setValueBinding( idAttributeBinding );
    entityBinding.getEntityIdentifier().setIdGenerator( identifierSource.getIdentifierGeneratorDescriptor() );

    final org.hibernate.metamodel.relational.Value relationalValue = idAttributeBinding.getValue();

    if ( SimpleValue.class.isInstance( relationalValue ) ) {
      if ( !Column.class.isInstance( relationalValue ) ) {
        // this should never ever happen..
        throw new AssertionFailure( "Simple-id was not a column." );
      }
      entityBinding.getBaseTable().getPrimaryKey().addColumn( Column.class.cast( relationalValue ) );
    }
    else {
      for ( SimpleValue subValue : ( (Tuple) relationalValue ).values() ) {
        if ( Column.class.isInstance( subValue ) ) {
          entityBinding.getBaseTable().getPrimaryKey().addColumn( Column.class.cast( subValue ) );
        }
      }
    }
  }

  private void bindVersion(EntityBinding entityBinding, RootEntitySource entitySource) {
    final SingularAttributeSource versioningAttributeSource = entitySource.getVersioningAttributeSource();
    if ( versioningAttributeSource == null ) {
      return;
    }

    SimpleSingularAttributeBinding attributeBinding = doBasicSingularAttributeBindingCreation(
        versioningAttributeSource, entityBinding
    );
    entityBinding.setVersionBinding( attributeBinding );
  }

  private void bindDiscriminator(RootEntitySource entitySource, EntityBinding entityBinding) {
    // todo : implement
  }

  private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBinding entityBinding) {
    // todo : implement
  }

  private void bindAttributes(AttributeSourceContainer attributeSourceContainer, EntityBinding entityBinding) {
    // todo : we really need the notion of a Stack here for the table from which the columns come for binding these attributes.
    // todo : adding the concept (interface) of a source of attribute metadata would allow reuse of this method for entity, component, unique-key, etc
    // for now, simply assume all columns come from the base table....

    for ( AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) {
      if ( attributeSource.isSingular() ) {
        final SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource;
        if ( singularAttributeSource.getNature() == SingularAttributeNature.COMPONENT ) {
          throw new NotYetImplementedException( "Component binding not yet implemented :(" );
        }
        else {
          doBasicSingularAttributeBindingCreation( singularAttributeSource, entityBinding );
        }
      }
      else {
        bindPersistentCollection( (PluralAttributeSource) attributeSource, entityBinding );
      }
    }
  }

  private void bindPersistentCollection(PluralAttributeSource attributeSource, EntityBinding entityBinding) {
    final AbstractPluralAttributeBinding pluralAttributeBinding;
    if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) {
      final PluralAttribute pluralAttribute = entityBinding.getEntity().locateOrCreateBag( attributeSource.getName() );
      pluralAttributeBinding = entityBinding.makeBagAttributeBinding( pluralAttribute, convert( attributeSource.getPluralAttributeElementNature() ) );
    }
    else {
      // todo : implement other collection types
      throw new NotYetImplementedException( "Collections other than bag not yet implmented :(" );
    }

    doBasicAttributeBinding( attributeSource, pluralAttributeBinding );
  }

  private void doBasicAttributeBinding(AttributeSource attributeSource, AttributeBinding attributeBinding) {
    attributeBinding.setPropertyAccessorName( attributeSource.getPropertyAccessorName() );
    attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() );
  }

  private CollectionElementNature convert(PluralAttributeElementNature pluralAttributeElementNature) {
    return CollectionElementNature.valueOf( pluralAttributeElementNature.name() );
  }

  private SimpleSingularAttributeBinding doBasicSingularAttributeBindingCreation(
      SingularAttributeSource attributeSource,
      EntityBinding entityBinding) {
    final SingularAttribute attribute = attributeSource.isVirtualAttribute()
        ? entityBinding.getEntity().locateOrCreateVirtualAttribute( attributeSource.getName() )
        : entityBinding.getEntity().locateOrCreateSingularAttribute( attributeSource.getName() );

    final SimpleSingularAttributeBinding attributeBinding;
    if ( attributeSource.getNature() == SingularAttributeNature.BASIC ) {
      attributeBinding = entityBinding.makeSimpleAttributeBinding( attribute );
      resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
    }
    else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) {
      attributeBinding = entityBinding.makeManyToOneAttributeBinding( attribute );
      resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding );
      resolveToOneInformation( (ToOneAttributeSource) attributeSource, (ManyToOneAttributeBinding) attributeBinding );
    }
    else {
      throw new NotYetImplementedException();
    }

    attributeBinding.setGeneration( attributeSource.getGeneration() );
    attributeBinding.setLazy( attributeSource.isLazy() );
    attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() );

    attributeBinding.setPropertyAccessorName(
        Helper.getPropertyAccessorName(
            attributeSource.getPropertyAccessorName(),
            false,
            currentBindingContext.getMappingDefaults().getPropertyAccessorName()
        )
    );

    bindRelationalValues( attributeSource, attributeBinding );

    attributeBinding.setMetaAttributeContext(
        buildMetaAttributeContext( attributeSource.metaAttributes(), entityBinding.getMetaAttributeContext() )
    );

    return attributeBinding;
  }

  private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, SimpleSingularAttributeBinding attributeBinding) {
    final Class<?> attributeJavaType = determineJavaType( attributeBinding.getAttribute() );
    if ( attributeJavaType != null ) {
      attributeBinding.getHibernateTypeDescriptor().setJavaTypeName( attributeJavaType.getName() );
      attributeBinding.getAttribute().resolveType( currentBindingContext.makeJavaType( attributeJavaType.getName() ) );
    }

    final String explicitTypeName = typeSource.getName();
    if ( explicitTypeName != null ) {
      final TypeDef typeDef = currentBindingContext.getMetadataImplementor().getTypeDefinition( explicitTypeName );
      if ( typeDef != null ) {
        attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( typeDef.getTypeClass() );
        attributeBinding.getHibernateTypeDescriptor().getTypeParameters().putAll( typeDef.getParameters() );
      }
      else {
        attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( explicitTypeName );
      }
      final Map<String,String> parameters = typeSource.getParameters();
      if ( parameters != null ) {
        attributeBinding.getHibernateTypeDescriptor().getTypeParameters().putAll( parameters );
      }
    }
    else {
      if ( attributeJavaType == 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
      }
    }
  }

  private Class<?> determineJavaType(final Attribute attribute) {
    try {
      final Class ownerClass = attribute.getAttributeContainer().getClassReference();
      AttributeJavaTypeDeterminerDelegate delegate = new AttributeJavaTypeDeterminerDelegate( attribute.getName() );
      BeanInfoHelper.visitBeanInfo( ownerClass, delegate );
      return delegate.javaType;
    }
    catch ( Exception ignore ) {
      // todo : log it?
    }
    return null;
  }

  private static class AttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate {
    private final String attributeName;
    private Class<?> javaType = null;

    private AttributeJavaTypeDeterminerDelegate(String attributeName) {
      this.attributeName = attributeName;
    }

    @Override
    public void processBeanInfo(BeanInfo beanInfo) throws Exception {
      for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) {
        if ( propertyDescriptor.getName().equals( attributeName ) ) {
          javaType = propertyDescriptor.getPropertyType();
          break;
        }
      }
    }
  }

  private void resolveToOneInformation(ToOneAttributeSource attributeSource, ManyToOneAttributeBinding attributeBinding) {
    final String referencedEntityName = attributeSource.getReferencedEntityName() != null
        ? attributeSource.getReferencedEntityName()
        : attributeBinding.getAttribute().getSingularAttributeType().getClassName();
    attributeBinding.setReferencedEntityName( referencedEntityName );
    // todo : we should consider basing references on columns instead of property-ref, which would require a resolution (later) of property-ref to column names
    attributeBinding.setReferencedAttributeName( attributeSource.getReferencedEntityAttributeName() );

    attributeBinding.setCascadeStyles( attributeSource.getCascadeStyles() );
    attributeBinding.setFetchMode( attributeSource.getFetchMode() );
  }

  private MetaAttributeContext buildMetaAttributeContext(EntitySource entitySource) {
    return buildMetaAttributeContext(
        entitySource.metaAttributes(),
        true,
        currentBindingContext.getMetadataImplementor().getGlobalMetaAttributeContext()
    );
  }

  private static MetaAttributeContext buildMetaAttributeContext(
      Iterable<MetaAttributeSource> metaAttributeSources,
      MetaAttributeContext parentContext) {
    return buildMetaAttributeContext( metaAttributeSources, false, parentContext );
  }

  private static MetaAttributeContext buildMetaAttributeContext(
      Iterable<MetaAttributeSource> metaAttributeSources,
      boolean onlyInheritable,
      MetaAttributeContext parentContext) {
    final MetaAttributeContext subContext = new MetaAttributeContext( parentContext );

    for ( MetaAttributeSource metaAttributeSource : metaAttributeSources ) {
      if ( onlyInheritable & !metaAttributeSource.isInheritable() ) {
        continue;
      }

      final String name = metaAttributeSource.getName();
      final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name );
      MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name );
      if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) {
        metaAttribute = new MetaAttribute( name );
        subContext.add( metaAttribute );
      }
      metaAttribute.addValue( metaAttributeSource.getValue() );
    }

    return subContext;
  }


  // Relational ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  private void bindPrimaryTable(EntitySource entitySource, EntityBinding entityBinding) {
    final TableSource tableSource = entitySource.getPrimaryTable();
    final String schemaName = StringHelper.isEmpty( tableSource.getExplicitSchemaName() )
        ? currentBindingContext.getMappingDefaults().getSchemaName()
        : currentBindingContext.getMetadataImplementor().getOptions().isGloballyQuotedIdentifiers()
            ? StringHelper.quote( tableSource.getExplicitSchemaName() )
            : tableSource.getExplicitSchemaName();
    final String catalogName = StringHelper.isEmpty( tableSource.getExplicitCatalogName() )
        ? currentBindingContext.getMappingDefaults().getCatalogName()
        : currentBindingContext.getMetadataImplementor().getOptions().isGloballyQuotedIdentifiers()
            ? StringHelper.quote( tableSource.getExplicitCatalogName() )
            : tableSource.getExplicitCatalogName();

    String tableName = tableSource.getExplicitTableName();
    if ( StringHelper.isEmpty( tableName ) ) {
      tableName = currentBindingContext.getNamingStrategy()
          .classToTableName( entityBinding.getEntity().getClassName() );
    }
    else {
      tableName = currentBindingContext.getNamingStrategy().tableName( tableName );
    }
    if ( currentBindingContext.isGloballyQuotedIdentifiers() ) {
      tableName = StringHelper.quote( tableName );
    }

    final org.hibernate.metamodel.relational.Table table = currentBindingContext.getMetadataImplementor()
        .getDatabase()
        .getSchema( new Schema.Name( schemaName, catalogName ) )
        .locateOrCreateTable( Identifier.toIdentifier( tableName ) );

    entityBinding.setBaseTable( table );
  }

  private void bindSecondaryTables(EntitySource entitySource, EntityBinding entityBinding) {
    // todo : implement
  }

  private void bindTableUniqueConstraints(EntitySource entitySource, EntityBinding entityBinding) {
    // todo : implement
  }

  private void bindRelationalValues(
      RelationalValueSourceContainer relationalValueSourceContainer,
      SingularAttributeBinding attributeBinding) {

    List<SimpleValueBinding> valueBindings = new ArrayList<SimpleValueBinding>();

    if ( relationalValueSourceContainer.relationalValueSources().size() > 0 ) {
      for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) {
        final TableSpecification table = attributeBinding.getEntityBinding()
            .getTable( valueSource.getContainingTableName() );

        if ( ColumnSource.class.isInstance( valueSource ) ) {
          final ColumnSource columnSource = ColumnSource.class.cast( valueSource );
          final Column column = table.locateOrCreateColumn( columnSource.getName() );
          column.setNullable( columnSource.isNullable() );
          column.setDefaultValue( columnSource.getDefaultValue() );
          column.setSqlType( columnSource.getSqlType() );
          column.setSize( columnSource.getSize() );
          column.setDatatype( columnSource.getDatatype() );
          column.setReadFragment( columnSource.getReadFragment() );
          column.setWriteFragment( columnSource.getWriteFragment() );
          column.setUnique( columnSource.isUnique() );
          column.setCheckCondition( columnSource.getCheckCondition() );
          column.setComment( columnSource.getComment() );
          valueBindings.add(
              new SimpleValueBinding(
                  column,
                  columnSource.isIncludedInInsert(),
                  columnSource.isIncludedInUpdate()
              )
          );
        }
        else {
          valueBindings.add(
              new SimpleValueBinding(
                  table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() )
              )
          );
        }
      }
    }
    else {
      final String name = metadata.getOptions()
          .getNamingStrategy()
          .propertyToColumnName( attributeBinding.getAttribute().getName() );
      final SimpleValueBinding valueBinding = new SimpleValueBinding();
      valueBindings.add(
          new SimpleValueBinding(
              attributeBinding.getEntityBinding().getBaseTable().locateOrCreateColumn( name )
          )
      );
    }
    attributeBinding.setSimpleValueBindings( valueBindings );
  }

  private void processFetchProfiles(EntitySource entitySource, EntityBinding entityBinding) {
    // todo : process the entity-local fetch-profile declaration
  }

}
TOP

Related Classes of org.hibernate.metamodel.source.binder.Binder

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.