Package org.hibernate.metamodel.binding

Source Code of org.hibernate.metamodel.binding.EntityBinding

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.binding;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.internal.util.collections.JoinedIterable;
import org.hibernate.metamodel.domain.AttributeContainer;
import org.hibernate.metamodel.domain.Entity;
import org.hibernate.metamodel.domain.PluralAttribute;
import org.hibernate.metamodel.domain.PluralAttributeNature;
import org.hibernate.metamodel.domain.SingularAttribute;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.metamodel.source.MetaAttributeContext;
import org.hibernate.metamodel.source.binder.JpaCallbackClass;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.entity.EntityTuplizer;

/**
* Provides the link between the domain and the relational model for an entity.
*
* @author Steve Ebersole
* @author Hardy Ferentschik
* @author Gail Badner
*/
public class EntityBinding implements AttributeBindingContainer {
  private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null";
  private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null";

  private final EntityBinding superEntityBinding;
  private final List<EntityBinding> subEntityBindings = new ArrayList<EntityBinding>();
  private final HierarchyDetails hierarchyDetails;

  private Entity entity;
  private TableSpecification primaryTable;
    private String primaryTableName;
  private Map<String, TableSpecification> secondaryTables = new HashMap<String, TableSpecification>();

  private ValueHolder<Class<?>> proxyInterfaceType;

  private String jpaEntityName;

  private Class<? extends EntityPersister> customEntityPersisterClass;
  private Class<? extends EntityTuplizer> customEntityTuplizerClass;

  private String discriminatorMatchValue;

  private Set<FilterDefinition> filterDefinitions = new HashSet<FilterDefinition>();
  private Set<SingularAssociationAttributeBinding> entityReferencingAttributeBindings = new HashSet<SingularAssociationAttributeBinding>();

  private MetaAttributeContext metaAttributeContext;

  private boolean lazy;
  private boolean mutable;
  private String whereFilter;
  private String rowId;

  private boolean dynamicUpdate;
  private boolean dynamicInsert;

  private int batchSize;
  private boolean selectBeforeUpdate;
  private boolean hasSubselectLoadableCollections;

  private Boolean isAbstract;

  private String customLoaderName;
  private CustomSQL customInsert;
  private CustomSQL customUpdate;
  private CustomSQL customDelete;

  private Set<String> synchronizedTableNames = new HashSet<String>();
  private Map<String, AttributeBinding> attributeBindingMap = new HashMap<String, AttributeBinding>();

    private List<JpaCallbackClass> jpaCallbackClasses = new ArrayList<JpaCallbackClass>();

  /**
   * Used to instantiate the EntityBinding for an entity that is the root of an inheritance hierarchy
   *
   * @param inheritanceType The inheritance type for the hierarchy
   * @param entityMode The entity mode used in this hierarchy.
   */
  public EntityBinding(InheritanceType inheritanceType, EntityMode entityMode) {
    this.superEntityBinding = null;
    this.hierarchyDetails = new HierarchyDetails( this, inheritanceType, entityMode );
  }

  /**
   * Used to instantiate the EntityBinding for an entity that is a subclass (sub-entity) in an inheritance hierarchy
   *
   * @param superEntityBinding The entity binding of this binding's super
   */
  public EntityBinding(EntityBinding superEntityBinding) {
    this.superEntityBinding = superEntityBinding;
    this.superEntityBinding.subEntityBindings.add( this );
    this.hierarchyDetails = superEntityBinding.getHierarchyDetails();
  }

  public HierarchyDetails getHierarchyDetails() {
    return hierarchyDetails;
  }

  public EntityBinding getSuperEntityBinding() {
    return superEntityBinding;
  }

  public boolean isRoot() {
    return superEntityBinding == null;
  }

  public boolean isPolymorphic() {
    return  superEntityBinding != null ||
        hierarchyDetails.getEntityDiscriminator() != null ||
        ! subEntityBindings.isEmpty();
  }

  public boolean hasSubEntityBindings() {
    return subEntityBindings.size() > 0;
  }

  public int getSubEntityBindingClosureSpan() {
    int n = subEntityBindings.size();
    for ( EntityBinding subEntityBinding : subEntityBindings ) {
      n += subEntityBinding.getSubEntityBindingClosureSpan();
    }
    return n;
  }

