[hibernate-commits] Hibernate SVN: r10253 - in trunk/HibernateExt/metadata: lib src/java/org/hibernate/annotations src/java/org/hibernate/cfg src/java/org/hibernate/cfg/annotations src/java/org/hibernate/reflection/java src/test/org/hibernate/test/annotations src/test/org/hibernate/test/annotations/identifiercollection

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Sun Aug 13 20:19:56 EDT 2006


Author: epbernard
Date: 2006-08-13 20:19:48 -0400 (Sun, 13 Aug 2006)
New Revision: 10253

Added:
   trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/CollectionId.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/IdBagBinder.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Passport.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Stamp.java
Modified:
   trunk/HibernateExt/metadata/lib/ejb3-persistence.jar
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/BinderHelper.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/IndexColumn.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/OneToOneSecondPass.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/QueryBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/SimpleValueBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java
Log:
ANN-39 introduce @CollectionId
ANN-412 Ejb3OverridenAnnotationReader field used to swallow generators annotations

Modified: trunk/HibernateExt/metadata/lib/ejb3-persistence.jar
===================================================================
(Binary files differ)

Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/CollectionId.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/CollectionId.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/CollectionId.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -0,0 +1,26 @@
+//$Id: $
+package org.hibernate.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.FIELD;
+import javax.persistence.Column;
+
+/**
+ * Describe an identifier column for a bag (ie an idbag)
+ * EXPERIMENTAL: the structure of this annotation might slightly change (generator() mix strategy and generator
+ * 
+ * @author Emmanuel Bernard
+ */
+ at Target({METHOD, FIELD})
+ at Retention(RUNTIME)
+public @interface CollectionId {
+	/** Collection id column(s) */
+	Column[] columns();
+	/** id type, type.type() must be set  */
+	Type type();
+	/** generator name: 'identity' or a defined generator name */
+	String generator();
+}

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -85,6 +85,7 @@
 import org.hibernate.annotations.TypeDef;
 import org.hibernate.annotations.TypeDefs;
 import org.hibernate.annotations.Where;
+import org.hibernate.annotations.CollectionId;
 import org.hibernate.cfg.annotations.CollectionBinder;
 import org.hibernate.cfg.annotations.EntityBinder;
 import org.hibernate.cfg.annotations.Nullability;
@@ -109,7 +110,6 @@
 import org.hibernate.mapping.SimpleValue;
 import org.hibernate.mapping.SingleTableSubclass;
 import org.hibernate.mapping.Subclass;
-import org.hibernate.mapping.Table;
 import org.hibernate.mapping.ToOne;
 import org.hibernate.mapping.UnionSubclass;
 import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
