/* * 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.orm.persister.collection.spi; import java.util.List; import org.hibernate.HibernateException; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.orm.persister.common.spi.Column; import org.hibernate.orm.persister.common.spi.JoinColumnMapping; import org.hibernate.orm.persister.common.spi.OrmTypeExporter; import org.hibernate.orm.type.spi.Type; import org.hibernate.persister.entity.Joinable; import org.hibernate.query.sqm.NotYetImplementedException; /** * @author Steve Ebersole */ public class CollectionKey implements OrmTypeExporter { // todo : split into interface/impl // that way we can pass in the impl here, but PluralAttributeKey (interface) // can work with any ImprovedCollectionPersister (interface) impl private final CollectionPersister collectionPersister; private List<JoinColumnMapping> joinColumnMappings; public CollectionKey(CollectionPersister collectionPersister) { this.collectionPersister = collectionPersister; } @Override public Type getOrmType() { return collectionPersister.getOrmType(); } public List<JoinColumnMapping> getJoinColumnMappings() { if ( joinColumnMappings == null ) { joinColumnMappings = collectionPersister.getSource().resolveJoinColumnMappings( collectionPersister ); } return joinColumnMappings; } public List<JoinColumnMapping> buildJoinColumnMappings(List<Column> joinTargetColumns) { // NOTE : called from JoinableAttributeContainer#resolveColumnMappings do not "refactor" into #getJoinColumnMappings() // NOTE : joinTargetColumns are the owner's columns we join to (target) whereas #resolveJoinSourceColumns() // returns the collection's key columns (join/fk source). // todo : would much rather carry forward the ForeignKey (in some "resolved" form from the mapping model // Same for entity-typed attributes (all JoinableAttributes) final List<Column> joinSourceColumns = resolveJoinSourceColumns( joinTargetColumns ); if ( joinSourceColumns.size() != joinTargetColumns.size() ) { throw new HibernateException( "Bad resolution of right-hand and left-hand columns for attribute join : " + collectionPersister ); } final List<JoinColumnMapping> joinColumnMappings = CollectionHelper.arrayList( joinSourceColumns.size() ); for ( int i = 0; i < joinSourceColumns.size(); i++ ) { joinColumnMappings.add( new JoinColumnMapping( joinSourceColumns.get( i ), joinTargetColumns.get( i ) ) ); } return joinColumnMappings; } private List<Column> resolveJoinSourceColumns(List<Column> joinTargetColumns) { // NOTE : If the elements are one-to-many (no collection table) we'd really need to understand // columns (or formulas) across the entity hierarchy. For now we assume the persister's // root table. columns are conceivably doable already since @Column names a specific table. // Maybe we should add same to @Formula // // on the bright side, atm CollectionPersister does not currently support // formulas in its key definition final String[] columnNames = ( (Joinable) collectionPersister ).getKeyColumnNames(); final List<Column> columns = CollectionHelper.arrayList( columnNames.length ); assert joinTargetColumns.size() == columnNames.length; throw new NotYetImplementedException( ); // final Table separateCollectionTable = collectionPersister.getSeparateCollectionTable(); // if ( separateCollectionTable != null ) { // for ( int i = 0; i < columnNames.length; i++ ) { // columns.add( // separateCollectionTable.makeColumn( // columnNames[i], // joinTargetColumns.get( i ).getJdbcType() // ) // ); // } // } // else { // // otherwise we just need to resolve the column names in the element table(s) (as the "collection table") // final EntityPersister elementPersister = ( (PluralAttributeElementEntity) collectionPersister.getElementDescriptor() ).getElementPersister(); // // for ( int i = 0; i < columnNames.length; i++ ) { // // it is conceivable that the column already exists // // todo : is the same ^^ true for separateCollectionTable? // Column column = elementPersister.getRootTable().locateColumn( columnNames[i] ); // if ( column == null ) { // column = elementPersister.getRootTable().makeColumn( // columnNames[i], // joinTargetColumns.get( i ).getJdbcType() // ); // } // columns.add( column ); // } // } // // return columns; } }