  /* used for testing */
  public Iterable<EntityBinding> getDirectSubEntityBindings() {
    return subEntityBindings;
  }

  /**
   * Returns sub-EntityBinding objects in a special 'order', most derived subclasses
   * first. Specifically, the sub-entity bindings follow a depth-first,
   * post-order traversal
   *
   * Note that the returned value excludes this entity binding.
   *
   * @return sub-entity bindings ordered by those entity bindings that are most derived.
   */
  public Iterable<EntityBinding> getPostOrderSubEntityBindingClosure() {
    // TODO: why this order?
    List<Iterable<EntityBinding>> subclassIterables = new ArrayList<Iterable<EntityBinding>>( subEntityBindings.size() + 1 );
    for ( EntityBinding subEntityBinding : subEntityBindings ) {
      Iterable<EntityBinding> subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure();
      if ( subSubEntityBindings.iterator().hasNext() ) {
        subclassIterables.add( subSubEntityBindings );
      }
    }
    if ( ! subEntityBindings.isEmpty() ) {
      subclassIterables.add( subEntityBindings );
    }
    return new JoinedIterable<EntityBinding>( subclassIterables );
  }

  /**
   * Returns sub-EntityBinding ordered as a depth-first,
   * pre-order traversal (a subclass precedes its own subclasses).
   *
   * Note that the returned value specifically excludes this entity binding.
   *
   * @return sub-entity bindings ordered as a depth-first,
   * pre-order traversal
   */
  public Iterable<EntityBinding> getPreOrderSubEntityBindingClosure() {
    return getPreOrderSubEntityBindingClosure( false );
  }

  private Iterable<EntityBinding> getPreOrderSubEntityBindingClosure(boolean includeThis) {
    List<Iterable<EntityBinding>> iterables = new ArrayList<Iterable<EntityBinding>>();
    if ( includeThis ) {
      iterables.add( java.util.Collections.singletonList( this ) );
    }
    for ( EntityBinding subEntityBinding : subEntityBindings ) {
      Iterable<EntityBinding> subSubEntityBindingClosure =  subEntityBinding.getPreOrderSubEntityBindingClosure( true );
      if ( subSubEntityBindingClosure.iterator().hasNext() ) {
        iterables.add( subSubEntityBindingClosure );
      }
    }
    return new JoinedIterable<EntityBinding>( iterables );
  }

  public Entity getEntity() {
    return entity;
  }

  public void setEntity(Entity entity) {
    this.entity = entity;
  }

  public TableSpecification getPrimaryTable() {
    return primaryTable;
  }

  public void setPrimaryTable(TableSpecification primaryTable) {
    this.primaryTable = primaryTable;
  }