@@ -133,7 +133,6 @@
  * @author Emmanuel Bernard
  */
 public final class AnnotationBinder {
-	public static final String ANNOTATION_STRING_DEFAULT = "";
 
 	/*
 	 * Some design description
@@ -303,24 +302,24 @@
 			idGen.setName( tabGen.name() );
 			idGen.setIdentifierGeneratorStrategy( MultipleHiLoPerTableGenerator.class.getName() );
 
-			if ( !isDefault( tabGen.table() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.table() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.ID_TABLE, tabGen.table() );
 			}
-			if ( ! isDefault( tabGen.catalog() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.catalog() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.CATALOG, tabGen.catalog() );
 			}
-			if ( ! isDefault( tabGen.schema() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.schema() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.SCHEMA, tabGen.schema() );
 			}
 			//FIXME implements uniqueconstrains
 
-			if ( ! isDefault( tabGen.pkColumnName() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.pkColumnName() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, tabGen.pkColumnName() );
 			}
-			if ( ! isDefault( tabGen.valueColumnName() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.valueColumnName() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, tabGen.valueColumnName() );
 			}
-			if ( !isDefault( tabGen.pkColumnValue() ) ) {
+			if ( ! BinderHelper.isDefault( tabGen.pkColumnValue() ) ) {
 				idGen.addParam( MultipleHiLoPerTableGenerator.PK_VALUE_NAME, tabGen.pkColumnValue() );
 			}
 			idGen.addParam( TableHiLoGenerator.MAX_LO, String.valueOf( tabGen.allocationSize() - 1 ) );
@@ -331,7 +330,7 @@
 			idGen.setName( seqGen.name() );
 			idGen.setIdentifierGeneratorStrategy( "seqhilo" );
 
-			if ( ! isDefault( seqGen.sequenceName() ) ) {
+			if ( ! BinderHelper.isDefault( seqGen.sequenceName() ) ) {
 				idGen.addParam( org.hibernate.id.SequenceGenerator.SEQUENCE, seqGen.sequenceName() );
 			}
 			//FIXME: work on initialValue() through SequenceGenerator.PARAMETERS
@@ -645,7 +644,7 @@
 			boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
 			String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
 			String generatorType = "assigned";
-			String generator = ANNOTATION_STRING_DEFAULT;
+			String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
 			PropertyData inferredData = new PropertyPreloadedData(
 					entityBinder.getPropertyAccessor(), "id", compositeClass
 			);
@@ -1164,7 +1163,7 @@
 
 			GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
 			String generatorType = generatedValue != null ? generatorType( generatedValue.strategy() ) : "assigned";
-			String generator = generatedValue != null ? generatedValue.generator() : ANNOTATION_STRING_DEFAULT;
+			String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
 			if ( isComponent ) generatorType = "assigned"; //a component must not have any generator
 			Type typeAnn = property.getAnnotation( Type.class );
 			bindId(
@@ -1309,7 +1308,7 @@
 			);
 			CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder(
 					propertyHolder.getEntityName(),
-					inferredData,
+					property,
 					! indexColumn.isImplicit()
 			);
 			collectionBinder.setIndexColumn( indexColumn );
@@ -1466,7 +1465,14 @@
 				collectionBinder.setInsertable( false );
 				collectionBinder.setUpdatable( false );
 			}
+			if ( property.isAnnotationPresent( CollectionId.class ) ) { //do not compute the generators unless necessary
+				HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
+				localGenerators.putAll( buildLocalGenerators( property, mappings ) );
+				collectionBinder.setLocalGenerators(localGenerators);
+
+			}
 			collectionBinder.bind();
+
 		}
 		else {
 			//define whether the type is a component or not
@@ -1534,9 +1540,9 @@
 		JoinColumn[] annInverseJoins;
 		if ( joinTableAnn != null ) {
 			collectionBinder.setExplicitAssociationTable( true );
-			if ( ! isDefault( joinTableAnn.schema() ) ) associationTableBinder.setSchema( joinTableAnn.schema() );
-			if ( ! isDefault( joinTableAnn.catalog() ) ) associationTableBinder.setCatalog( joinTableAnn.catalog() );
-			if ( ! isDefault( joinTableAnn.name() ) ) associationTableBinder.setName( joinTableAnn.name() );
+			if ( ! BinderHelper.isDefault( joinTableAnn.schema() ) ) associationTableBinder.setSchema( joinTableAnn.schema() );
+			if ( ! BinderHelper.isDefault( joinTableAnn.catalog() ) ) associationTableBinder.setCatalog( joinTableAnn.catalog() );
+			if ( ! BinderHelper.isDefault( joinTableAnn.name() ) ) associationTableBinder.setName( joinTableAnn.name() );
 			associationTableBinder.setUniqueConstraints( joinTableAnn.uniqueConstraints() );
 
 			//set check constaint in the second pass
@@ -1700,47 +1706,7 @@
 			id = value.make();
 		}
 		rootClass.setIdentifier( id );
-		Table table = id.getTable();
-		table.setIdentifierValue( id );
-		//generator settings
-		id.setIdentifierGeneratorStrategy( generatorType );
-		Properties params = new Properties();
-		//always settable
-		params.setProperty(
-				PersistentIdentifierGenerator.TABLE, table.getName()
-		);
-
-		if ( id.getColumnSpan() == 1 ) {
-			params.setProperty(
-					PersistentIdentifierGenerator.PK,
-					( (org.hibernate.mapping.Column) id.getColumnIterator().next() ).getName()
-			);
-		}
-		if ( ! isDefault( generatorName ) ) {
-			//we have a named generator
-			IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );
-			if ( gen == null ) {
-				throw new AnnotationException( "Unknown Id.generator: " + generatorName );
-			}
-			//This is quite vague in the spec but a generator could override the generate choice
-			String identifierGeneratorStrategy = gen.getIdentifierGeneratorStrategy();
-			//yuk! this is a hack not to override 'AUTO' even if generator is set
-			final boolean avoidOverriding =
-					identifierGeneratorStrategy.equals( "identity" )
-							|| identifierGeneratorStrategy.equals( "seqhilo" )
-							|| identifierGeneratorStrategy.equals( MultipleHiLoPerTableGenerator.class.getName() );
-			if ( ! avoidOverriding ) {
-				id.setIdentifierGeneratorStrategy( identifierGeneratorStrategy );
-			}
-			//checkIfMatchingGenerator(gen, generatorType, generatorName);
-			Iterator genParams = gen.getParams().entrySet().iterator();
-			while ( genParams.hasNext() ) {
-				Map.Entry elt = (Map.Entry) genParams.next();
-				params.setProperty( (String) elt.getKey(), (String) elt.getValue() );
-			}
-		}
-		if ( generatorType == "assigned" ) id.setNullValue( "undefined" );
-		id.setIdentifierGeneratorProperties( params );
+		BinderHelper.makeIdGenerator( id, generatorType, generatorName, mappings, localGenerators );
 		if ( isEmbedded ) {
 			rootClass.setEmbeddedIdentifier( inferredData.getPropertyClass() == null );
 		}
@@ -1891,7 +1857,7 @@
 				}
 			}
 		}
-		if ( trueOneToOne || mapToPK || ! isDefault( mappedBy ) ) {
+		if ( trueOneToOne || mapToPK || ! BinderHelper.isDefault( mappedBy ) ) {
 			//is a true one-to-one
 			//FIXME referencedColumnName ignored => ordering may fail.
 			mappings.addSecondPass(
@@ -2038,10 +2004,6 @@
 		return generators;
 	}
 
-	public static boolean isDefault(String annotationString) {
-		return ANNOTATION_STRING_DEFAULT.equals( annotationString );
-	}
-
 	public static boolean isDefault(XClass clazz, ExtendedMappings mappings) {
 		return mappings.getReflectionManager().equals( clazz, void.class );
 	}

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/BinderHelper.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/BinderHelper.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/BinderHelper.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -10,10 +10,13 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.Properties;
 
 import org.hibernate.AnnotationException;
 import org.hibernate.AssertionFailure;
 import org.hibernate.MappingException;
+import org.hibernate.id.PersistentIdentifierGenerator;
+import org.hibernate.id.MultipleHiLoPerTableGenerator;
 import org.hibernate.cfg.annotations.TableBinder;
 import org.hibernate.mapping.Collection;
 import org.hibernate.mapping.Column;
@@ -24,12 +27,17 @@
 import org.hibernate.mapping.Table;
 import org.hibernate.mapping.ToOne;
 import org.hibernate.mapping.Value;
+import org.hibernate.mapping.SimpleValue;
+import org.hibernate.mapping.IdGenerator;
 import org.hibernate.util.StringHelper;
 
 /**
  * @author Emmanuel Bernard
  */
 public class BinderHelper {
+
+	public static final String ANNOTATION_STRING_DEFAULT = "";
+
 	private BinderHelper() {
 	}
 
@@ -351,4 +359,56 @@
 		while ( !found && current != null );
 		return found ? result : null;
 	}
+
+	/** apply an id generator to a SimpleValue */
+	public static void makeIdGenerator(
+			SimpleValue id, String generatorType, String generatorName, ExtendedMappings mappings,
+			Map<String, IdGenerator> localGenerators
+	) {
+		Table table = id.getTable();
+		table.setIdentifierValue( id );
+		//generator settings
+		id.setIdentifierGeneratorStrategy( generatorType );
+		Properties params = new Properties();
+		//always settable
+		params.setProperty(
+				PersistentIdentifierGenerator.TABLE, table.getName()
+		);
+
+		if ( id.getColumnSpan() == 1 ) {
+			params.setProperty(
+					PersistentIdentifierGenerator.PK,
+					( (org.hibernate.mapping.Column) id.getColumnIterator().next() ).getName()
+			);
+		}
+		if ( ! isDefault( generatorName ) ) {
+			//we have a named generator
+			IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );
+			if ( gen == null ) {
+				throw new AnnotationException( "Unknown Id.generator: " + generatorName );
+			}
+			//This is quite vague in the spec but a generator could override the generate choice
+			String identifierGeneratorStrategy = gen.getIdentifierGeneratorStrategy();
+			//yuk! this is a hack not to override 'AUTO' even if generator is set
+			final boolean avoidOverriding =
+					identifierGeneratorStrategy.equals( "identity" )
+							|| identifierGeneratorStrategy.equals( "seqhilo" )
+							|| identifierGeneratorStrategy.equals( MultipleHiLoPerTableGenerator.class.getName() );
+			if ( generatorType == null || ! avoidOverriding ) {
+				id.setIdentifierGeneratorStrategy( identifierGeneratorStrategy );
+			}
+			//checkIfMatchingGenerator(gen, generatorType, generatorName);
+			Iterator genParams = gen.getParams().entrySet().iterator();
+			while ( genParams.hasNext() ) {
+				Map.Entry elt = (Map.Entry) genParams.next();
+				params.setProperty( (String) elt.getKey(), (String) elt.getValue() );
+			}
+		}
+		if ( generatorType == "assigned" ) id.setNullValue( "undefined" );
+		id.setIdentifierGeneratorProperties( params );
+	}
+
+	public static boolean isDefault(String annotationString) {
+		return ANNOTATION_STRING_DEFAULT.equals( annotationString );
+	}
 }

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -51,12 +51,12 @@
 		}
 		else if ( discAnn != null ) {
 			discriminatorColumn.setImplicit( false );
-			if ( ! AnnotationBinder.isDefault( discAnn.columnDefinition() ) ) {
+			if ( ! BinderHelper.isDefault( discAnn.columnDefinition() ) ) {
 				discriminatorColumn.setSqlType(
 						discAnn.columnDefinition()
 				);
 			}
-			if ( ! AnnotationBinder.isDefault( discAnn.name() ) ) {
+			if ( ! BinderHelper.isDefault( discAnn.name() ) ) {
 				discriminatorColumn.setLogicalColumnName( discAnn.name() );
 			}
 			discriminatorColumn.setNullable( false );

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -61,7 +61,7 @@
 
 	//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
 	private Ejb3JoinColumn() {
-		setMappedBy( AnnotationBinder.ANNOTATION_STRING_DEFAULT );
+		setMappedBy( BinderHelper.ANNOTATION_STRING_DEFAULT );
 	}
 
 	//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
@@ -148,7 +148,7 @@
 			ExtendedMappings mappings
 	) {
 		if ( ann != null ) {
-			if ( AnnotationBinder.isDefault( mappedBy ) ) {
+			if ( BinderHelper.isDefault( mappedBy ) ) {
 				throw new AnnotationException(
 						"Illegal attempt to define a @JoinColumn with a mappedBy association: "
 								+ BinderHelper.getRelativePath( propertyHolder, propertyName )
@@ -185,8 +185,8 @@
 		}
 		else {
 			setImplicit( false );
-			if ( ! AnnotationBinder.isDefault( annJoin.columnDefinition() ) ) setSqlType( annJoin.columnDefinition() );
-			if ( ! AnnotationBinder.isDefault( annJoin.name() ) ) setLogicalColumnName( annJoin.name() );
+			if ( ! BinderHelper.isDefault( annJoin.columnDefinition() ) ) setSqlType( annJoin.columnDefinition() );
+			if ( ! BinderHelper.isDefault( annJoin.name() ) ) setLogicalColumnName( annJoin.name() );
 			setNullable( annJoin.nullable() );
 			setUnique( annJoin.unique() );
 			setInsertable( annJoin.insertable() );

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/IndexColumn.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/IndexColumn.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/IndexColumn.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -67,8 +67,8 @@
 	) {
 		IndexColumn column;
 		if ( ann != null ) {
-			String sqlType = AnnotationBinder.isDefault( ann.columnDefinition() ) ? null : ann.columnDefinition();
-			String name = AnnotationBinder.isDefault( ann.name() ) ? inferredData.getPropertyName() : ann.name();
+			String sqlType = BinderHelper.isDefault( ann.columnDefinition() ) ? null : ann.columnDefinition();
+			String name = BinderHelper.isDefault( ann.name() ) ? inferredData.getPropertyName() : ann.name();
 			//TODO move it to a getter based system and remove the constructor
 			column = new IndexColumn(
 					false, sqlType, 0, 0, 0, name, ann.nullable(),

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/OneToOneSecondPass.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/OneToOneSecondPass.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/OneToOneSecondPass.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -90,7 +90,7 @@
 		binder.setCascade( cascadeStrategy );
 		binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
 		Property prop = binder.make();
-		if ( AnnotationBinder.isDefault( mappedBy ) ) {
+		if ( BinderHelper.isDefault( mappedBy ) ) {
 			/*
 			 * we need to check if the columns are in the right order
 			 * if not, then we need to create a many to one and formula

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -33,6 +33,7 @@
 import org.hibernate.annotations.Sort;
 import org.hibernate.annotations.SortType;
 import org.hibernate.annotations.Where;
+import org.hibernate.annotations.CollectionId;
 import org.hibernate.cfg.AnnotatedClassType;
 import org.hibernate.cfg.AnnotationBinder;
 import org.hibernate.cfg.BinderHelper;
@@ -58,6 +59,7 @@
 import org.hibernate.mapping.Property;
 import org.hibernate.mapping.SimpleValue;
 import org.hibernate.mapping.Table;
+import org.hibernate.mapping.IdGenerator;
 import org.hibernate.reflection.XAnnotatedElement;
 import org.hibernate.reflection.XClass;
 import org.hibernate.reflection.XProperty;
@@ -68,7 +70,7 @@
  * Collection binder
  *
  * @author inger
- * @author emmanuel
+ * @author Emmanuel Bernard
  */
 public abstract class CollectionBinder {
 
@@ -108,6 +110,7 @@
 	private TableBinder tableBinder;
 	private Ejb3Column[] mapKeyColumns;
 	private Ejb3JoinColumn[] mapKeyManyToManyColumns;
+	protected HashMap<String, IdGenerator> localGenerators;
 
 	public void setUpdatable(boolean updatable) {
 		this.updatable = updatable;
@@ -154,7 +157,7 @@
 
 	public void setSqlOrderBy(OrderBy orderByAnn) {
 		if ( orderByAnn != null ) {
-			if ( ! AnnotationBinder.isDefault( orderByAnn.clause() ) ) orderBy = orderByAnn.clause();
+			if ( ! BinderHelper.isDefault( orderByAnn.clause() ) ) orderBy = orderByAnn.clause();
 		}
 	}
 
@@ -171,10 +174,9 @@
 	 * collection binder factory
 	 */
 	public static CollectionBinder getCollectionBinder(
-			String entityName, PropertyData inferredData,
+			String entityName, XProperty property,
 			boolean isIndexed
 	) {
-		XProperty property = inferredData.getProperty();
 		if ( property.isArray() ) {
 			if ( property.getElementClass().isPrimitive() ) {
 				return new PrimitiveArrayBinder();
@@ -196,12 +198,20 @@
 				return new MapBinder();
 			}
 			else if ( java.util.Collection.class.equals( returnedClass ) ) {
-				return new BagBinder();
+				if ( property.isAnnotationPresent( CollectionId.class ) ) {
+					return new IdBagBinder();
+				}
+				else {
+					return new BagBinder();
+				}
 			}
 			else if ( java.util.List.class.equals( returnedClass ) ) {
 				if ( isIndexed ) {
 					return new ListBinder();
 				}
+				else if ( property.isAnnotationPresent( CollectionId.class ) ) {
+					return new IdBagBinder();
+				}
 				else {
 					return new BagBinder();
 				}
@@ -321,7 +331,7 @@
 			Map.Entry<String, String> filter = iter.next();
 			String name = filter.getKey();
 			String cond = filter.getValue();
-			if ( AnnotationBinder.isDefault( cond ) ) {
+			if ( BinderHelper.isDefault( cond ) ) {
 				cond = mappings.getFilterDefinition( name ).getDefaultFilterCondition();
 				if ( StringHelper.isEmpty( cond ) ) {
 					throw new AnnotationException(
@@ -334,7 +344,7 @@
 		}
 
 		//work on association
-		boolean isMappedBy = ! AnnotationBinder.isDefault( mappedBy );
+		boolean isMappedBy = ! BinderHelper.isDefault( mappedBy );
 		collection.setInverse( isMappedBy );
 		String collType = getCollectionType().getName();
 
@@ -507,7 +517,7 @@
 				&& ! reversePropertyInJoin
 				&& oneToMany
 				&& ! this.isExplicitAssociationTable
-				&& ( joinColumns[0].isImplicit() && ! AnnotationBinder.isDefault( this.mappedBy ) //implicit @JoinColumn
+				&& ( joinColumns[0].isImplicit() && ! BinderHelper.isDefault( this.mappedBy ) //implicit @JoinColumn
 				|| ! fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
 				) {
 			//this is a Foreign key
@@ -598,7 +608,7 @@
 
 	public void setCache(Cache cacheAnn) {
 		if ( cacheAnn != null ) {
-			cacheRegionName = AnnotationBinder.isDefault( cacheAnn.region() ) ? null : cacheAnn.region();
+			cacheRegionName = BinderHelper.isDefault( cacheAnn.region() ) ? null : cacheAnn.region();
 			cacheConcurrencyStrategy = EntityBinder.getCacheConcurrencyStrategy( cacheAnn.usage() );
 		}
 		else {
@@ -881,7 +891,7 @@
 			}
 		}
 
-		boolean mappedBy = ! AnnotationBinder.isDefault( joinColumns[0].getMappedBy() );
+		boolean mappedBy = ! BinderHelper.isDefault( joinColumns[0].getMappedBy() );
 		if ( mappedBy ) {
 			if ( ! isCollectionOfEntities ) {
 				StringBuilder error = new StringBuilder( 80 )
@@ -1202,4 +1212,8 @@
 	public void setMapKeyManyToManyColumns(Ejb3JoinColumn[] mapJoinColumns) {
 		this.mapKeyManyToManyColumns = mapJoinColumns;
 	}
+
+	public void setLocalGenerators(HashMap<String, IdGenerator> localGenerators) {
+		this.localGenerators = localGenerators;
+	}
 }
\ No newline at end of file

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -34,6 +34,7 @@
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.InheritanceState;
 import org.hibernate.cfg.PropertyHolder;
+import org.hibernate.cfg.BinderHelper;
 import org.hibernate.engine.Versioning;
 import org.hibernate.mapping.DependantValue;
 import org.hibernate.mapping.Join;
@@ -130,7 +131,7 @@
 
 	private void bindEjb3Annotation(Entity ejb3Ann) {
 		if ( ejb3Ann == null ) throw new AssertionFailure( "@Entity should always be not null" );
-		if ( AnnotationBinder.isDefault( ejb3Ann.name() ) ) {
+		if ( BinderHelper.isDefault( ejb3Ann.name() ) ) {
 			name = StringHelper.unqualify( annotatedClass.getName() );
 		}
 		else {
@@ -174,7 +175,7 @@
 		}
 		persistentClass.setOptimisticLockMode( getVersioning( optimisticLockType ) );
 		persistentClass.setSelectBeforeUpdate( selectBeforeUpdate );
-		if ( ! AnnotationBinder.isDefault( persister ) ) {
+		if ( ! BinderHelper.isDefault( persister ) ) {
 			try {
 				persistentClass.setEntityPersisterClass( ReflectHelper.classForName( persister ) );
 			}
@@ -190,7 +191,7 @@
 				Map.Entry<String, String> filter = iter.next();
 				String filterName = filter.getKey();
 				String cond = filter.getValue();
-				if ( AnnotationBinder.isDefault( cond ) ) {
+				if ( BinderHelper.isDefault( cond ) ) {
 					cond = mappings.getFilterDefinition( filterName ).getDefaultFilterCondition();
 					if ( StringHelper.isEmpty( cond ) ) {
 						throw new AnnotationException(
@@ -538,7 +539,7 @@
 
 	public void setCache(Cache cacheAnn) {
 		if ( cacheAnn != null ) {
-			cacheRegion = AnnotationBinder.isDefault( cacheAnn.region() ) ? null : cacheAnn.region();
+			cacheRegion = BinderHelper.isDefault( cacheAnn.region() ) ? null : cacheAnn.region();
 			cacheConcurrentStrategy = getCacheConcurrencyStrategy( cacheAnn.usage() );
 			if ( "all".equalsIgnoreCase( cacheAnn.include() ) ) {
 				cacheLazyProperty = true;

Added: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/IdBagBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/IdBagBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/IdBagBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -0,0 +1,87 @@
+//$Id: $
+package org.hibernate.cfg.annotations;
+
+import java.util.Map;
+import java.util.Collections;
+
+import org.hibernate.mapping.Collection;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.SimpleValue;
+import org.hibernate.mapping.IdentifierCollection;
+import org.hibernate.mapping.Table;
+import org.hibernate.cfg.Ejb3JoinColumn;
+import org.hibernate.cfg.Ejb3Column;
+import org.hibernate.cfg.ExtendedMappings;
+import org.hibernate.cfg.PropertyData;
+import org.hibernate.cfg.WrappedInferredData;
+import org.hibernate.cfg.PropertyInferredData;
+import org.hibernate.cfg.BinderHelper;
+import org.hibernate.reflection.XProperty;
+import org.hibernate.annotations.CollectionId;
+import org.hibernate.annotations.Type;
+import org.hibernate.AnnotationException;
+import org.hibernate.util.StringHelper;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class IdBagBinder extends BagBinder {
+	protected Collection createCollection(PersistentClass persistentClass) {
+		return new org.hibernate.mapping.IdentifierBag( persistentClass );
+	}
+
+	@Override
+	protected boolean bindStarToManySecondPass(
+			Map persistentClasses, String collType, Ejb3JoinColumn[] fkJoinColumns, Ejb3JoinColumn[] keyColumns,
+			Ejb3JoinColumn[] inverseColumns, Ejb3Column[] elementColumns, boolean isEmbedded, XProperty property,
+			boolean unique, TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings
+	) {
+		boolean result = super.bindStarToManySecondPass(
+				persistentClasses, collType, fkJoinColumns, keyColumns, inverseColumns, elementColumns, isEmbedded,
+				property, unique, associationTableBinder, ignoreNotFound, mappings
+		);
+		CollectionId collectionIdAnn = property.getAnnotation( CollectionId.class );
+		if (collectionIdAnn != null) {
+			SimpleValueBinder simpleValue = new SimpleValueBinder();
+
+			PropertyData propertyData = new WrappedInferredData(
+					new PropertyInferredData(property, null), //default access should not be useful
+					"id" );
+			Ejb3Column[] idColumns = Ejb3Column.buildColumnFromAnnotation(
+					collectionIdAnn.columns(),
+					null,
+					Nullability.FORCED_NOT_NULL,
+					propertyHolder,
+					propertyData,
+					Collections.EMPTY_MAP,
+					mappings
+			);
+			Table table = collection.getCollectionTable();
+			simpleValue.setTable( table );
+			simpleValue.setColumns( idColumns );
+			Type typeAnn = collectionIdAnn.type();
+			if ( typeAnn != null && ! BinderHelper.isDefault( typeAnn.type() ) ) {
+				simpleValue.setExplicitType( typeAnn );
+			}
+			else {
+				throw new AnnotationException("@CollectionId is missing type: "
+						+ StringHelper.qualify( propertyHolder.getPath(), propertyName ) );
+			}
+			simpleValue.setMappings( mappings );
+			SimpleValue id = simpleValue.make();
+			( (IdentifierCollection) collection ).setIdentifier( id );
+			String generator = collectionIdAnn.generator();
+			String generatorType;
+			if ( "identity".equals( generator ) || "assigned".equals( generator )
+					|| "sequence".equals( generator ) || "native".equals( generator ) ) {
+				generatorType = generator;
+				generator = "";
+			}
+			else {
+				generatorType = null;
+			}
+			BinderHelper.makeIdGenerator( id, generatorType, generator, mappings, localGenerators);
+		}
+		return result;
+	}
+}

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/QueryBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/QueryBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/QueryBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -19,7 +19,7 @@
 import org.hibernate.LockMode;
 import org.hibernate.annotations.CacheModeType;
 import org.hibernate.annotations.FlushModeType;
-import org.hibernate.cfg.AnnotationBinder;
+import org.hibernate.cfg.BinderHelper;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.NotYetImplementedException;
 import org.hibernate.engine.NamedQueryDefinition;
@@ -37,7 +37,7 @@
 
 	public static void bindQuery(NamedQuery queryAnn, ExtendedMappings mappings, boolean isDefault) {
 		if ( queryAnn == null ) return;
-		if ( AnnotationBinder.isDefault( queryAnn.name() ) ) {
+		if ( BinderHelper.isDefault( queryAnn.name() ) ) {
 			throw new AnnotationException( "A named query must have a name when used in class or package level" );
 		}
 		//EJBQL Query
@@ -68,14 +68,14 @@
 	public static void bindNativeQuery(NamedNativeQuery queryAnn, ExtendedMappings mappings, boolean isDefault) {
 		if ( queryAnn == null ) return;
 		//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
-		if ( AnnotationBinder.isDefault( queryAnn.name() ) ) {
+		if ( BinderHelper.isDefault( queryAnn.name() ) ) {
 			throw new AnnotationException( "A named query must have a name when used in class or package level" );
 		}
 		NamedSQLQueryDefinition query;
 		String resultSetMapping = queryAnn.resultSetMapping();
 		QueryHint[] hints = queryAnn.hints();
 		String queryName = queryAnn.query();
-		if ( ! AnnotationBinder.isDefault( resultSetMapping ) ) {
+		if ( ! BinderHelper.isDefault( resultSetMapping ) ) {
 			//sql result set usage
 			query = new NamedSQLQueryDefinition(
 					queryName,
@@ -131,25 +131,25 @@
 	public static void bindNativeQuery(org.hibernate.annotations.NamedNativeQuery queryAnn, ExtendedMappings mappings) {
 		if ( queryAnn == null ) return;
 		//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
-		if ( AnnotationBinder.isDefault( queryAnn.name() ) ) {
+		if ( BinderHelper.isDefault( queryAnn.name() ) ) {
 			throw new AnnotationException( "A named query must have a name when used in class or package level" );
 		}
 		NamedSQLQueryDefinition query;
 		String resultSetMapping = queryAnn.resultSetMapping();
-		if ( ! AnnotationBinder.isDefault( resultSetMapping ) ) {
+		if ( ! BinderHelper.isDefault( resultSetMapping ) ) {
 			//sql result set usage
 			query = new NamedSQLQueryDefinition(
 					queryAnn.query(),
 					resultSetMapping,
 					null,
 					queryAnn.cacheable(),
-					AnnotationBinder.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+					BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
 					queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
 					queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
 					getFlushMode( queryAnn.flushMode() ),
 					getCacheMode( queryAnn.cacheMode() ),
 					queryAnn.readOnly(),
-					AnnotationBinder.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+					BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
 					null,
 					queryAnn.callable()
 			);
@@ -164,13 +164,13 @@
 					new NativeSQLQueryReturn[]{entityQueryReturn},
 					null,
 					queryAnn.cacheable(),
-					AnnotationBinder.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+					BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
 					queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
 					queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
 					getFlushMode( queryAnn.flushMode() ),
 					getCacheMode( queryAnn.cacheMode() ),
 					queryAnn.readOnly(),
-					AnnotationBinder.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+					BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
 					null,
 					queryAnn.callable()
 			);
@@ -209,7 +209,7 @@
 
 	public static void bindQuery(org.hibernate.annotations.NamedQuery queryAnn, ExtendedMappings mappings) {
 		if ( queryAnn == null ) return;
-		if ( AnnotationBinder.isDefault( queryAnn.name() ) ) {
+		if ( BinderHelper.isDefault( queryAnn.name() ) ) {
 			throw new AnnotationException( "A named query must have a name when used in class or package level" );
 		}
 
@@ -219,13 +219,13 @@
 		NamedQueryDefinition query = new NamedQueryDefinition(
 				queryAnn.query(),
 				queryAnn.cacheable(),
-				AnnotationBinder.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+				BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
 				queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
 				queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
 				flushMode,
 				getCacheMode( queryAnn.cacheMode() ),
 				queryAnn.readOnly(),
-				AnnotationBinder.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+				BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
 				null
 		);
 

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -17,7 +17,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.LockMode;
 import org.hibernate.MappingException;
-import org.hibernate.cfg.AnnotationBinder;
+import org.hibernate.cfg.BinderHelper;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.QuerySecondPass;
 import org.hibernate.engine.ResultSetMappingDefinition;
@@ -136,7 +136,7 @@
 				}
 			}
 
-			if ( ! AnnotationBinder.isDefault( entity.discriminatorColumn() ) ) {
+			if ( ! BinderHelper.isDefault( entity.discriminatorColumn() ) ) {
 				propertyresults.put( "class", new String[]{entity.discriminatorColumn()} );
 			}
 

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/SimpleValueBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/SimpleValueBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/SimpleValueBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -16,7 +16,7 @@
 import org.hibernate.AssertionFailure;
 import org.hibernate.annotations.Parameter;
 import org.hibernate.annotations.Type;
-import org.hibernate.cfg.AnnotationBinder;
+import org.hibernate.cfg.BinderHelper;
 import org.hibernate.cfg.Ejb3Column;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.NotYetImplementedException;
@@ -45,6 +45,7 @@
 	private String explicitType = "";
 	private Properties typeParameters = new Properties();
 	private ExtendedMappings mappings;
+	private Table table;
 
 	public void setPropertyName(String propertyName) {
 		this.propertyName = propertyName;
@@ -54,6 +55,10 @@
 		this.returnedClassName = returnedClassName;
 	}
 
+	public void setTable(Table table) {
+		this.table = table;
+	}
+
 	public void setColumns(Ejb3Column[] columns) {
 		this.columns = columns;
 	}
@@ -74,7 +79,7 @@
 		}
 		Properties typeParameters = this.typeParameters;
 		typeParameters.clear();
-		String type = AnnotationBinder.ANNOTATION_STRING_DEFAULT;
+		String type = BinderHelper.ANNOTATION_STRING_DEFAULT;
 		if ( property.isAnnotationPresent( Temporal.class ) ) {
 			Temporal ann = property.getAnnotation( Temporal.class );
 			boolean isDate;
@@ -152,7 +157,7 @@
 		if ( columns == null ) {
 			throw new AssertionFailure( "SimpleValueBinder.setColumns should be set before SimpleValueBinder.setType" );
 		}
-		if ( AnnotationBinder.ANNOTATION_STRING_DEFAULT.equals( type ) ) {
+		if ( BinderHelper.ANNOTATION_STRING_DEFAULT.equals( type ) ) {
 			if ( returnedClassOrElement.isEnum() ) {
 				type = EnumType.class.getName();
 				typeParameters = new Properties();
@@ -213,13 +218,15 @@
 	public SimpleValue make() {
 		validate();
 		log.debug( "building SimpleValue for " + propertyName );
-		Table table = columns[0].getTable();
+		if (table == null) {
+			table = columns[0].getTable();
+		}
 		SimpleValue simpleValue = new SimpleValue( table );
 		return fillSimpleValue( simpleValue );
 	}
 
-	private SimpleValue fillSimpleValue(SimpleValue simpleValue) {
-		String type = AnnotationBinder.isDefault( explicitType ) ? returnedClassName : explicitType;
+	public SimpleValue fillSimpleValue(SimpleValue simpleValue) {
+		String type = BinderHelper.isDefault( explicitType ) ? returnedClassName : explicitType;
 		org.hibernate.mapping.TypeDef typeDef = mappings.getTypeDef( type );
 		if ( typeDef != null ) {
 			type = typeDef.getTypeClass();

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -11,7 +11,7 @@
 import org.hibernate.AnnotationException;
 import org.hibernate.AssertionFailure;
 import org.hibernate.annotations.Index;
-import org.hibernate.cfg.AnnotationBinder;
+import org.hibernate.cfg.BinderHelper;
 import org.hibernate.cfg.Ejb3JoinColumn;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.IndexSecondPass;
@@ -107,8 +107,8 @@
 			String schema, String catalog, String realTableName, String logicalName, boolean isAbstract,
 			List uniqueConstraints, String constraints, Table denormalizedSuperTable, ExtendedMappings mappings
 	) {
-		schema = AnnotationBinder.isDefault( schema ) ? mappings.getSchemaName() : schema;
-		catalog = AnnotationBinder.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
+		schema = BinderHelper.isDefault( schema ) ? mappings.getSchemaName() : schema;
+		catalog = BinderHelper.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
 		Table table;
 		if ( denormalizedSuperTable != null ) {
 			table = mappings.addDenormalizedTable(

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -353,6 +353,11 @@
 					getAssociation( OneToOne.class, annotationList, defaults );
 					getAssociation( OneToMany.class, annotationList, defaults );
 					getAssociation( ManyToMany.class, annotationList, defaults );
+					Annotation current = getSequenceGenerator( tree, defaults );
+					if ( current != null ) annotationList.add( current );
+					current = getTableGenerator( tree, defaults );
+					if ( current != null ) annotationList.add( current );
+
 				}
 				processEventAnnotations(annotationList, defaults);
 				this.annotations = annotationList.toArray( new Annotation[ annotationList.size() ] );

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -0,0 +1,45 @@
+//$Id: $
+package org.hibernate.test.annotations.identifiercollection;
+
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class IdentifierCollectionTest extends TestCase {
+	public void testIdBag() throws Exception {
+		Passport passport = new Passport();
+		passport.setName( "Emmanuel Bernard" );
+		Stamp canada = new Stamp();
+		canada.setCountry( "Canada" );
+		passport.getStamps().add( canada );
+		passport.getVisaStamp().add( canada );
+		Stamp norway = new Stamp();
+		norway.setCountry( "Norway" );
+		passport.getStamps().add( norway );
+		passport.getStamps().add(canada);
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		s.persist( passport );
+		s.flush();
+		//s.clear();
+		passport = (Passport) s.get( Passport.class, passport.getId() );
+		int canadaCount = 0;
+		for ( Stamp stamp : passport.getStamps() ) {
+			if ( "Canada".equals( stamp.getCountry() ) ) canadaCount++;
+		}
+		assertEquals( 2, canadaCount );
+		assertEquals( 1, passport.getVisaStamp().size() );
+		tx.rollback();
+		s.close();
+	}
+	protected Class[] getMappings() {
+		return new Class[] {
+				Passport.class,
+				Stamp.class
+		};
+	}
+}

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Passport.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Passport.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Passport.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -0,0 +1,70 @@
+//$Id: $
+package org.hibernate.test.annotations.identifiercollection;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.annotations.CollectionId;
+import org.hibernate.annotations.Type;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at TableGenerator(name="ids_generator", table="IDS")
+public class Passport {
+	@Id @GeneratedValue @Column(name="passport_id") private Long id;
+	private String name;
+
+	@ManyToMany(cascade = CascadeType.ALL)
+	@JoinTable(name="PASSPORT_STAMP")
+	@CollectionId(columns = @Column(name="COLLECTION_ID"), type=@Type(type="long"), generator = "generator")
+	@TableGenerator(name="generator", table="IDSTAMP")
+	private Collection<Stamp> stamps = new ArrayList();
+
+	@ManyToMany(cascade = CascadeType.ALL)
+	@JoinTable(name="PASSPORT_VISASTAMP")
+	@CollectionId(columns = @Column(name="COLLECTION_ID"), type=@Type(type="long"), generator = "ids_generator")
+	//TODO test identity generator
+	private Collection<Stamp> visaStamp = new ArrayList();
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Collection<Stamp> getStamps() {
+		return stamps;
+	}
+
+	public void setStamps(Collection<Stamp> stamps) {
+		this.stamps = stamps;
+	}
+
+	public Collection<Stamp> getVisaStamp() {
+		return visaStamp;
+	}
+
+	public void setVisaStamp(Collection<Stamp> visaStamp) {
+		this.visaStamp = visaStamp;
+	}
+}

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Stamp.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Stamp.java	2006-08-11 19:44:32 UTC (rev 10252)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/identifiercollection/Stamp.java	2006-08-14 00:19:48 UTC (rev 10253)
@@ -0,0 +1,31 @@
+//$Id: $
+package org.hibernate.test.annotations.identifiercollection;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Stamp {
+	@Id @GeneratedValue private Long id;
+	private String country;
+
+	public String getCountry() {
+		return country;
+	}
+
+	public void setCountry(String country) {
+		this.country = country;
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+}




More information about the hibernate-commits mailing list