[hibernate-commits] Hibernate SVN: r14899 - in core/branches/Branch_3_2_4_SP1_CP: src/org/hibernate/action and 16 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Jul 8 21:03:32 EDT 2008


Author: gbadner
Date: 2008-07-08 21:03:32 -0400 (Tue, 08 Jul 2008)
New Revision: 14899

Added:
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/AbstractCollectionEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEventListener.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractParentWithCollection.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/BrokenCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Child.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildEntity.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildValue.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionEventSuite.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionListeners.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Entity.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ParentWithCollection.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/AbstractAssociationCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ChildWithBidirectionalManyToMany.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ParentWithBidirectionalManyToMany.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ChildWithManyToOne.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToMany.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToManySubclass.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/ParentWithCollectionOfEntities.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ParentWithCollectionOfValues.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagCollectionEventTest.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagMapping.hbm.xml
Modified:
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRecreateAction.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRemoveAction.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionUpdateAction.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/cfg/Configuration.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/PersistenceContext.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/StatefulPersistenceContext.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/EventListeners.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/InitializeCollectionEvent.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/def/ReattachVisitor.java
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/hibernate-configuration-3.0.dtd
   core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/type/CollectionType.java
   core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/AllTests.java
Log:
JBPAPP-954, HHH-2616 : No event is fired on Collection recreate/remove/update action


Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRecreateAction.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRecreateAction.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRecreateAction.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -2,6 +2,11 @@
 package org.hibernate.action;
 
 import org.hibernate.HibernateException;
+import org.hibernate.event.PostCollectionRecreateEventListener;
+import org.hibernate.event.PostCollectionRecreateEvent;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.PreCollectionRecreateEvent;
+import org.hibernate.event.PreCollectionRecreateEventListener;
 import org.hibernate.cache.CacheException;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionImplementor;
@@ -21,8 +26,13 @@
 	}
 
 	public void execute() throws HibernateException {
+		// this method is called when a new non-null collection is persisted
+		// or when an existing (non-null) collection is moved to a new owner
+
 		final PersistentCollection collection = getCollection();
 		
+		preRecreate();
+
 		getPersister().recreate( collection, getKey(), getSession() );
 		
 		getSession().getPersistenceContext()
@@ -31,12 +41,37 @@
 		
 		evict();
 
+		postRecreate();
+
 		if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
 			getSession().getFactory().getStatisticsImplementor()
 					.recreateCollection( getPersister().getRole() );
 		}
 	}
 
+	private void preRecreate() {
+		PreCollectionRecreateEventListener[] preListeners = getSession().getListeners()
+				.getPreCollectionRecreateEventListeners();
+		if (preListeners.length > 0) {
+			PreCollectionRecreateEvent preEvent = new PreCollectionRecreateEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession() );
+			for ( int i = 0; i < preListeners.length; i++ ) {
+				preListeners[i].onPreRecreateCollection( preEvent );
+			}
+		}
+	}
+
+	private void postRecreate() {
+		PostCollectionRecreateEventListener[] postListeners = getSession().getListeners()
+				.getPostCollectionRecreateEventListeners();
+		if (postListeners.length > 0) {
+			PostCollectionRecreateEvent postEvent = new PostCollectionRecreateEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession() );
+			for ( int i = 0; i < postListeners.length; i++ ) {
+				postListeners[i].onPostRecreateCollection( postEvent );
+			}
+		}
+	}
 }
 
 

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRemoveAction.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRemoveAction.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionRemoveAction.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -1,32 +1,89 @@
 //$Id$
 package org.hibernate.action;
 
+import java.io.Serializable;
+
+import org.hibernate.AssertionFailure;
 import org.hibernate.HibernateException;
 import org.hibernate.cache.CacheException;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionImplementor;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.PostCollectionRemoveEvent;
+import org.hibernate.event.PostCollectionRemoveEventListener;
+import org.hibernate.event.PreCollectionRemoveEvent;
+import org.hibernate.event.PreCollectionRemoveEventListener;
 import org.hibernate.persister.collection.CollectionPersister;
 
-import java.io.Serializable;
-
 public final class CollectionRemoveAction extends CollectionAction {
 
 	private boolean emptySnapshot;
+	private final Object affectedOwner;
 
+	/**
+	 * Removes a persistent collection from its loaded owner.
+	 *
+	 * Use this constructor when the collection is non-null.
+	 *
+	 * @param collection The collection to to remove; must be non-null
+	 * @param persister  The collection's persister
+	 * @param id The collection key
+	 * @param emptySnapshot Indicates if the snapshot is empty
+	 * @param session The session
+	 * @throws AssertionFailure if collection is null.
+	 */
 	public CollectionRemoveAction(
 				final PersistentCollection collection,
 				final CollectionPersister persister,
-				final Serializable id, 
-				final boolean emptySnapshot, 
+				final Serializable id,
+				final boolean emptySnapshot,
 				final SessionImplementor session)
 			throws CacheException {
 		super( persister, collection, id, session );
+		if (collection == null) { throw new AssertionFailure("collection == null"); }
 		this.emptySnapshot = emptySnapshot;
+		// the loaded owner will be set to null after the collection is removed,
+		// so capture its value as the affected owner so it is accessible to
+		// both pre- and post- events
+		this.affectedOwner = session.getPersistenceContext().getLoadedCollectionOwnerOrNull( collection );
 	}
 
+	/**
+	 * Removes a persistent collection from a specified owner.
+	 *
+	 * Use this constructor when the collection to be removed has not been loaded.
+	 *
+	 * @param affectedOwner The collection's owner; must be non-null
+	 * @param persister  The collection's persister
+	 * @param id The collection key
+	 * @param emptySnapshot Indicates if the snapshot is empty
+	 * @param session The session
+	 * @throws AssertionFailure if affectedOwner is null.
+	 */
+	public CollectionRemoveAction(
+				final Object affectedOwner,
+				final CollectionPersister persister,
+				final Serializable id,
+				final boolean emptySnapshot,
+				final SessionImplementor session)
+			throws CacheException {
+		super( persister, null, id, session );
+		if (affectedOwner == null) { throw new AssertionFailure("affectedOwner == null"); }
+		this.emptySnapshot = emptySnapshot;
+		this.affectedOwner = affectedOwner;
+	}
+
 	public void execute() throws HibernateException {
-		if ( !emptySnapshot ) getPersister().remove( getKey(), getSession() );
-		
+		preRemove();
+
+		if ( !emptySnapshot ) {
+			// an existing collection that was either non-empty or uninitialized
+			// is replaced by null or a different collection
+			// (if the collection is uninitialized, hibernate has no way of
+			// knowing if the collection is actually empty without querying the db)
+			getPersister().remove( getKey(), getSession() );
+		}
+
 		final PersistentCollection collection = getCollection();
 		if (collection!=null) {
 			getSession().getPersistenceContext()
@@ -36,18 +93,35 @@
 		
 		evict();
 
+		postRemove();
+
 		if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
 			getSession().getFactory().getStatisticsImplementor()
 					.removeCollection( getPersister().getRole() );
 		}
 	}
 
+	private void preRemove() {
+		PreCollectionRemoveEventListener[] preListeners = getSession().getListeners()
+				.getPreCollectionRemoveEventListeners();
+		if (preListeners.length>0) {
+			PreCollectionRemoveEvent preEvent = new PreCollectionRemoveEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession(), affectedOwner );
+			for ( int i = 0; i < preListeners.length; i++ ) {
+				preListeners[i].onPreRemoveCollection(preEvent);
+			}
+		}
+	}
 
+	private void postRemove() {
+		PostCollectionRemoveEventListener[] postListeners = getSession().getListeners()
+				.getPostCollectionRemoveEventListeners();
+		if (postListeners.length>0) {
+			PostCollectionRemoveEvent postEvent = new PostCollectionRemoveEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession(), affectedOwner );
+			for ( int i = 0; i < postListeners.length; i++ ) {
+				postListeners[i].onPostRemoveCollection(postEvent);
+			}
+		}
+	}
 }
-
-
-
-
-
-
-

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionUpdateAction.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionUpdateAction.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/action/CollectionUpdateAction.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -3,6 +3,11 @@
 
 import org.hibernate.AssertionFailure;
 import org.hibernate.HibernateException;
+import org.hibernate.event.PostCollectionUpdateEvent;
+import org.hibernate.event.PreCollectionUpdateEvent;
+import org.hibernate.event.PreCollectionUpdateEventListener;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.PostCollectionUpdateEventListener;
 import org.hibernate.cache.CacheException;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionImplementor;
@@ -33,6 +38,8 @@
 		final PersistentCollection collection = getCollection();
 		boolean affectedByFilters = persister.isAffectedByEnabledFilters(session);
 
+		preUpdate();
+
 		if ( !collection.wasInitialized() ) {
 			if ( !collection.hasQueuedOperations() ) throw new AssertionFailure( "no queued adds" );
 			//do nothing - we only need to notify the cache...
@@ -62,12 +69,37 @@
 
 		evict();
 
+		postUpdate();
+
 		if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
 			getSession().getFactory().getStatisticsImplementor().
 					updateCollection( getPersister().getRole() );
 		}
 	}
 
+	private void preUpdate() {
+		PreCollectionUpdateEventListener[] preListeners = getSession().getListeners()
+				.getPreCollectionUpdateEventListeners();
+		if (preListeners.length > 0) {
+			PreCollectionUpdateEvent preEvent = new PreCollectionUpdateEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession() );
+			for ( int i = 0; i < preListeners.length; i++ ) {
+				preListeners[i].onPreUpdateCollection( preEvent );
+			}
+		}
+	}
+
+	private void postUpdate() {
+		PostCollectionUpdateEventListener[] postListeners = getSession().getListeners()
+				.getPostCollectionUpdateEventListeners();
+		if (postListeners.length > 0) {
+			PostCollectionUpdateEvent postEvent = new PostCollectionUpdateEvent(
+					getPersister(), getCollection(), ( EventSource ) getSession() );
+			for ( int i = 0; i < postListeners.length; i++ ) {
+				postListeners[i].onPostUpdateCollection( postEvent );
+			}
+		}
+	}
 }
 
 

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/cfg/Configuration.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/cfg/Configuration.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/cfg/Configuration.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -67,6 +67,12 @@
 import org.hibernate.event.RefreshEventListener;
 import org.hibernate.event.ReplicateEventListener;
 import org.hibernate.event.SaveOrUpdateEventListener;
+import org.hibernate.event.PreCollectionRecreateEventListener;
+import org.hibernate.event.PreCollectionRemoveEventListener;
+import org.hibernate.event.PreCollectionUpdateEventListener;
+import org.hibernate.event.PostCollectionUpdateEventListener;
+import org.hibernate.event.PostCollectionRemoveEventListener;
+import org.hibernate.event.PostCollectionRecreateEventListener;
 import org.hibernate.id.IdentifierGenerator;
 import org.hibernate.id.PersistentIdentifierGenerator;
 import org.hibernate.impl.SessionFactoryImpl;