    public TableSpecification locateTable(String tableName) {
        if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) {
            return primaryTable;
        }
        TableSpecification tableSpec = secondaryTables.get( tableName );
        if ( tableSpec == null ) {
            throw new AssertionFailure(
                    String.format(
                            "Unable to find table %s amongst tables %s",
                            tableName,
                            secondaryTables.keySet()
                    )
            );
        }
        return tableSpec;
    }
    public String getPrimaryTableName() {
        return primaryTableName;
    }

    public void setPrimaryTableName(String primaryTableName) {
        this.primaryTableName = primaryTableName;
    }

  public void addSecondaryTable(String tableName, TableSpecification table) {
    secondaryTables.put( tableName, table );
  }

  public boolean isVersioned() {
    return getHierarchyDetails().getVersioningAttributeBinding() != null;
  }

  public boolean isDiscriminatorMatchValueNull() {
    return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue );
  }

  public boolean isDiscriminatorMatchValueNotNull() {
    return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue );
  }

  public String getDiscriminatorMatchValue() {
    return discriminatorMatchValue;
  }

  public void setDiscriminatorMatchValue(String discriminatorMatchValue) {
    this.discriminatorMatchValue = discriminatorMatchValue;
  }

  public Iterable<FilterDefinition> getFilterDefinitions() {
    return filterDefinitions;
  }

  public void addFilterDefinition(FilterDefinition filterDefinition) {
    filterDefinitions.add( filterDefinition );
  }

  public Iterable<SingularAssociationAttributeBinding> getEntityReferencingAttributeBindings() {
    return entityReferencingAttributeBindings;
  }

  @Override
  public EntityBinding seekEntityBinding() {
    return this;
  }

  @Override
  public String getPathBase() {
    return getEntity().getName();
  }

  @Override
  public Class<?> getClassReference() {
    return getEntity().getClassReference();
  }

  @Override
  public AttributeContainer getAttributeContainer() {
    return getEntity();
  }

  protected void registerAttributeBinding(String name, AttributeBinding attributeBinding) {
    if ( SingularAssociationAttributeBinding.class.isInstance( attributeBinding ) ) {
      entityReferencingAttributeBindings.add( (SingularAssociationAttributeBinding) attributeBinding );
    }
    attributeBindingMap.put( name, attributeBinding );
  }

  @Override
  public MetaAttributeContext getMetaAttributeContext() {
    return metaAttributeContext;
  }

  public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) {
    this.metaAttributeContext = metaAttributeContext;
  }

  public boolean isMutable() {
    return mutable;
  }

  public void setMutable(boolean mutable) {
    this.mutable = mutable;
  }

  public boolean isLazy() {
    return lazy;
  }

  public void setLazy(boolean lazy) {
    this.lazy = lazy;
  }

  public ValueHolder<Class<?>> getProxyInterfaceType() {
    return proxyInterfaceType;
  }

  public void setProxyInterfaceType(ValueHolder<Class<?>> proxyInterfaceType) {
    this.proxyInterfaceType = proxyInterfaceType;
  }

  public String getWhereFilter() {
    return whereFilter;
  }

  public void setWhereFilter(String whereFilter) {
    this.whereFilter = whereFilter;
  }

  public String getRowId() {
    return rowId;
  }

  public void setRowId(String rowId) {
    this.rowId = rowId;
  }

  public boolean isDynamicUpdate() {
    return dynamicUpdate;
  }

  public void setDynamicUpdate(boolean dynamicUpdate) {
    this.dynamicUpdate = dynamicUpdate;
  }

  public boolean isDynamicInsert() {
    return dynamicInsert;
  }

  public void setDynamicInsert(boolean dynamicInsert) {
    this.dynamicInsert = dynamicInsert;
  }

  public int getBatchSize() {
    return batchSize;
  }

  public void setBatchSize(int batchSize) {
    this.batchSize = batchSize;
  }

  public boolean isSelectBeforeUpdate() {
    return selectBeforeUpdate;
  }

  public void setSelectBeforeUpdate(boolean selectBeforeUpdate) {
    this.selectBeforeUpdate = selectBeforeUpdate;
  }

  public boolean hasSubselectLoadableCollections() {
    return hasSubselectLoadableCollections;
  }

  /* package-protected */
  void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) {
    this.hasSubselectLoadableCollections = hasSubselectLoadableCollections;
  }

  public Class<? extends EntityPersister> getCustomEntityPersisterClass() {
    return customEntityPersisterClass;
  }

  public void setCustomEntityPersisterClass(Class<? extends EntityPersister> customEntityPersisterClass) {
    this.customEntityPersisterClass = customEntityPersisterClass;
  }

  public Class<? extends EntityTuplizer> getCustomEntityTuplizerClass() {
    return customEntityTuplizerClass;
  }

  public void setCustomEntityTuplizerClass(Class<? extends EntityTuplizer> customEntityTuplizerClass) {
    this.customEntityTuplizerClass = customEntityTuplizerClass;
  }

  public Boolean isAbstract() {
    return isAbstract;
  }

  public void setAbstract(Boolean isAbstract) {
    this.isAbstract = isAbstract;
  }

  public Set<String> getSynchronizedTableNames() {
    return synchronizedTableNames;
  }

  public void addSynchronizedTableNames(java.util.Collection<String> synchronizedTableNames) {
    this.synchronizedTableNames.addAll( synchronizedTableNames );
  }

  public String getJpaEntityName() {
    return jpaEntityName;
  }

  public void setJpaEntityName(String jpaEntityName) {
    this.jpaEntityName = jpaEntityName;
  }

  public String getCustomLoaderName() {
    return customLoaderName;
  }

  public void setCustomLoaderName(String customLoaderName) {
    this.customLoaderName = customLoaderName;
  }

  public CustomSQL getCustomInsert() {
    return customInsert;
  }

  public void setCustomInsert(CustomSQL customInsert) {
    this.customInsert = customInsert;
  }

  public CustomSQL getCustomUpdate() {
    return customUpdate;
  }

  public void setCustomUpdate(CustomSQL customUpdate) {
    this.customUpdate = customUpdate;
  }

  public CustomSQL getCustomDelete() {
    return customDelete;
  }

  public void setCustomDelete(CustomSQL customDelete) {
    this.customDelete = customDelete;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append( "EntityBinding" );
    sb.append( "{entity=" ).append( entity != null ? entity.getName() : "not set" );
    sb.append( '}' );
    return sb.toString();
  }

  @Override
  public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) {
    return makeSimpleAttributeBinding( attribute, false, false );
  }

  private BasicAttributeBinding makeSimpleAttributeBinding(SingularAttribute attribute, boolean forceNonNullable, boolean forceUnique) {
    final BasicAttributeBinding binding = new BasicAttributeBinding(
        this,
        attribute,
        forceNonNullable,
        forceUnique
    );
    registerAttributeBinding( attribute.getName(), binding );
    return binding;
  }

  @Override
  public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) {
    final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute );
    registerAttributeBinding( attribute.getName(), binding );
    return binding;
  }

  @Override
  public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) {
    final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute );
    registerAttributeBinding( attribute.getName(), binding );
    return binding;
  }

  @Override
  public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) {
    Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG );
    final BagBinding binding = new BagBinding( this, attribute, nature );
    registerAttributeBinding( attribute.getName(), binding );
    return binding;
  }

  @Override
  public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) {
    Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET );
    final SetBinding binding = new SetBinding( this, attribute, nature );
    registerAttributeBinding( attribute.getName(), binding );
    return binding;
  }

  @Override
  public AttributeBinding locateAttributeBinding(String name) {
    return attributeBindingMap.get( name );
  }

  @Override
  public Iterable<AttributeBinding> attributeBindings() {
    return attributeBindingMap.values();
  }

  /**
   * Gets the number of attribute bindings defined on this class, including the
   * identifier attribute binding and attribute bindings defined
   * as part of a join.
   *
   * @return The number of attribute bindings
   */
  public int getAttributeBindingClosureSpan() {
    // TODO: update account for join attribute bindings
    return superEntityBinding != null ?
        superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() :
        attributeBindingMap.size();
  }

  /**
   * Gets the attribute bindings defined on this class, including the
   * identifier attribute binding and attribute bindings defined
   * as part of a join.
   *
   * @return The attribute bindings.
   */
  public Iterable<AttributeBinding> getAttributeBindingClosure() {
    // TODO: update size to account for joins
    Iterable<AttributeBinding> iterable;
    if ( superEntityBinding != null ) {
      List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>( 2 );
      iterables.add( superEntityBinding.getAttributeBindingClosure() );
      iterables.add( attributeBindings() );
      iterable = new JoinedIterable<AttributeBinding>( iterables );
    }
    else {
      iterable = attributeBindings();
    }
    return iterable;
  }

  /**
   * Gets the attribute bindings for this EntityBinding and all of its
   * sub-EntityBinding, starting from the root of the hierarchy; includes
   * the identifier and attribute bindings defined as part of a join.
   * @return
   */
  public Iterable<AttributeBinding> getSubEntityAttributeBindingClosure() {
    List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>();
    iterables.add( getAttributeBindingClosure() );
    for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) {
      // only add attribute bindings declared for the subEntityBinding
      iterables.add( subEntityBinding.attributeBindings() );
      // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here
    }
    return new JoinedIterable<AttributeBinding>( iterables );
  }

  public void setJpaCallbackClasses( List<JpaCallbackClass> jpaCallbackClasses ) {
      this.jpaCallbackClasses = jpaCallbackClasses;
  }

    public Iterable<JpaCallbackClass> getJpaCallbackClasses() {
        return jpaCallbackClasses;
    }
}
TOP

Related Classes of org.hibernate.metamodel.binding.EntityBinding

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.