Package org.hibernate.metamodel.binding

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

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

import org.hibernate.MappingException;
import org.hibernate.metamodel.binding.state.ManyToOneAttributeBindingState;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.ForeignKey;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.state.ManyToOneRelationalState;

/**
* TODO : javadoc
*
* @author Gail Badner
*/
public class ManyToOneAttributeBinding extends SimpleAttributeBinding implements EntityReferencingAttributeBinding {
  private boolean isLogicalOneToOne;
  private boolean isPropertyReference;
  private String foreignKeyName;
  private String referencedAttributeName;
  private String referencedEntityName;
  private AttributeBinding referencedAttributeBinding;

  ManyToOneAttributeBinding(EntityBinding entityBinding) {
    super( entityBinding, false, false );
  }

  public final ManyToOneAttributeBinding initialize(ManyToOneAttributeBindingState state) {
    super.initialize( state );
    isPropertyReference = state.getReferencedAttributeName() != null;
    referencedAttributeName = state.getReferencedAttributeName();
    referencedEntityName = state.getReferencedEntityName();
    return this;
  }

  public final ManyToOneAttributeBinding initialize(ManyToOneRelationalState state) {
    super.initializeValueRelationalState( state );
    isLogicalOneToOne = state.isLogicalOneToOne();
    foreignKeyName = state.getForeignKeyName();
    return this;
  }

  public final boolean isPropertyReference() {
    return isPropertyReference;
  }

  public final String getReferencedEntityName() {
    return referencedEntityName;
  }

  public final String getReferencedAttributeName() {
    if ( referencedAttributeName == null ) {
      throw new IllegalStateException(
          "Referenced attribute name is not available."
      );
    }
    return referencedAttributeName;
  }

  public final boolean isReferenceResolved() {
    return referencedAttributeBinding != null;
  }

  public final EntityBinding getReferencedEntityBinding() {
    if ( !isReferenceResolved() ) {
      throw new IllegalStateException( "EntityBinding reference has not be referenced." );
    }
    // TODO: throw exception if referencedEntityBinding is null?
    return referencedAttributeBinding.getEntityBinding();
  }

  public final void resolveReference(AttributeBinding referencedAttributeBinding) {
    if ( !referencedEntityName.equals( referencedAttributeBinding.getEntityBinding().getEntity().getName() ) ) {
      throw new IllegalStateException(
          "attempt to set EntityBinding with name: [" +
              referencedAttributeBinding.getEntityBinding().getEntity().getName() +
              "; entity name should be: " + referencedEntityName
      );
    }
    if ( referencedAttributeName == null ) {
      referencedAttributeName = referencedAttributeBinding.getAttribute().getName();
    }
    else if ( !referencedAttributeName.equals( referencedAttributeBinding.getAttribute().getName() ) ) {
      throw new IllegalStateException(
          "Inconsistent attribute name; expected: " + referencedAttributeName +
              "actual: " + referencedAttributeBinding.getAttribute().getName()
      );
    }
    this.referencedAttributeBinding = referencedAttributeBinding;
    buildForeignKey();
  }

  private void buildForeignKey() {
    // TODO: move this stuff to relational model
    ForeignKey foreignKey = getValue().getTable()
        .createForeignKey( referencedAttributeBinding.getValue().getTable(), foreignKeyName );
    Iterator<SimpleValue> referencingValueIterator = getValues().iterator();
    Iterator<SimpleValue> targetValueIterator = referencedAttributeBinding.getValues().iterator();
    while ( referencingValueIterator.hasNext() ) {
      if ( !targetValueIterator.hasNext() ) {
        // TODO: improve this message
        throw new MappingException(
            "number of values in many-to-one reference is greater than number of values in target"
        );
      }
      SimpleValue referencingValue = referencingValueIterator.next();
      SimpleValue targetValue = targetValueIterator.next();
      if ( Column.class.isInstance( referencingValue ) ) {
        if ( !Column.class.isInstance( targetValue ) ) {
          // TODO improve this message
          throw new MappingException( "referencing value is a column, but target is not a column" );
        }
        foreignKey.addColumnMapping( Column.class.cast( referencingValue ), Column.class.cast( targetValue ) );
      }
      else if ( Column.class.isInstance( targetValue ) ) {
        // TODO: improve this message
        throw new MappingException( "referencing value is not a column, but target is a column." );
      }
    }
    if ( targetValueIterator.hasNext() ) {
      throw new MappingException( "target value has more simple values than referencing value" );
    }
  }

  public boolean isSimpleValue() {
    return false;
  }

  public void validate() {
    // can't check this until both the domain and relational states are initialized...
    if ( getCascadeTypes().contains( CascadeType.DELETE_ORPHAN ) ) {
      if ( !isLogicalOneToOne ) {
        throw new MappingException(
            "many-to-one attribute [" + getAttribute().getName() + "] does not support orphan delete as it is not unique"
        );
      }
    }
    //TODO: validate that the entity reference is resolved
  }
}
TOP

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

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.