@@ -1853,6 +1859,30 @@
 				eventListeners.setPreInsertEventListeners( (PreInsertEventListener[]) listeners );
 			}
 		}
+		else if ( "pre-collection-recreate".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPreCollectionRecreateEventListeners( new PreCollectionRecreateEventListener[]{} );
+			}
+			else {
+				eventListeners.setPreCollectionRecreateEventListeners( (PreCollectionRecreateEventListener[]) listeners );
+			}
+		}
+		else if ( "pre-collection-remove".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPreCollectionRemoveEventListeners( new PreCollectionRemoveEventListener[]{} );
+			}
+			else {
+				eventListeners.setPreCollectionRemoveEventListeners( ( PreCollectionRemoveEventListener[]) listeners );
+			}
+		}
+		else if ( "pre-collection-update".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPreCollectionUpdateEventListeners( new PreCollectionUpdateEventListener[]{} );
+			}
+			else {
+				eventListeners.setPreCollectionUpdateEventListeners( ( PreCollectionUpdateEventListener[]) listeners );
+			}
+		}
 		else if ( "post-load".equals( type ) ) {
 			if ( listeners == null ) {
 				eventListeners.setPostLoadEventListeners( new PostLoadEventListener[]{} );
@@ -1915,6 +1945,30 @@
 				eventListeners.setPostCommitInsertEventListeners( (PostInsertEventListener[]) listeners );
 			}
 		}
+		else if ( "post-collection-recreate".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPostCollectionRecreateEventListeners( new PostCollectionRecreateEventListener[]{} );
+			}
+			else {
+				eventListeners.setPostCollectionRecreateEventListeners( (PostCollectionRecreateEventListener[]) listeners );
+			}
+		}
+		else if ( "post-collection-remove".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPostCollectionRemoveEventListeners( new PostCollectionRemoveEventListener[]{} );
+			}
+			else {
+				eventListeners.setPostCollectionRemoveEventListeners( ( PostCollectionRemoveEventListener[]) listeners );
+			}
+		}
+		else if ( "post-collection-update".equals( type ) ) {
+			if ( listeners == null ) {
+				eventListeners.setPostCollectionUpdateEventListeners( new PostCollectionUpdateEventListener[]{} );
+			}
+			else {
+				eventListeners.setPostCollectionUpdateEventListeners( ( PostCollectionUpdateEventListener[]) listeners );
+			}
+		}
 		else {
 			log.warn( "Unrecognized listener type [" + type + "]" );
 		}

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/PersistenceContext.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/PersistenceContext.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/PersistenceContext.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -250,7 +250,24 @@
 	public Object getCollectionOwner(Serializable key, CollectionPersister collectionPersister)
 			throws MappingException;
 
+	/**         
+	 * Get the entity that owned this persistent collection when it was loaded
+	 *
+	 * @param collection The persistent collection
+	 * @return the owner if its entity ID is available from the collection's loaded key
+	 * and the owner entity is in the persistence context; otherwise, returns null
+	 */
+	Object getLoadedCollectionOwnerOrNull(PersistentCollection collection);
+
 	/**
+	 * Get the ID for the entity that owned this persistent collection when it was loaded
+	 *
+	 * @param collection The persistent collection
+	 * @return the owner ID if available from the collection's loaded key; otherwise, returns null
+	 */
+	public Serializable getLoadedCollectionOwnerIdOrNull(PersistentCollection collection);
+
+	/**
 	 * add a collection we just loaded up (still needs initializing)
 	 */
 	public void addUninitializedCollection(CollectionPersister persister,

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/StatefulPersistenceContext.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/engine/StatefulPersistenceContext.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -679,6 +679,53 @@
 	}
 
 	/**
+	 * Get the entity that owned this persistent collection when it was loaded
+	 *
+	 * @param collection The persistent collection
+	 * @return the owner, if its entity ID is available from the collection's loaded key
+	 * and the owner entity is in the persistence context; otherwise, returns null
+	 */
+	public Object getLoadedCollectionOwnerOrNull(PersistentCollection collection) {
+		CollectionEntry ce = getCollectionEntry( collection );
+		if ( ce.getLoadedPersister() == null ) {
+			return null; // early exit...
+		}
+		Object loadedOwner = null;
+		// TODO: an alternative is to check if the owner has changed; if it hasn't then 
+		// return collection.getOwner()
+		Serializable entityId = getLoadedCollectionOwnerIdOrNull( ce );
+		if ( entityId != null ) {
+			loadedOwner = getCollectionOwner( entityId, ce.getLoadedPersister() );
+		}
+		return loadedOwner;
+	}
+
+	/**
+	 * Get the ID for the entity that owned this persistent collection when it was loaded
+	 *
+	 * @param collection The persistent collection
+	 * @return the owner ID if available from the collection's loaded key; otherwise, returns null
+	 */
+	public Serializable getLoadedCollectionOwnerIdOrNull(PersistentCollection collection) {
+		return getLoadedCollectionOwnerIdOrNull( getCollectionEntry( collection ) );
+	}
+
+	/**
+	 * Get the ID for the entity that owned this persistent collection when it was loaded
+	 *
+	 * @param ce The collection entry
+	 * @return the owner ID if available from the collection's loaded key; otherwise, returns null
+	 */
+	private Serializable getLoadedCollectionOwnerIdOrNull(CollectionEntry ce) {
+		if ( ce == null || ce.getLoadedKey() == null || ce.getLoadedPersister() == null ) {
+			return null;
+		}
+		// TODO: an alternative is to check if the owner has changed; if it hasn't then
+		// get the ID from collection.getOwner()
+		return ce.getLoadedPersister().getCollectionType().getIdOfOwnerOrNull( ce.getLoadedKey(), session );
+	}
+
+	/**
 	 * add a collection we just loaded up (still needs initializing)
 	 */
 	public void addUninitializedCollection(CollectionPersister persister, PersistentCollection collection, Serializable id) {

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/AbstractCollectionEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/AbstractCollectionEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/AbstractCollectionEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,115 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.engine.CollectionEntry;
+import org.hibernate.engine.EntityEntry;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * Defines a base class for events involving collections.
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractCollectionEvent extends AbstractEvent {
+
+	private final PersistentCollection collection;
+	private final Object affectedOwner;
+	private final Serializable affectedOwnerId;
+	private final String affectedOwnerEntityName;
+
+	/**
+	 * Constructs an AbstractCollectionEvent object.
+	 *
+	 * @param collection - the collection
+	 * @param source - the Session source
+	 * @param affectedOwner - the owner that is affected by this event;
+	 * can be null if unavailable
+	 * @param affectedOwnerId - the ID for the owner that is affected
+	 * by this event; can be null if unavailable
+	 * that is affected by this event; can be null if unavailable
+	 */
+	public AbstractCollectionEvent( CollectionPersister collectionPersister,
+					PersistentCollection collection,
+					EventSource source,
+					Object affectedOwner,
+					Serializable affectedOwnerId) {
+		super(source);
+		this.collection = collection;
+		this.affectedOwner = affectedOwner;
+		this.affectedOwnerId = affectedOwnerId;
+		this.affectedOwnerEntityName =
+				getAffectedOwnerEntityName( collectionPersister, affectedOwner, source );
+	}
+
+	protected static CollectionPersister getLoadedCollectionPersister( PersistentCollection collection, EventSource source ) {
+		CollectionEntry ce = source.getPersistenceContext().getCollectionEntry( collection );
+		return ( ce == null ? null : ce.getLoadedPersister() );		
+	}
+
+	protected static Object getLoadedOwnerOrNull( PersistentCollection collection, EventSource source ) {
+		return source.getPersistenceContext().getLoadedCollectionOwnerOrNull( collection );
+	}
+
+	protected static Serializable getLoadedOwnerIdOrNull( PersistentCollection collection, EventSource source ) {
+		return source.getPersistenceContext().getLoadedCollectionOwnerIdOrNull( collection );
+	}
+
+	protected static Serializable getOwnerIdOrNull( Object owner, EventSource source ) {
+		EntityEntry ownerEntry = source.getPersistenceContext().getEntry( owner );
+		return ( ownerEntry == null ? null : ownerEntry.getId() );
+	}
+
+	protected static String getAffectedOwnerEntityName(CollectionPersister collectionPersister, Object affectedOwner, EventSource source ) {
+
+		// collectionPersister should not be null, but we don't want to throw
+		// an exception if it is null
+		String entityName =
+				( collectionPersister == null ? null : collectionPersister.getOwnerEntityPersister().getEntityName() );
+		if ( affectedOwner != null ) {
+			EntityEntry ee = source.getPersistenceContext().getEntry( affectedOwner );
+			if ( ee != null && ee.getEntityName() != null) {
+				entityName = ee.getEntityName();
+			}
+		}	
+		return entityName;
+	}
+
+	public PersistentCollection getCollection() {
+		return collection;
+	}
+
+	/**
+	 * Get the collection owner entity that is affected by this event.
+	 *
+	 * @return the affected owner; returns null if the entity is not in the persistence context
+	 * (e.g., because the collection from a detached entity was moved to a new owner)
+	 */
+	public Object getAffectedOwnerOrNull() {
+		return affectedOwner;
+	}
+
+	/**
+	 * Get the ID for the collection owner entity that is affected by this event.
+	 *
+	 * @return the affected owner ID; returns null if the ID cannot be obtained
+	 * from the collection's loaded key (e.g., a property-ref is used for the
+	 * collection and does not include the entity's ID)
+	 */
+	public Serializable getAffectedOwnerIdOrNull() {
+		return affectedOwnerId;
+	}
+
+	/**
+	 * Get the entity name for the collection owner entity that is affected by this event.
+	 *
+	 * @return the entity name; if the owner is not in the PersistenceContext, the
+	 * returned value may be a superclass name, instead of the actual class name
+	 */
+	public String getAffectedOwnerEntityName() {
+		return affectedOwnerEntityName;
+	}
+
+}

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/EventListeners.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/EventListeners.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/EventListeners.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -69,6 +69,13 @@
 	private PostUpdateEventListener[] postCommitUpdateEventListeners = {};
 	private PostInsertEventListener[] postCommitInsertEventListeners = {};
 
+	private PreCollectionRecreateEventListener[] preCollectionRecreateEventListeners = {};
+	private PostCollectionRecreateEventListener[] postCollectionRecreateEventListeners = {};
+	private PreCollectionRemoveEventListener[] preCollectionRemoveEventListeners = {};
+	private PostCollectionRemoveEventListener[] postCollectionRemoveEventListeners = {};
+	private PreCollectionUpdateEventListener[] preCollectionUpdateEventListeners = {};
+	private PostCollectionUpdateEventListener[] postCollectionUpdateEventListeners = {};
+
 	private SaveOrUpdateEventListener[] saveEventListeners = { new DefaultSaveEventListener() };
 	private SaveOrUpdateEventListener[] updateEventListeners = { new DefaultUpdateEventListener() };
 	private MergeEventListener[] saveOrUpdateCopyEventListeners = { new DefaultSaveOrUpdateCopyEventListener() };//saveOrUpdateCopy() is deprecated!
@@ -99,6 +106,9 @@
 		eventInterfaceFromType.put("pre-update", PreUpdateEventListener.class);
 		eventInterfaceFromType.put("pre-delete", PreDeleteEventListener.class);
 		eventInterfaceFromType.put("pre-insert", PreInsertEventListener.class);
+		eventInterfaceFromType.put("pre-collection-recreate", PreCollectionRecreateEventListener.class);
+		eventInterfaceFromType.put("pre-collection-remove", PreCollectionRemoveEventListener.class);
+		eventInterfaceFromType.put("pre-collection-update", PreCollectionUpdateEventListener.class);
 		eventInterfaceFromType.put("post-load", PostLoadEventListener.class);
 		eventInterfaceFromType.put("post-update", PostUpdateEventListener.class);
 		eventInterfaceFromType.put("post-delete", PostDeleteEventListener.class);
@@ -106,6 +116,9 @@
 		eventInterfaceFromType.put("post-commit-update", PostUpdateEventListener.class);
 		eventInterfaceFromType.put("post-commit-delete", PostDeleteEventListener.class);
 		eventInterfaceFromType.put("post-commit-insert", PostInsertEventListener.class);
+		eventInterfaceFromType.put("post-collection-recreate", PostCollectionRecreateEventListener.class);
+		eventInterfaceFromType.put("post-collection-remove", PostCollectionRemoveEventListener.class);
+		eventInterfaceFromType.put("post-collection-update", PostCollectionUpdateEventListener.class);                          
 		eventInterfaceFromType = Collections.unmodifiableMap( eventInterfaceFromType );
 	}
 
