/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.cfg;

import java.util.Iterator;

import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.annotations.TableBinder;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;

Enable a proper set of the FK columns in respect with the id column order Allow the correct implementation of the default EJB3 values which needs both sides of the association to be resolved
Author:Emmanuel Bernard
/** * Enable a proper set of the FK columns in respect with the id column order * Allow the correct implementation of the default EJB3 values which needs both * sides of the association to be resolved * * @author Emmanuel Bernard */
public class ToOneFkSecondPass extends FkSecondPass { private MetadataBuildingContext buildingContext; private boolean unique; private String path; private String entityClassName; public ToOneFkSecondPass( ToOne value, Ejb3JoinColumn[] columns, boolean unique, String entityClassName, String path, MetadataBuildingContext buildingContext) { super( value, columns ); this.buildingContext = buildingContext; this.unique = unique; this.entityClassName = entityClassName; this.path = entityClassName != null ? path.substring( entityClassName.length() + 1 ) : path; } @Override public String getReferencedEntityName() { return ( (ToOne) value ).getReferencedEntityName(); } @Override public boolean isInPrimaryKey() { if ( entityClassName == null ) return false; final PersistentClass persistentClass = buildingContext.getMetadataCollector().getEntityBinding( entityClassName ); Property property = persistentClass.getIdentifierProperty(); if ( path == null ) { return false; } else if ( property != null) { //try explicit identifier property return path.startsWith( property.getName() + "." ); } else { //try the embedded property //embedded property starts their path with 'id.' See PropertyPreloadedData( ) use when idClass != null in AnnotationSourceProcessor if ( path.startsWith( "id." ) ) { KeyValue valueIdentifier = persistentClass.getIdentifier(); String localPath = path.substring( 3 ); if ( valueIdentifier instanceof Component ) { Iterator it = ( (Component) valueIdentifier ).getPropertyIterator(); while ( it.hasNext() ) { Property idProperty = (Property) it.next(); if ( localPath.startsWith( idProperty.getName() ) ) return true; } } } } return false; } public void doSecondPass(java.util.Map persistentClasses) throws MappingException { if ( value instanceof ManyToOne ) { ManyToOne manyToOne = (ManyToOne) value; PersistentClass ref = (PersistentClass) persistentClasses.get( manyToOne.getReferencedEntityName() ); if ( ref == null ) { throw new AnnotationException( "@OneToOne or @ManyToOne on " + StringHelper.qualify( entityClassName, path ) + " references an unknown entity: " + manyToOne.getReferencedEntityName() ); } manyToOne.setPropertyName( path ); BinderHelper.createSyntheticPropertyReference( columns, ref, null, manyToOne, false, buildingContext ); TableBinder.bindFk( ref, null, columns, manyToOne, unique, buildingContext ); /* * HbmMetadataSourceProcessorImpl does this only when property-ref != null, but IMO, it makes sense event if it is null */ if ( !manyToOne.isIgnoreNotFound() ) manyToOne.createPropertyRefConstraints( persistentClasses ); } else if ( value instanceof OneToOne ) { value.createForeignKey(); } else { throw new AssertionFailure( "FkSecondPass for a wrong value type: " + value.getClass().getName() ); } } }