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

import java.util.Iterator;

import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
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 boolean unique; private Mappings mappings; private String path; private String entityClassName; public ToOneFkSecondPass( ToOne value, Ejb3JoinColumn[] columns, boolean unique, String entityClassName, String path, Mappings mappings) { super( value, columns ); this.mappings = mappings; 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 = mappings.getClass( 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() ); } BinderHelper.createSyntheticPropertyReference( columns, ref, null, manyToOne, false, mappings ); TableBinder.bindFk( ref, null, columns, manyToOne, unique, mappings ); /* * 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() ); } } }