@@ -279,6 +292,30 @@
 		this.preLoadEventListeners = preLoadEventListener;
 	}
 
+	public PreCollectionRecreateEventListener[] getPreCollectionRecreateEventListeners() {
+		return preCollectionRecreateEventListeners;
+	}
+
+	public void setPreCollectionRecreateEventListeners(PreCollectionRecreateEventListener[] preCollectionRecreateEventListener) {
+		this.preCollectionRecreateEventListeners = preCollectionRecreateEventListener;
+	}
+
+	public PreCollectionRemoveEventListener[] getPreCollectionRemoveEventListeners() {
+		return preCollectionRemoveEventListeners;
+	}
+
+	public void setPreCollectionRemoveEventListeners(PreCollectionRemoveEventListener[] preCollectionRemoveEventListener) {
+		this.preCollectionRemoveEventListeners = preCollectionRemoveEventListener;
+	}
+
+	public PreCollectionUpdateEventListener[] getPreCollectionUpdateEventListeners() {
+		return preCollectionUpdateEventListeners;
+	}
+
+	public void setPreCollectionUpdateEventListeners(PreCollectionUpdateEventListener[] preCollectionUpdateEventListeners) {
+		this.preCollectionUpdateEventListeners = preCollectionUpdateEventListeners;
+	}
+
 	public PostDeleteEventListener[] getPostDeleteEventListeners() {
 		return postDeleteEventListeners;
 	}
@@ -302,7 +339,31 @@
 	public void setPostUpdateEventListeners(PostUpdateEventListener[] postUpdateEventListener) {
 		this.postUpdateEventListeners = postUpdateEventListener;
 	}
-	
+
+	public PostCollectionRecreateEventListener[] getPostCollectionRecreateEventListeners() {
+		return postCollectionRecreateEventListeners;
+	}
+
+	public void setPostCollectionRecreateEventListeners(PostCollectionRecreateEventListener[] postCollectionRecreateEventListener) {
+		this.postCollectionRecreateEventListeners = postCollectionRecreateEventListener;
+	}
+
+	public PostCollectionRemoveEventListener[] getPostCollectionRemoveEventListeners() {
+		return postCollectionRemoveEventListeners;
+	}
+
+	public void setPostCollectionRemoveEventListeners(PostCollectionRemoveEventListener[] postCollectionRemoveEventListener) {
+		this.postCollectionRemoveEventListeners = postCollectionRemoveEventListener;
+	}
+
+	public PostCollectionUpdateEventListener[] getPostCollectionUpdateEventListeners() {
+		return postCollectionUpdateEventListeners;
+	}
+
+	public void setPostCollectionUpdateEventListeners(PostCollectionUpdateEventListener[] postCollectionUpdateEventListeners) {
+		this.postCollectionUpdateEventListeners = postCollectionUpdateEventListeners;
+	}
+
 	public PreDeleteEventListener[] getPreDeleteEventListeners() {
 		return preDeleteEventListeners;
 	}

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/InitializeCollectionEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/InitializeCollectionEvent.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/InitializeCollectionEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -9,16 +9,13 @@
  * 
  * @author Gavin King
  */
-public class InitializeCollectionEvent extends AbstractEvent {
-	
-	private final PersistentCollection collection;
+public class InitializeCollectionEvent extends AbstractCollectionEvent {
 
-	public InitializeCollectionEvent(PersistentCollection collection, EventSource source) {
-		super(source);
-		this.collection = collection;
+	public InitializeCollectionEvent(PersistentCollection collection, EventSource source ) {
+		super( getLoadedCollectionPersister( collection, source ),
+				collection,
+				source,
+				getLoadedOwnerOrNull( collection, source ),
+				getLoadedOwnerIdOrNull( collection, source ) );
 	}
-	
-	public PersistentCollection getCollection() {
-		return collection;
-	}
 }

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,21 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs after a collection is recreated
+ *
+ * @author Gail Badner
+ */
+public class PostCollectionRecreateEvent extends AbstractCollectionEvent {
+
+	public PostCollectionRecreateEvent( CollectionPersister collectionPersister,
+										PersistentCollection collection,
+										EventSource source ) {
+		super( collectionPersister, collection, source,
+				collection.getOwner(),
+				getOwnerIdOrNull( collection.getOwner(), source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRecreateEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called after recreating a collection
+ *
+ * @author Gail Badner
+ */
+public interface PostCollectionRecreateEventListener extends Serializable {
+	public void onPostRecreateCollection(PostCollectionRecreateEvent event);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,22 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs after a collection is removed
+ *
+ * @author Gail Badner
+ */
+public class PostCollectionRemoveEvent extends AbstractCollectionEvent {
+
+	public PostCollectionRemoveEvent(CollectionPersister collectionPersister,
+									 PersistentCollection collection,
+									 EventSource source,
+									 Object loadedOwner ) {
+		super( collectionPersister, collection, source,
+				loadedOwner,
+				getOwnerIdOrNull( loadedOwner, source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionRemoveEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called after removing a collection
+ *
+ * @author Gail Badner
+ */
+public interface PostCollectionRemoveEventListener extends Serializable {
+	public void onPostRemoveCollection(PostCollectionRemoveEvent event);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,21 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs after a collection is updated
+ *
+ * @author Gail Badner
+ */
+public class PostCollectionUpdateEvent extends AbstractCollectionEvent {
+
+	public PostCollectionUpdateEvent(CollectionPersister collectionPersister,
+									 PersistentCollection collection,
+									 EventSource source) {
+		super( collectionPersister, collection, source,
+				getLoadedOwnerOrNull( collection, source ),
+				getLoadedOwnerIdOrNull( collection, source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PostCollectionUpdateEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called after updating a collection
+ *
+ * @author Gail Badner
+ */
+public interface PostCollectionUpdateEventListener extends Serializable {
+	public void onPostUpdateCollection(PostCollectionUpdateEvent event);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,21 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs before a collection is recreated
+ *
+ * @author Gail Badner
+ */
+public class PreCollectionRecreateEvent extends AbstractCollectionEvent {
+
+	public PreCollectionRecreateEvent(CollectionPersister collectionPersister,
+									  PersistentCollection collection,
+									  EventSource source) {
+		super( collectionPersister, collection, source,
+				collection.getOwner(),
+				getOwnerIdOrNull( collection.getOwner(), source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRecreateEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called before recreating a collection
+ *
+ * @author Gail Badner
+ */
+public interface PreCollectionRecreateEventListener extends Serializable {
+	public void onPreRecreateCollection(PreCollectionRecreateEvent event);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,22 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs before a collection is removed
+ *
+ * @author Gail Badner
+ */
+public class PreCollectionRemoveEvent extends AbstractCollectionEvent {
+
+	public PreCollectionRemoveEvent(CollectionPersister collectionPersister,
+									PersistentCollection collection,
+									EventSource source,
+									Object loadedOwner) {
+		super( collectionPersister, collection, source,
+				loadedOwner,
+				getOwnerIdOrNull( loadedOwner, source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionRemoveEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called before removing a collection
+ *
+ * @author Gail Badner
+ */
+public interface PreCollectionRemoveEventListener extends Serializable {
+	public void onPreRemoveCollection(PreCollectionRemoveEvent event);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEvent.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEvent.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEvent.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,21 @@
+//$Id: $
+package org.hibernate.event;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * An event that occurs before a collection is updated
+ *
+ * @author Gail Badner
+ */
+public class PreCollectionUpdateEvent extends AbstractCollectionEvent {
+
+	public PreCollectionUpdateEvent(CollectionPersister collectionPersister,
+									PersistentCollection collection,
+									EventSource source) {
+		super( collectionPersister, collection, source,
+				getLoadedOwnerOrNull( collection, source ),
+				getLoadedOwnerIdOrNull( collection, source ) );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEventListener.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEventListener.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/PreCollectionUpdateEventListener.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,12 @@
+package org.hibernate.event;
+
+import java.io.Serializable;
+
+/**
+ * Called before updating a collection
+ *
+ * @author Gail Badner
+ */
+public interface PreCollectionUpdateEventListener extends Serializable {
+	public void onPreUpdateCollection(PreCollectionUpdateEvent event);
+}

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/def/ReattachVisitor.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/def/ReattachVisitor.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/event/def/ReattachVisitor.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -79,7 +79,7 @@
 					MessageHelper.collectionInfoString( role, ownerIdentifier, source.getFactory() )
 			);
 		}
-		source.getActionQueue().addAction( new CollectionRemoveAction( null, role, collectionKey, false, source ) );
+		source.getActionQueue().addAction( new CollectionRemoveAction( owner, role, collectionKey, false, source ) );
 	}
 
 	/**

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/hibernate-configuration-3.0.dtd
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/hibernate-configuration-3.0.dtd	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/hibernate-configuration-3.0.dtd	2008-07-09 01:03:32 UTC (rev 14899)
@@ -34,10 +34,10 @@
 <!ATTLIST collection-cache usage (read-only|read-write|nonstrict-read-write|transactional) #REQUIRED>
 
 <!ELEMENT event (listener*)>
-<!ATTLIST event type (auto-flush|merge|create|create-onflush|delete|dirty-check|evict|flush|flush-entity|load|load-collection|lock|refresh|replicate|save-update|save|update|pre-load|pre-update|pre-insert|pre-delete|post-load|post-update|post-insert|post-delete|post-commit-update|post-commit-insert|post-commit-delete) #REQUIRED>
+<!ATTLIST event type (auto-flush|merge|create|create-onflush|delete|dirty-check|evict|flush|flush-entity|load|load-collection|lock|refresh|replicate|save-update|save|update|pre-load|pre-update|pre-insert|pre-delete|pre-collection-recreate|pre-collection-remove|pre-collection-update|post-load|post-update|post-insert|post-delete|post-collection-recreate|post-collection-remove|post-collection-update|post-commit-update|post-commit-insert|post-commit-delete) #REQUIRED>
 
 <!ELEMENT listener EMPTY>
-<!ATTLIST listener type (auto-flush|merge|create|create-onflush|delete|dirty-check|evict|flush|flush-entity|load|load-collection|lock|refresh|replicate|save-update|save|update|pre-load|pre-update|pre-insert|pre-delete|post-load|post-update|post-insert|post-delete|post-commit-update|post-commit-insert|post-commit-delete) #IMPLIED>
+<!ATTLIST listener type (auto-flush|merge|create|create-onflush|delete|dirty-check|evict|flush|flush-entity|load|load-collection|lock|refresh|replicate|save-update|save|update|pre-load|pre-update|pre-insert|pre-delete|pre-collection-recreate|pre-collection-remove|pre-collection-update|post-load|post-update|post-insert|post-delete|post-collection-recreate|post-collection-remove|post-collection-update|post-commit-update|post-commit-insert|post-commit-delete) #IMPLIED>
 <!ATTLIST listener class CDATA #REQUIRED>
 
 <!ELEMENT session-factory (property*, mapping*, (class-cache|collection-cache)*, event*, listener*)>

Modified: core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/type/CollectionType.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/type/CollectionType.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/src/org/hibernate/type/CollectionType.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -26,6 +26,7 @@
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.persister.collection.CollectionPersister;
 import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.persister.entity.Joinable;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.proxy.LazyInitializer;
@@ -343,6 +344,7 @@
 			}
 
 			// NOTE VERY HACKISH WORKAROUND!!
+			// TODO: Fix this so it will work for non-POJO entity mode
 			Type keyType = getPersister( session ).getKeyType();
 			if ( !keyType.getReturnedClass().isInstance( id ) ) {
 				id = (Serializable) keyType.semiResolve(
@@ -356,6 +358,37 @@
 		}
 	}
 
+	/**
+	 * Get the id value from the owning entity key, usually the same as the key, but might be some
+	 * other property, in the case of property-ref
+	 *
+	 * @param key The collection owner key
+	 * @param session The session from which the request is originating.
+	 * @return The collection owner's id, if it can be obtained from the key;
+	 * otherwise, null is returned
+	 */
+	public Serializable getIdOfOwnerOrNull(Serializable key, SessionImplementor session) {
+		Serializable ownerId = null;
+		if ( foreignKeyPropertyName == null ) {
+			ownerId = key;
+		}
+		else {
+			Type keyType = getPersister( session ).getKeyType();
+			EntityPersister ownerPersister = getPersister( session ).getOwnerEntityPersister();
+			// TODO: Fix this so it will work for non-POJO entity mode
+			Class ownerMappedClass = ownerPersister.getMappedClass( session.getEntityMode() );
+			if ( ownerMappedClass.isAssignableFrom( keyType.getReturnedClass() ) &&
+					keyType.getReturnedClass().isInstance( key ) ) {
+				// the key is the owning entity itself, so get the ID from the key
+				ownerId = ownerPersister.getIdentifier( key, session.getEntityMode() );
+			}
+			else {
+				// TODO: check if key contains the owner ID
+			}
+		}
+		return ownerId;
+	}
+
 	public Object hydrate(ResultSet rs, String[] name, SessionImplementor session, Object owner) {
 		// can't just return null here, since that would
 		// cause an owning component to become null

Modified: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/AllTests.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/AllTests.java	2008-07-08 21:37:55 UTC (rev 14898)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/AllTests.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -37,6 +37,7 @@
 import org.hibernate.test.dynamicentity.tuplizer.TuplizerDynamicEntityTest;
 import org.hibernate.test.ecid.EmbeddedCompositeIdTest;
 import org.hibernate.test.entitymode.EntityModeSuite;
+import org.hibernate.test.event.collection.CollectionEventSuite;
 import org.hibernate.test.exception.SQLExceptionConversionTest;
 import org.hibernate.test.extralazy.ExtraLazyTest;
 import org.hibernate.test.filter.DynamicFilterTest;
@@ -259,6 +260,7 @@
 			suite.addTest( WhereTest.suite() );
 			suite.addTest( IterateTest.suite() );
 			suite.addTest( RefreshTest.suite() );
+			suite.addTest( CollectionEventSuite.suite() );
 			suite.addTest( ExtraLazyTest.suite() );
 			suite.addTest( StatsTest.suite() );
 			suite.addTest( SessionStatsTest.suite() );
@@ -438,4 +440,4 @@
 			}
 		}
 	}
-}
\ No newline at end of file
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,783 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.collection.PersistentSet;
+import org.hibernate.event.AbstractCollectionEvent;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractCollectionEventTest extends FunctionalTestCase {
+
+	public AbstractCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public abstract String[] getMappings();
+
+	public abstract ParentWithCollection createParent(String name);
+
+	public abstract Collection createCollection();
+
+	protected void cleanupTest() {
+		ParentWithCollection dummyParent = createParent( "dummyParent" );
+		dummyParent.newChildren( createCollection() );
+		Child dummyChild = dummyParent.addChild( "dummyChild" );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		List children = s.createCriteria( dummyChild.getClass() ).list();
+		List parents = s.createCriteria( dummyParent.getClass() ).list();
+		for ( Iterator it = parents.iterator(); it.hasNext(); ) {
+			ParentWithCollection parent = ( ParentWithCollection ) it.next();
+			parent.clearChildren();
+			s.delete( parent );
+		}
+		for ( Iterator it = children.iterator(); it.hasNext(); ) {
+			s.delete( it.next() );
+		}
+		tx.commit();
+		s.close();
+	}
+
+	public void testSaveParentEmptyChildren() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		assertEquals( 0, parent.getChildren().size() );
+		int index = 0;
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		tx.commit();
+		s.close();
+		assertNotNull( parent.getChildren() );
+		checkNumberOfResults( listeners, 0 );
+	}
+
+	public void testSaveParentOneChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		int index = 0;
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentNullToOneChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNullChildren( "parent" );
+		listeners.clear();
+		assertNull( parent.getChildren() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		assertNotNull( parent.getChildren() );
+		Child newChild = parent.addChild( "new" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( newChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentNoneToOneChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		listeners.clear();
+		assertEquals( 0, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		Child newChild = parent.addChild( "new" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( newChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneToTwoChildren() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		assertEquals( 1, parent.getChildren().size() );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		Child newChild = parent.addChild( "new2" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( newChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneToTwoSameChildren() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		assertEquals( 1, parent.getChildren().size() );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		parent.addChild( child );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		ChildWithBidirectionalManyToMany childWithManyToMany = null;
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			childWithManyToMany = ( ChildWithBidirectionalManyToMany ) child;
+			if ( ( ( PersistentCollection ) childWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), childWithManyToMany, index++ );
+			}
+		}
+		if ( !( parent.getChildren() instanceof PersistentSet ) ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		}
+		if ( childWithManyToMany != null && !( childWithManyToMany.getParents() instanceof PersistentSet ) ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), childWithManyToMany, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), childWithManyToMany, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentNullToOneChildDiffCollection() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNullChildren( "parent" );
+		listeners.clear();
+		assertNull( parent.getChildren() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		Collection collectionOrig = parent.getChildren();
+		parent.newChildren( createCollection() );
+		Child newChild = parent.addChild( "new" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) collectionOrig ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, collectionOrig, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, collectionOrig, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, collectionOrig, index++ );
+		if ( newChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentNoneToOneChildDiffCollection() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		listeners.clear();
+		assertEquals( 0, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( createCollection() );
+		Child newChild = parent.addChild( "new" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) oldCollection ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, oldCollection, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( newChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneChildDiffCollectionSameChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		assertEquals( 1, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child).getId() );
+		}
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( createCollection() );
+		parent.addChild( child );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) oldCollection ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, oldCollection, index++ );
+		}
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			ChildWithBidirectionalManyToMany childWithManyToMany = ( ChildWithBidirectionalManyToMany ) child;
+			if ( ( ( PersistentCollection ) childWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), childWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			// hmmm, the same parent was removed and re-added to the child's collection;
+			// should this be considered an update?
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneChildDiffCollectionDiffChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child oldChild = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		assertEquals( 1, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( oldChild instanceof Entity ) {
+			oldChild = ( Child ) s.get( oldChild.getClass(), ( ( Entity ) oldChild).getId() );
+		}
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( createCollection() );
+		Child newChild = parent.addChild( "new1" );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) oldCollection ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, oldCollection, index++ );
+		}
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			ChildWithBidirectionalManyToMany oldChildWithManyToMany = ( ChildWithBidirectionalManyToMany ) oldChild;
+			if ( ( ( PersistentCollection ) oldChildWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), oldChildWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+			checkResult( listeners, listeners.getPreCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionRecreateListener(), ( ChildWithBidirectionalManyToMany ) newChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneChildToNoneByRemove() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		assertEquals( 1, parent.getChildren().size() );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		parent.removeChild( child );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			ChildWithBidirectionalManyToMany childWithManyToMany = ( ChildWithBidirectionalManyToMany ) child;
+			if ( ( ( PersistentCollection ) childWithManyToMany.getParents( ) ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), childWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentOneChildToNoneByClear() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		assertEquals( 1, parent.getChildren().size() );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		parent.clearChildren();
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			ChildWithBidirectionalManyToMany childWithManyToMany = ( ChildWithBidirectionalManyToMany ) child;
+			if ( ( ( PersistentCollection ) childWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), childWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateParentTwoChildrenToOne() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		assertEquals( 1, parent.getChildren().size() );
+		Child oldChild = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		parent.addChild( "new" );
+		tx.commit();
+		s.close();
+		listeners.clear();
+		s = openSession();
+		tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( oldChild instanceof Entity ) {
+			oldChild = ( Child ) s.get( oldChild.getClass(), ( ( Entity ) oldChild ).getId() );
+		}
+		parent.removeChild( oldChild );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			ChildWithBidirectionalManyToMany oldChildWithManyToMany = ( ChildWithBidirectionalManyToMany ) oldChild;
+			if ( ( ( PersistentCollection ) oldChildWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), oldChildWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testDeleteParentWithNullChildren() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNullChildren( "parent" );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		s.delete( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testDeleteParentWithNoChildren() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		s.delete( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testDeleteParentAndChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		parent.removeChild( child );
+		if ( child instanceof Entity ) {
+			s.delete( child );
+		}
+		s.delete( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionRemoveListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionRemoveListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testMoveChildToDifferentParent() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		ParentWithCollection otherParent = createParentWithOneChild( "otherParent", "otherChild" );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		otherParent = ( ParentWithCollection ) s.get( otherParent.getClass(), otherParent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		parent.removeChild( child );
+		otherParent.addChild( child );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		if ( ( ( PersistentCollection ) otherParent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), otherParent, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), otherParent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), otherParent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testMoveAllChildrenToDifferentParent() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		ParentWithCollection otherParent = createParentWithOneChild( "otherParent", "otherChild" );
+		Child child = ( Child ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		otherParent = ( ParentWithCollection ) s.get( otherParent.getClass(), otherParent.getId() );
+		if ( child instanceof Entity ) {
+			child = ( Child ) s.get( child.getClass(), ( ( Entity ) child ).getId() );
+		}
+		otherParent.addAllChildren( parent.getChildren() );
+		parent.clearChildren();
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) parent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		}
+		if ( ( ( PersistentCollection ) otherParent.getChildren() ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), otherParent, index++ );
+		}
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPreCollectionUpdateListener(), otherParent, index++ );
+		checkResult( listeners, listeners.getPostCollectionUpdateListener(), otherParent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testMoveCollectionToDifferentParent() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		ParentWithCollection otherParent = createParentWithOneChild( "otherParent", "otherChild" );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		otherParent = ( ParentWithCollection ) s.get( otherParent.getClass(), otherParent.getId() );
+		Collection otherCollectionOrig = otherParent.getChildren();
+		otherParent.newChildren( parent.getChildren() );
+		parent.newChildren( null );
+		tx.commit();
+		s.close();
+		int index = 0;
+		Child otherChildOrig = null;
+		if ( ( ( PersistentCollection ) otherCollectionOrig ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), otherParent, otherCollectionOrig, index++ );
+			otherChildOrig = ( Child ) otherCollectionOrig.iterator().next();
+			if ( otherChildOrig instanceof ChildWithBidirectionalManyToMany ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, otherParent.getChildren(), index++ );
+		Child otherChild = ( Child ) otherParent.getChildren().iterator().next();
+		if ( otherChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) otherChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, otherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, otherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), otherParent, otherCollectionOrig, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), otherParent, otherCollectionOrig, index++ );
+		if ( otherChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), otherParent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), otherParent, index++ );
+		// there should also be pre- and post-recreate collection events for parent, but thats broken now;
+		// this is covered in BrokenCollectionEventTest
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testMoveCollectionToDifferentParentFlushMoveToDifferentParent() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		ParentWithCollection otherParent = createParentWithOneChild( "otherParent", "otherChild" );
+		ParentWithCollection otherOtherParent = createParentWithNoChildren( "otherParent" );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		otherParent = ( ParentWithCollection ) s.get( otherParent.getClass(), otherParent.getId() );
+		otherOtherParent = ( ParentWithCollection ) s.get( otherOtherParent.getClass(), otherOtherParent.getId() );
+		Collection otherCollectionOrig = otherParent.getChildren();
+		Collection otherOtherCollectionOrig = otherOtherParent.getChildren();
+		otherParent.newChildren( parent.getChildren() );
+		parent.newChildren( null );
+		s.flush();
+		otherOtherParent.newChildren( otherParent.getChildren() );
+		otherParent.newChildren( null );
+		tx.commit();
+		s.close();
+		int index = 0;
+		Child otherChildOrig = null;
+		if ( ( ( PersistentCollection ) otherCollectionOrig ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), otherParent, otherCollectionOrig, index++ );
+			otherChildOrig = ( Child ) otherCollectionOrig.iterator().next();
+			if ( otherChildOrig instanceof ChildWithBidirectionalManyToMany ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, otherOtherParent.getChildren(), index++ );
+		Child otherOtherChild = ( Child ) otherOtherParent.getChildren().iterator().next();
+		if ( otherOtherChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) otherOtherChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, otherOtherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, otherOtherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), otherParent, otherCollectionOrig, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), otherParent, otherCollectionOrig, index++ );
+		if ( otherOtherChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherChildOrig, index++ );
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherOtherChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherOtherChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), otherParent, otherOtherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), otherParent, otherOtherParent.getChildren(), index++ );
+		if ( ( ( PersistentCollection ) otherOtherCollectionOrig ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), otherOtherParent, otherOtherCollectionOrig, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), otherParent, otherOtherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), otherParent, otherOtherParent.getChildren(), index++ );
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), otherOtherParent, otherOtherCollectionOrig, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), otherOtherParent, otherOtherCollectionOrig, index++ );
+		if ( otherOtherChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherOtherChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) otherOtherChild, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), otherOtherParent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), otherOtherParent, index++ );
+		// there should also be pre- and post-recreate collection events for parent, and otherParent
+		// but thats broken now; this is covered in BrokenCollectionEventTest
+		checkNumberOfResults( listeners, index );
+	}
+
+	protected ParentWithCollection createParentWithNullChildren(String parentName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	protected ParentWithCollection createParentWithNoChildren(String parentName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		parent.newChildren( createCollection() );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	protected ParentWithCollection createParentWithOneChild(String parentName, String ChildName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		parent.newChildren( createCollection() );
+		parent.addChild( ChildName );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 ParentWithCollection parent,
+							 int index) {
+		checkResult( listeners, listenerExpected, parent, parent.getChildren(), index );
+	}
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 ChildWithBidirectionalManyToMany child,
+							 int index) {
+		checkResult( listeners, listenerExpected, child, child.getParents(), index );
+	}
+
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 Entity ownerExpected,
+							 Collection collExpected,
+							 int index) {
+		assertSame( listenerExpected, listeners.getListenersCalled().get( index ) );
+		assertSame(
+				ownerExpected,
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerOrNull()
+		);
+		assertEquals(
+				ownerExpected.getId(),
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerIdOrNull()
+		);
+		assertEquals(
+				ownerExpected.getClass().getName(),
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerEntityName()
+		);
+		assertSame(
+				collExpected, ( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getCollection()
+		);
+	}
+
+	protected void checkNumberOfResults(CollectionListeners listeners, int nEventsExpected) {
+		assertEquals( nEventsExpected, listeners.getListenersCalled().size() );
+		assertEquals( nEventsExpected, listeners.getEvents().size() );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractParentWithCollection.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractParentWithCollection.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/AbstractParentWithCollection.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,100 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import java.util.Collection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractParentWithCollection implements ParentWithCollection {
+	private Long id;
+	private String name;
+	           
+	private Collection children;
+
+	public AbstractParentWithCollection() {
+	}
+
+	public AbstractParentWithCollection(String name) {
+		this.name = name;
+	}
+
+	public void newChildren(Collection collection) {
+		setChildren( collection );
+	}
+
+	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 getChildren() {
+		return children;
+	}
+
+	public void setChildren(Collection children) {
+		this.children = children;
+	}
+
+	public Child addChild(String name) {
+		Child child = createChild( name );
+		addChild( child );
+		return child;
+	}
+
+	public void addChild(Child child) {
+		if ( child != null ) {
+			children.add( child );
+		}
+	}
+
+	public void addAllChildren(Collection children) {
+		this.children.addAll( children );
+	}
+
+	public void removeChild(Child child) {
+		children.remove( child );
+	}
+
+	public void removeAllChildren(Collection children) {
+		children.removeAll( children );
+	}
+
+	public void clearChildren() {
+		if ( children != null && !children.isEmpty() ) {
+			this.children.clear();
+		}
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/BrokenCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/BrokenCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/BrokenCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,333 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.Test;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.event.AbstractCollectionEvent;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany;
+import org.hibernate.test.event.collection.association.unidirectional.ParentWithCollectionOfEntities;
+
+/**
+ *
+ * @author Gail Badner
+ *
+ * These tests are known to fail. When the functionality is corrected, the
+ * corresponding method will be moved into AbstractCollectionEventTest.
+ */
+public class BrokenCollectionEventTest extends FunctionalTestCase {
+
+	public BrokenCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BrokenCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithCollectionOfEntities( name );
+	}
+
+	public Collection createCollection() {
+		return new HashSet();
+	}
+
+	protected void cleanupTest() {
+		ParentWithCollection dummyParent = createParent( "dummyParent" );
+		dummyParent.setChildren( createCollection() );
+		Child dummyChild = dummyParent.addChild( "dummyChild" );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		List children = s.createCriteria( dummyChild.getClass() ).list();
+		List parents = s.createCriteria( dummyParent.getClass() ).list();
+		for ( Iterator it = parents.iterator(); it.hasNext(); ) {
+			ParentWithCollection parent = ( ParentWithCollection ) it.next();
+			parent.clearChildren();
+			s.delete( parent );
+		}
+		for ( Iterator it = children.iterator(); it.hasNext(); ) {
+			s.delete( it.next() );
+		}
+		tx.commit();
+		s.close();
+	}
+
+	public void testUpdateDetachedParentNoChildrenToNullFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		listeners.clear();
+		assertEquals( 0, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( null );
+		s.update( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		// pre- and post- collection recreate events should be created when updating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	// The following fails for the same reason as testUpdateDetachedParentNoChildrenToNullFailureExpected
+	// When that issue is fixed, this one should also be fixed and moved into AbstractCollectionEventTest.
+	/*
+	public void testUpdateDetachedParentOneChildToNullFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child oldChild = ( Child ) parent.getChildren().iterator().next();
+		assertEquals( 1, parent.getChildren().size() );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( null );
+		s.update( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) oldChild, index++ );
+		}
+		// pre- and post- collection recreate events should be created when updating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+	*/
+
+	public void testSaveParentNullChildrenFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNullChildren( "parent" );
+		assertNull( parent.getChildren() );
+		int index = 0;
+		// pre- and post- collection recreate events should be created when creating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		tx.commit();
+		s.close();
+		assertNotNull( parent.getChildren() );
+		checkNumberOfResults( listeners, 0 );
+	}
+
+	public void testUpdateParentNoChildrenToNullFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithNoChildren( "parent" );
+		listeners.clear();
+		assertEquals( 0, parent.getChildren().size() );
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( null );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) oldCollection ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, oldCollection, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		// pre- and post- collection recreate events should be created when updating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+
+	// The following two tests fail for the same reason as testUpdateParentNoChildrenToNullFailureExpected
+	// When that issue is fixed, this one should also be fixed and moved into AbstractCollectionEventTest.
+	/*
+	public void testUpdateParentOneChildToNullFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		Child oldChild = ( Child ) parent.getChildren().iterator().next();
+		assertEquals( 1, parent.getChildren().size() );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( AbstractParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		if ( oldChild instanceof ChildEntity ) {
+			oldChild = ( Child ) s.get( oldChild.getClass(), ( ( ChildEntity ) oldChild ).getId() );
+		}
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( null );
+		tx.commit();
+		s.close();
+		int index = 0;
+		if ( ( ( PersistentCollection ) oldCollection ).wasInitialized() ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), parent, oldCollection, index++ );
+		}
+		ChildWithBidirectionalManyToMany oldChildWithManyToMany = null;
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			oldChildWithManyToMany = ( ChildWithBidirectionalManyToMany ) oldChild;
+			if ( ( ( PersistentCollection ) oldChildWithManyToMany.getParents() ).wasInitialized() ) {
+				checkResult( listeners, listeners.getInitializeCollectionListener(), oldChildWithManyToMany, index++ );
+			}
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( oldChildWithManyToMany != null ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), oldChildWithManyToMany, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), oldChildWithManyToMany, index++ );
+		}
+		// pre- and post- collection recreate events should be created when updating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}
+
+	public void testUpdateMergedParentOneChildToNullFailureExpected() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		assertEquals( 1, parent.getChildren().size() );
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( AbstractParentWithCollection ) s.merge( parent );
+		Collection oldCollection = parent.getChildren();
+		parent.newChildren( null );
+		tx.commit();
+		s.close();
+		int index = 0;
+		Child oldChild = ( Child ) oldCollection.iterator().next();
+		ChildWithBidirectionalManyToMany oldChildWithManyToMany = null;
+		if ( oldChild instanceof ChildWithBidirectionalManyToMany ) {
+			oldChildWithManyToMany = ( ChildWithBidirectionalManyToMany ) oldChild;
+			if ( ( ( PersistentCollection ) oldChildWithManyToMany.getParents() ).wasInitialized() ) {
+		}
+			checkResult( listeners, listeners.getInitializeCollectionListener(), oldChildWithManyToMany, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, oldCollection, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, oldCollection, index++ );
+		if ( oldChildWithManyToMany != null ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), oldChildWithManyToMany, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), oldChildWithManyToMany, index++ );
+		}
+		// pre- and post- collection recreate events should be created when updating an entity with a "null" collection
+		checkResult( listeners, listeners.getPreCollectionRecreateListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRecreateListener(), parent, index++ );
+		checkNumberOfResults( listeners, index );
+	}	
+	*/
+
+	private ParentWithCollection createParentWithNullChildren(String parentName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	private ParentWithCollection createParentWithNoChildren(String parentName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		parent.setChildren( createCollection() );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	private ParentWithCollection createParentWithOneChild(String parentName, String ChildName) {
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		ParentWithCollection parent = createParent( parentName );
+		parent.setChildren( createCollection() );
+		parent.addChild( ChildName );
+		s.save( parent );
+		tx.commit();
+		s.close();
+		return parent;
+	}
+
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 ParentWithCollection parent,
+							 int index) {
+		checkResult( listeners, listenerExpected, parent, parent.getChildren(), index );
+	}
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 ChildWithBidirectionalManyToMany child,
+							 int index) {
+		checkResult( listeners, listenerExpected, child, child.getParents(), index );
+	}
+
+	protected void checkResult(CollectionListeners listeners,
+							 CollectionListeners.Listener listenerExpected,
+							 Entity ownerExpected,
+							 Collection collExpected,
+							 int index) {
+		assertSame( listenerExpected, listeners.getListenersCalled().get( index ) );
+		assertSame(
+				ownerExpected,
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerOrNull()
+		);
+		assertEquals(
+				ownerExpected.getId(),
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerIdOrNull()
+		);
+		assertEquals(
+				ownerExpected.getClass().getName(),
+				( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getAffectedOwnerEntityName()
+		);
+		assertSame(
+				collExpected, ( ( AbstractCollectionEvent ) listeners.getEvents().get( index ) ).getCollection()
+		);
+	}
+
+	private void checkNumberOfResults(CollectionListeners listeners, int nEventsExpected) {
+		assertEquals( nEventsExpected, listeners.getListenersCalled().size() );
+		assertEquals( nEventsExpected, listeners.getEvents().size() );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Child.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Child.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Child.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,33 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public interface Child {
+
+	String getName();
+
+	void setName(String name);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildEntity.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildEntity.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildEntity.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,47 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ChildEntity extends ChildValue implements Entity {
+	private Long id;
+
+	public ChildEntity() {
+		super();
+	}
+
+	public ChildEntity(String name) {
+		super( name );
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildValue.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildValue.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ChildValue.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ChildValue implements Child {
+	private String name;
+
+	public ChildValue() {
+	}
+
+	public ChildValue(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public boolean equals(Object otherChild) {
+		if ( this == otherChild ) {
+			return true;
+		}
+		if ( !( otherChild instanceof ChildValue ) ) {
+			return false;
+		}
+		return name.equals( ( ( ChildValue ) otherChild ).name );
+	}
+
+	public int hashCode() {
+		return name.hashCode();
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionEventSuite.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionEventSuite.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionEventSuite.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.BidirectionalManyToManyBagToSetCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.BidirectionalManyToManySetToSetCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.BidirectionalOneToManyBagCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.BidirectionalOneToManySetCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.manytomany.UnidirectionalManyToManyBagCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.onetomany.UnidirectionalOneToManyBagCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.onetomany.UnidirectionalOneToManySetCollectionEventTest;
+import org.hibernate.test.event.collection.values.ValuesBagCollectionEventTest;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class CollectionEventSuite {
+	public static Test suite() {
+		TestSuite suite = new TestSuite( "Collection event test suite" );
+		suite.addTest( BrokenCollectionEventTest.suite() );
+		suite.addTest( BidirectionalManyToManyBagToSetCollectionEventTest.suite() );
+		suite.addTest( BidirectionalManyToManySetToSetCollectionEventTest.suite() );
+		suite.addTest( BidirectionalOneToManyBagCollectionEventTest.suite() );
+		suite.addTest( BidirectionalOneToManySetCollectionEventTest.suite() );
+		suite.addTest( UnidirectionalManyToManyBagCollectionEventTest.suite() );
+		suite.addTest( UnidirectionalOneToManyBagCollectionEventTest.suite() );
+		suite.addTest( UnidirectionalOneToManySetCollectionEventTest.suite() );
+		suite.addTest( ValuesBagCollectionEventTest.suite() );
+		return suite;
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionListeners.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionListeners.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/CollectionListeners.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,214 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.event.AbstractCollectionEvent;
+import org.hibernate.event.InitializeCollectionEvent;
+import org.hibernate.event.InitializeCollectionEventListener;
+import org.hibernate.event.PostCollectionRecreateEvent;
+import org.hibernate.event.PostCollectionRecreateEventListener;
+import org.hibernate.event.PostCollectionRemoveEvent;
+import org.hibernate.event.PostCollectionRemoveEventListener;
+import org.hibernate.event.PostCollectionUpdateEvent;
+import org.hibernate.event.PostCollectionUpdateEventListener;
+import org.hibernate.event.PreCollectionRecreateEvent;
+import org.hibernate.event.PreCollectionRecreateEventListener;
+import org.hibernate.event.PreCollectionRemoveEvent;
+import org.hibernate.event.PreCollectionRemoveEventListener;
+import org.hibernate.event.PreCollectionUpdateEvent;
+import org.hibernate.event.PreCollectionUpdateEventListener;
+import org.hibernate.event.def.DefaultInitializeCollectionEventListener;
+import org.hibernate.impl.SessionFactoryImpl;
+
+/**
+ * Author: Gail Badner
+ */
+public class CollectionListeners {
+
+
+	public interface Listener extends Serializable {
+		void addEvent(AbstractCollectionEvent event, Listener listener);
+	}
+
+	public static abstract class AbstractListener implements Listener {
+
+		private final CollectionListeners listeners;
+
+		protected AbstractListener( CollectionListeners listeners ) {
+			this.listeners = listeners;
+		}
+
+		public void addEvent(AbstractCollectionEvent event, Listener listener) {
+			listeners.addEvent( event, listener );
+		}
+	}
+
+	public static class InitializeCollectionListener
+			extends DefaultInitializeCollectionEventListener
+			implements Listener {
+		private final CollectionListeners listeners;
+		private InitializeCollectionListener(CollectionListeners listeners) {
+			this.listeners = listeners;
+		}
+		public void onInitializeCollection(InitializeCollectionEvent event) {
+			super.onInitializeCollection( event );
+			addEvent( event, this );
+		}
+		public void addEvent(AbstractCollectionEvent event, Listener listener) {
+			listeners.addEvent( event, listener );
+		}
+	}
+
+	public static class PreCollectionRecreateListener extends AbstractListener
+			implements PreCollectionRecreateEventListener {
+		private PreCollectionRecreateListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPreRecreateCollection(PreCollectionRecreateEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	public static class PostCollectionRecreateListener extends AbstractListener
+			implements PostCollectionRecreateEventListener {
+		private PostCollectionRecreateListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	public static class PreCollectionRemoveListener extends AbstractListener
+			implements PreCollectionRemoveEventListener {
+		private PreCollectionRemoveListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	public static class PostCollectionRemoveListener extends AbstractListener
+			implements PostCollectionRemoveEventListener {
+		private PostCollectionRemoveListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	public static class PreCollectionUpdateListener extends AbstractListener
+			implements PreCollectionUpdateEventListener {
+		private PreCollectionUpdateListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	public static class PostCollectionUpdateListener extends AbstractListener
+			implements PostCollectionUpdateEventListener {
+		private PostCollectionUpdateListener(CollectionListeners listeners) {
+			super( listeners );
+		}
+		public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
+			addEvent( event, this );
+		}
+	}
+
+	private final PreCollectionRecreateListener preCollectionRecreateListener;
+	private final InitializeCollectionListener initializeCollectionListener;
+	private final PreCollectionRemoveListener preCollectionRemoveListener;
+	private final PreCollectionUpdateListener preCollectionUpdateListener;
+	private final PostCollectionRecreateListener postCollectionRecreateListener;
+	private final PostCollectionRemoveListener postCollectionRemoveListener;
+	private final PostCollectionUpdateListener postCollectionUpdateListener;
+
+	private List listenersCalled = new ArrayList();
+	private List events = new ArrayList();
+
+	public CollectionListeners( SessionFactory sf) {
+		preCollectionRecreateListener = new PreCollectionRecreateListener( this );
+		initializeCollectionListener = new InitializeCollectionListener( this );
+		preCollectionRemoveListener = new PreCollectionRemoveListener( this );
+		preCollectionUpdateListener = new PreCollectionUpdateListener( this );
+		postCollectionRecreateListener = new PostCollectionRecreateListener( this );
+		postCollectionRemoveListener = new PostCollectionRemoveListener( this );
+		postCollectionUpdateListener = new PostCollectionUpdateListener( this );
+		SessionFactoryImpl impl = ( SessionFactoryImpl ) sf;
+		impl.getEventListeners().setInitializeCollectionEventListeners(
+				new InitializeCollectionEventListener[] { initializeCollectionListener }
+		);
+		impl.getEventListeners().setPreCollectionRecreateEventListeners(
+				new PreCollectionRecreateEventListener[] { preCollectionRecreateListener }
+		);
+		impl.getEventListeners().setPostCollectionRecreateEventListeners(
+				new PostCollectionRecreateEventListener[] { postCollectionRecreateListener }
+		);
+		impl.getEventListeners().setPreCollectionRemoveEventListeners(
+				new PreCollectionRemoveEventListener[] { preCollectionRemoveListener }
+		);
+		impl.getEventListeners().setPostCollectionRemoveEventListeners(
+				new PostCollectionRemoveEventListener[] { postCollectionRemoveListener }
+		);
+		impl.getEventListeners().setPreCollectionUpdateEventListeners(
+				new PreCollectionUpdateEventListener[] { preCollectionUpdateListener }
+		);
+		impl.getEventListeners().setPostCollectionUpdateEventListeners(
+				new PostCollectionUpdateEventListener[] { postCollectionUpdateListener }
+		);
+	}
+
+	public void addEvent(AbstractCollectionEvent event, Listener listener) {
+		listenersCalled.add( listener );
+		events.add( event );
+	}
+
+	public List getListenersCalled() {
+		return listenersCalled;
+	}
+
+	public List getEvents() {
+		return events;
+	}
+
+	public void clear() {
+		listenersCalled.clear();
+		events.clear();
+	}
+
+	public PreCollectionRecreateListener getPreCollectionRecreateListener() { return preCollectionRecreateListener; }
+	public InitializeCollectionListener getInitializeCollectionListener() { return initializeCollectionListener; }
+	public PreCollectionRemoveListener getPreCollectionRemoveListener() { return preCollectionRemoveListener; }
+	public PreCollectionUpdateListener getPreCollectionUpdateListener() { return preCollectionUpdateListener; }
+	public PostCollectionRecreateListener getPostCollectionRecreateListener() { return postCollectionRecreateListener; }
+	public PostCollectionRemoveListener getPostCollectionRemoveListener() { return postCollectionRemoveListener; }
+	public PostCollectionUpdateListener getPostCollectionUpdateListener() { return postCollectionUpdateListener; }
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Entity.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Entity.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/Entity.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,14 @@
+package org.hibernate.test.event.collection;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: gbadner
+ * Date: Jan 30, 2008
+ * Time: 2:39:37 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface Entity {
+	Long getId();
+
+	void setId(Long id);
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ParentWithCollection.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ParentWithCollection.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/ParentWithCollection.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,58 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection;
+
+import java.util.Collection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public interface ParentWithCollection extends Entity {
+	void newChildren(Collection collection);
+
+	Child createChild(String name);
+
+	Long getId();
+
+	void setId(Long id);
+
+	String getName();
+
+	void setName(String name);
+
+	Collection getChildren();
+
+	void setChildren(Collection children);
+
+	Child addChild(String name);
+
+	void addChild(Child child);
+
+	void addAllChildren(Collection children);
+
+	void removeChild(Child child);
+
+	void removeAllChildren(Collection children);
+
+	void clearChildren();
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/AbstractAssociationCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/AbstractAssociationCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/AbstractAssociationCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,67 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.test.event.collection.AbstractCollectionEventTest;
+import org.hibernate.test.event.collection.ChildEntity;
+import org.hibernate.test.event.collection.CollectionListeners;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractAssociationCollectionEventTest extends AbstractCollectionEventTest {
+	public AbstractAssociationCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public void testDeleteParentButNotChild() {
+		CollectionListeners listeners = new CollectionListeners( getSessions() );
+		ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
+		ChildEntity child = ( ChildEntity ) parent.getChildren().iterator().next();
+		listeners.clear();
+		Session s = openSession();
+		Transaction tx = s.beginTransaction();
+		parent = ( ParentWithCollection ) s.get( parent.getClass(), parent.getId() );
+		child = ( ChildEntity ) s.get( child.getClass(), child.getId() );
+		parent.removeChild( child );
+		s.delete( parent );
+		tx.commit();
+		s.close();
+		int index = 0;
+		checkResult( listeners, listeners.getInitializeCollectionListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getInitializeCollectionListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkResult( listeners, listeners.getPreCollectionRemoveListener(), parent, index++ );
+		checkResult( listeners, listeners.getPostCollectionRemoveListener(), parent, index++ );
+		if ( child instanceof ChildWithBidirectionalManyToMany ) {
+			checkResult( listeners, listeners.getPreCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+			checkResult( listeners, listeners.getPostCollectionUpdateListener(), ( ChildWithBidirectionalManyToMany ) child, index++ );
+		}
+		checkNumberOfResults( listeners, index );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.manytomany;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.ParentWithBidirectionalManyToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class BidirectionalManyToManyBagToSetCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public BidirectionalManyToManyBagToSetCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BidirectionalManyToManyBagToSetCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithBidirectionalManyToMany( name );
+	}
+
+	public Collection createCollection() {
+		return new ArrayList();
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManyBagToSetMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.bidirectional.manytomany">
+
+    <class name="ParentWithBidirectionalManyToMany" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <bag name="children" table="PARENT_CHILD"
+             inverse="false" cascade="all">
+            <key column="parent_id"/>
+            <many-to-many column="child_id" class="ChildWithBidirectionalManyToMany"/>
+        </bag>
+    </class>
+
+    <class name="ChildWithBidirectionalManyToMany" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+        <set name="parents" table="PARENT_CHILD"
+             inverse="true">
+            <key column="child_id"/>
+            <many-to-many column="parent_id" class="ParentWithBidirectionalManyToMany"/>
+        </set>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.manytomany;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.manytomany.ParentWithBidirectionalManyToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class BidirectionalManyToManySetToSetCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public BidirectionalManyToManySetToSetCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BidirectionalManyToManySetToSetCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithBidirectionalManyToMany( name );
+	}
+
+	public Collection createCollection() {
+		return new HashSet();
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/BidirectionalManyToManySetToSetMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.bidirectional.manytomany">
+
+    <class name="ParentWithBidirectionalManyToMany" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <set name="children" table="PARENT_CHILD"
+             inverse="false" cascade="all">
+            <key column="parent_id"/>
+            <many-to-many column="child_id" class="ChildWithBidirectionalManyToMany"/>
+        </set>
+    </class>
+
+    <class name="ChildWithBidirectionalManyToMany" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+        <set name="parents" table="PARENT_CHILD"
+             inverse="true">
+            <key column="child_id"/>
+            <many-to-many column="parent_id" class="ParentWithBidirectionalManyToMany"/>
+        </set>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ChildWithBidirectionalManyToMany.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ChildWithBidirectionalManyToMany.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ChildWithBidirectionalManyToMany.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,62 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.manytomany;
+
+import java.util.Collection;
+
+import org.hibernate.test.event.collection.ChildEntity;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ChildWithBidirectionalManyToMany extends ChildEntity {
+	private Collection parents;
+
+	public ChildWithBidirectionalManyToMany() {
+	}
+
+	public ChildWithBidirectionalManyToMany(String name, Collection parents) {
+		super( name );
+		this.parents = parents;
+	}
+
+	public Collection getParents() {
+		return parents;
+	}
+
+	public void setParents(Collection parents) {
+		this.parents = parents;
+	}
+
+	public void addParent(ParentWithBidirectionalManyToMany parent) {
+		if ( parent != null ) {
+			parents.add( parent );
+		}
+	}
+
+	public void removeParent(ParentWithBidirectionalManyToMany parent) {
+		if ( parent != null ) {
+			parents.remove( parent );
+		}
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ParentWithBidirectionalManyToMany.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ParentWithBidirectionalManyToMany.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/manytomany/ParentWithBidirectionalManyToMany.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,105 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.manytomany;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.AbstractParentWithCollection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ParentWithBidirectionalManyToMany extends AbstractParentWithCollection {
+	public ParentWithBidirectionalManyToMany() {
+	}
+
+	public ParentWithBidirectionalManyToMany(String name) {
+		super( name );
+	}
+
+	public void newChildren(Collection children) {
+		if ( children == getChildren() ) {
+			return;
+		}
+		if ( getChildren() != null ) {
+			for ( Iterator it = getChildren().iterator(); it.hasNext(); ) {
+				ChildWithBidirectionalManyToMany child = ( ChildWithBidirectionalManyToMany ) it.next();
+				child.removeParent( this );
+			}
+		}
+		if ( children != null ) {
+			for ( Iterator it = children.iterator(); it.hasNext(); ) {
+				ChildWithBidirectionalManyToMany child = ( ChildWithBidirectionalManyToMany ) it.next();
+				child.addParent( this );
+			}
+		}
+		super.newChildren( children );
+	}
+
+	public Child createChild(String name) {
+		return new ChildWithBidirectionalManyToMany( name, new HashSet() );
+	}
+
+	public void addChild(Child child) {
+		super.addChild( child );
+		( ( ChildWithBidirectionalManyToMany ) child ).addParent( this );
+	}
+
+	public void addAllChildren(Collection children) {
+		super.addAllChildren( children );
+		for ( Iterator it = children.iterator(); it.hasNext(); ) {
+			ChildWithBidirectionalManyToMany child = ( ChildWithBidirectionalManyToMany ) it.next();
+			child.addParent( this );
+		}
+	}
+
+	public void removeChild(Child child) {
+		// Note: if the collection is a bag, the same child can be in the collection more than once
+		super.removeChild( child );
+		// only remove the parent from the child's set if child is no longer in the collection
+		if ( ! getChildren().contains( child ) ) {
+			( ( ChildWithBidirectionalManyToMany ) child ).removeParent( this );
+		}
+	}
+
+	public void removeAllChildren(Collection children) {
+		super.removeAllChildren( children );
+		for ( Iterator it = children.iterator(); it.hasNext(); ) {
+			ChildWithBidirectionalManyToMany child = ( ChildWithBidirectionalManyToMany ) it.next();
+			child.removeParent( this );
+		}
+	}
+
+	public void clearChildren() {
+		if ( getChildren() != null ) {
+			for ( Iterator it = getChildren().iterator(); it.hasNext(); ) {
+				ChildWithBidirectionalManyToMany child = ( ChildWithBidirectionalManyToMany ) it.next();
+				child.removeParent( this );
+			}
+		}
+		super.clearChildren();
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ChildWithManyToOne;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ParentWithBidirectionalOneToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class BidirectionalOneToManyBagCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public BidirectionalOneToManyBagCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BidirectionalOneToManyBagCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithBidirectionalOneToMany( name );
+	}
+
+	public Collection createCollection() {
+		return new ArrayList();
+	}
+
+	public Child createChild(String name) {
+		return new ChildWithManyToOne( name );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.bidirectional.onetomany">
+
+    <class name="ParentWithBidirectionalOneToMany" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <bag name="children"
+             inverse="true"
+             cascade="all">
+            <key column="parent_id"/>
+            <one-to-many class="ChildWithManyToOne"/>
+        </bag>
+    </class>
+
+    <class name="ChildWithManyToOne" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+        <many-to-one name="parent" column="parent_id" class="ParentWithBidirectionalOneToMany" cascade="none"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,57 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ChildWithManyToOne;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ParentWithBidirectionalOneToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class BidirectionalOneToManyBagSubclassCollectionEventTest extends BidirectionalOneToManyBagCollectionEventTest {
+
+	public BidirectionalOneToManyBagSubclassCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BidirectionalOneToManyBagSubclassCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithBidirectionalOneToManySubclass( name );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManyBagSubclassMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.bidirectional.onetomany">
+
+    <class name="ParentWithBidirectionalOneToMany" table="PARENT" discriminator-value="P">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+
+        <discriminator column="TYPE" type="string" length="1"/>
+
+        <bag name="children"
+             inverse="true"
+             cascade="all">
+            <key column="parent_id"/>
+            <one-to-many class="ChildWithManyToOne"/>
+        </bag>
+
+        <subclass name="ParentWithBidirectionalOneToManySubclass"
+            discriminator-value="S">
+        </subclass>
+    </class>
+
+    <class name="ChildWithManyToOne" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+        <many-to-one name="parent" column="parent_id" class="ParentWithBidirectionalOneToMany" cascade="none"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ChildWithManyToOne;
+import org.hibernate.test.event.collection.association.bidirectional.onetomany.ParentWithBidirectionalOneToMany;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class BidirectionalOneToManySetCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public BidirectionalOneToManySetCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BidirectionalOneToManySetCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithBidirectionalOneToMany( name );
+	}
+
+	public Collection createCollection() {
+		return new HashSet();
+	}
+
+	public Child createChild(String name) {
+		return new ChildWithManyToOne( name );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/BidirectionalOneToManySetMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.bidirectional.onetomany">
+
+    <class name="ParentWithBidirectionalOneToMany" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <set name="children"
+             inverse="true"
+             cascade="all">
+            <key column="parent_id"/>
+            <one-to-many class="ChildWithManyToOne"/>
+        </set>
+    </class>
+
+    <class name="ChildWithManyToOne" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+        <many-to-one name="parent" column="parent_id" class="ParentWithBidirectionalOneToMany" cascade="none"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ChildWithManyToOne.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ChildWithManyToOne.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ChildWithManyToOne.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,47 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import org.hibernate.test.event.collection.ChildEntity;
+import org.hibernate.test.event.collection.ParentWithCollection;
+
+/**
+ * @author Gail Badner
+ */
+public class ChildWithManyToOne extends ChildEntity {
+	private ParentWithCollection parent;
+
+	public ChildWithManyToOne() {
+	}
+
+	public ChildWithManyToOne(String name) {
+		super( name );
+	}
+
+	public ParentWithCollection getParent() {
+		return parent;
+	}
+
+	public void setParent(ParentWithCollection parent) {
+		this.parent = parent;
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToMany.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToMany.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToMany.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,85 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.AbstractParentWithCollection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ParentWithBidirectionalOneToMany extends AbstractParentWithCollection {
+	public ParentWithBidirectionalOneToMany() {
+	}
+
+	public ParentWithBidirectionalOneToMany(String name) {
+		super( name );
+	}
+
+	public Child createChild( String name ) {
+		return new ChildWithManyToOne( name );
+	}
+
+	public Child addChild(String name) {
+		Child child = createChild( name );
+		addChild( child );
+		return child;
+	}
+
+	public void addChild(Child child) {
+		super.addChild( child );
+		( ( ChildWithManyToOne ) child ).setParent( this );
+	}
+
+	public void newChildren(Collection children) {
+		if ( children == getChildren() ) {
+			return;
+		}
+		if ( getChildren() != null ) {
+			for ( Iterator it = getChildren().iterator(); it.hasNext(); ) {
+				ChildWithManyToOne child =  ( ChildWithManyToOne ) it.next();
+				child.setParent( null );
+			}
+		}
+		if ( children != null ) {
+			for ( Iterator it = children.iterator(); it.hasNext(); ) {
+				ChildWithManyToOne child = ( ChildWithManyToOne ) it.next();
+				child.setParent( this );
+			}
+		}
+		super.newChildren( children );
+	}
+
+	public void removeChild(Child child) {
+		// Note: there can be more than one child in the collection
+		super.removeChild( child );
+		// only set the parent to null if child is no longer in the bag
+		if ( ! getChildren().contains( child ) ) {
+			( ( ChildWithManyToOne ) child ).setParent( null );
+		}
+	}
+
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToManySubclass.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToManySubclass.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/bidirectional/onetomany/ParentWithBidirectionalOneToManySubclass.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,42 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.bidirectional.onetomany;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.AbstractParentWithCollection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ParentWithBidirectionalOneToManySubclass extends ParentWithBidirectionalOneToMany {
+	public ParentWithBidirectionalOneToManySubclass() {
+	}
+
+	public ParentWithBidirectionalOneToManySubclass(String name) {
+		super( name );
+	}
+
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/ParentWithCollectionOfEntities.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/ParentWithCollectionOfEntities.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/ParentWithCollectionOfEntities.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,43 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.unidirectional;
+
+import org.hibernate.test.event.collection.AbstractParentWithCollection;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ChildEntity;
+
+/**
+ * @author Gail Badner
+ */
+public class ParentWithCollectionOfEntities extends AbstractParentWithCollection {
+
+	public ParentWithCollectionOfEntities() {
+	}
+
+	public ParentWithCollectionOfEntities(String name) {
+		super( name );
+	}
+
+	public Child createChild(String name) {
+		return new ChildEntity( name );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.unidirectional.manytomany;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ChildEntity;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.ParentWithCollectionOfEntities;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class UnidirectionalManyToManyBagCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public UnidirectionalManyToManyBagCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( UnidirectionalManyToManyBagCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithCollectionOfEntities( name );
+	}
+
+	public Collection createCollection() {
+		return new ArrayList();
+	}
+
+	public Child createChild(String name) {
+		return new ChildEntity( name );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/manytomany/UnidirectionalManyToManyBagMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.unidirectional">
+
+    <class name="ParentWithCollectionOfEntities" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <bag name="children" table="PARENT_CHILD"
+             inverse="false" cascade="all">
+            <key column="parent_id"/>
+            <many-to-many column="child_id" class="org.hibernate.test.event.collection.ChildEntity"/>
+        </bag>
+    </class>
+
+    <class name="org.hibernate.test.event.collection.ChildEntity" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.unidirectional.onetomany;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ChildEntity;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.ParentWithCollectionOfEntities;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class UnidirectionalOneToManyBagCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public UnidirectionalOneToManyBagCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( UnidirectionalOneToManyBagCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithCollectionOfEntities( name );
+	}
+
+	public Collection createCollection() {
+		return new ArrayList();
+	}
+
+	public Child createChild(String name) {
+		return new ChildEntity( name );
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManyBagMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.unidirectional">
+
+    <class name="ParentWithCollectionOfEntities" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <bag name="children"
+             cascade="all">
+            <key column="parent_id"/>
+            <one-to-many class="org.hibernate.test.event.collection.ChildEntity"/>
+        </bag>
+    </class>
+
+    <class name="org.hibernate.test.event.collection.ChildEntity" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,60 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.association.unidirectional.onetomany;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.association.AbstractAssociationCollectionEventTest;
+import org.hibernate.test.event.collection.association.unidirectional.ParentWithCollectionOfEntities;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class UnidirectionalOneToManySetCollectionEventTest extends AbstractAssociationCollectionEventTest {
+
+	public UnidirectionalOneToManySetCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( UnidirectionalOneToManySetCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithCollectionOfEntities( name );
+	}
+
+	public Collection createCollection() {
+		return new HashSet();
+	}	
+}
+

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/association/unidirectional/onetomany/UnidirectionalOneToManySetMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.association.unidirectional">
+
+    <class name="ParentWithCollectionOfEntities" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <set name="children"
+             cascade="all">
+            <key column="parent_id"/>
+            <one-to-many class="org.hibernate.test.event.collection.ChildEntity"/>
+        </set>
+    </class>
+
+    <class name="org.hibernate.test.event.collection.ChildEntity" table="CHILD">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <property name="name" column="NAME" type="string"/>
+    </class>
+
+</hibernate-mapping>

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ParentWithCollectionOfValues.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ParentWithCollectionOfValues.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ParentWithCollectionOfValues.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,45 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.values;
+
+import java.util.Collection;
+
+import org.hibernate.test.event.collection.Child;
+import org.hibernate.test.event.collection.ChildValue;
+import org.hibernate.test.event.collection.AbstractParentWithCollection;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ParentWithCollectionOfValues extends AbstractParentWithCollection {
+	public ParentWithCollectionOfValues() {
+	}
+
+	public ParentWithCollectionOfValues(String name) {
+		super( name );
+	}
+	
+	public Child createChild(String name) {
+		return new ChildValue( name );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagCollectionEventTest.java
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagCollectionEventTest.java	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagCollectionEventTest.java	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC 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
+ * Middleware LLC.  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.test.event.collection.values;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.event.collection.AbstractCollectionEventTest;
+import org.hibernate.test.event.collection.ParentWithCollection;
+import org.hibernate.test.event.collection.values.ParentWithCollectionOfValues;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class ValuesBagCollectionEventTest extends AbstractCollectionEventTest {
+
+	public ValuesBagCollectionEventTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ValuesBagCollectionEventTest.class );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "event/collection/values/ValuesBagMapping.hbm.xml" };
+	}
+
+	public ParentWithCollection createParent(String name) {
+		return new ParentWithCollectionOfValues( name );
+	}
+
+	public Collection createCollection() {
+		return new ArrayList();
+	}
+}

Added: core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagMapping.hbm.xml
===================================================================
--- core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagMapping.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_2_4_SP1_CP/test/org/hibernate/test/event/collection/values/ValuesBagMapping.hbm.xml	2008-07-09 01:03:32 UTC (rev 14899)
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.event.collection.values">
+
+    <class name="ParentWithCollectionOfValues" table="PARENT">
+        <id name="id" column="ID" type="long">
+            <generator class="native"/>
+        </id>
+        <bag name="children"
+             cascade="all">
+            <key column="parent_id"/>
+            <composite-element class="org.hibernate.test.event.collection.ChildValue">
+                <property name="name"/>
+            </composite-element>
+        </bag>
+    </class>
+
+</hibernate-mapping>




More information about the hibernate-commits mailing list