From: Paul H. <pha...@us...> - 2005-03-14 18:52:40
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Engine In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6586/nhibernate/src/NHibernate/Engine Modified Files: Cascades.cs ISessionImplementor.cs Log Message: Refactored as per 2.1 Index: ISessionImplementor.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Engine/ISessionImplementor.cs,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** ISessionImplementor.cs 6 Mar 2005 12:44:39 -0000 1.31 --- ISessionImplementor.cs 14 Mar 2005 18:52:11 -0000 1.32 *************** *** 38,48 **** /// <summary> - /// Set the "shallow dirty" status of the collection. Called when the collection detects - /// that the client is modifying it - /// </summary> - /// TODO: (2.1) This method no longer required. - void Dirty( PersistentCollection collection ); - - /// <summary> /// Initialize the collection (if not already initialized) /// </summary> --- 38,41 ---- *************** *** 59,81 **** /// <summary> ! /// new in h2.0.3 and no javadoc /// </summary> /// <param name="persister"></param> /// <param name="id"></param> /// <returns></returns> ! PersistentCollection GetLoadingCollection( ICollectionPersister persister, object id ); ! ! /// <summary> ! /// new in h2.0.3 and no javadoc ! /// </summary> ! /// <param name="role"></param> ! /// <param name="id"></param> ! /// <returns></returns> ! PersistentCollection GetLoadingCollection( String role, object id ); /// <summary> ! /// new in h2.0.3 and no javadoc /// </summary> ! void EndLoadingCollections(); /// <summary> --- 52,67 ---- /// <summary> ! /// new in h2.1 and no javadoc /// </summary> /// <param name="persister"></param> /// <param name="id"></param> + /// <param name="resultSetId"></param> /// <returns></returns> ! PersistentCollection GetLoadingCollection( ICollectionPersister persister, object id, object resultSetId ); /// <summary> ! /// new in h2.1 and no javadoc /// </summary> ! void EndLoadingCollections( ICollectionPersister persister, object resultSetId ); /// <summary> *************** *** 274,280 **** /// <summary> /// Notify the session that the transaction completed, so we no longer own the old locks. ! /// (Also we shold release cache softlocks). /// </summary> ! void AfterTransactionCompletion(); /// <summary> --- 260,267 ---- /// <summary> /// Notify the session that the transaction completed, so we no longer own the old locks. ! /// (Also we shold release cache softlocks). May be called multiple times during the transaction ! /// completion process. /// </summary> ! void AfterTransactionCompletion( bool successful ); /// <summary> Index: Cascades.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Engine/Cascades.cs,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** Cascades.cs 6 Mar 2005 12:44:38 -0000 1.17 --- Cascades.cs 14 Mar 2005 18:52:11 -0000 1.18 *************** *** 17,20 **** --- 17,21 ---- /// </summary> CascadeAfterInsertBeforeDelete = 1, + /// <summary> /// A cascade point that occurs just before the insertion of the parent entity *************** *** 22,25 **** --- 23,27 ---- /// </summary> CascadeBeforeInsertAfterDelete = 2, + /// <summary> /// A cascade point that occurs just after the insertion of the parent entity *************** *** 27,34 **** --- 29,38 ---- /// </summary> CascadeAfterInsertBeforeDeleteViaCollection = 3, + /// <summary> /// A cascade point that occurs just after the update of the parent entity /// </summary> CascadeOnUpdate = 0, + /// <summary> /// A cascade point that occurs just after eviction of the parent entity from the *************** *** 38,44 **** /// <summary> ! /// A cascade point that occurs just after locking the parent entity /// </summary> ! CascadeOnLock = 0 } --- 42,53 ---- /// <summary> ! /// A cascade point that occurs just after locking a transient parent entity into the session cache /// </summary> ! CascadeOnLock = 0, ! ! /// <summary> ! /// A cascade point that occurs just after copying from a transient parent entity into the object in the session cache ! /// </summary> ! CascadeOnCopy = 0 } *************** *** 71,79 **** /// <summary> ! /// Should this action be cascaded to the given (possibly unitilized) collection? /// </summary> ! public abstract bool ShouldCascadeCollection( object collection ); ! /// <summary></summary> public abstract bool DeleteOrphans(); --- 80,90 ---- /// <summary> ! /// The children to whom we should cascade. /// </summary> ! public abstract ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ); ! /// <summary> ! /// Do we need to handle orphan delete for this action? ! /// </summary> public abstract bool DeleteOrphans(); *************** *** 92,98 **** } ! public override bool ShouldCascadeCollection( object collection ) { ! return true; } --- 103,109 ---- } ! public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) { ! return Cascades.GetAllElementsCollection( collectionType, collection ); } *************** *** 104,120 **** /// <summary></summary> ! public static CascadingAction ActionEvict = new ActionEvictClass(); ! private class ActionEvictClass : CascadingAction { public override void Cascade( ISessionImplementor session, object child, object anything ) { ! log.Debug( "cascading to evict()" ); ! session.Evict( child ); } ! public override bool ShouldCascadeCollection( object collection ) { ! return CollectionIsInitialized( collection ); } --- 115,131 ---- /// <summary></summary> ! public static CascadingAction ActionLock = new ActionLockClass(); ! private class ActionLockClass : CascadingAction { public override void Cascade( ISessionImplementor session, object child, object anything ) { ! log.Debug( "cascading to lock()" ); ! session.Lock( child, (LockMode) anything ); } ! public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) { ! return Cascades.GetLoadedElementsCollection( collectionType, collection ); } *************** *** 126,142 **** /// <summary></summary> ! public static CascadingAction ActionLock = new ActionLockClass(); ! private class ActionLockClass : CascadingAction { public override void Cascade( ISessionImplementor session, object child, object anything ) { ! log.Debug( "cascading to lock()" ); ! session.Lock( child, (LockMode) anything ); } ! public override bool ShouldCascadeCollection( object collection ) { ! return CollectionIsInitialized( collection ); } --- 137,153 ---- /// <summary></summary> ! public static CascadingAction ActionEvict = new ActionEvictClass(); ! private class ActionEvictClass : CascadingAction { public override void Cascade( ISessionImplementor session, object child, object anything ) { ! log.Debug( "cascading to evict()" ); ! session.Evict( child ); } ! public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) { ! return Cascades.GetLoadedElementsCollection( collectionType, collection ); } *************** *** 158,165 **** } ! public override bool ShouldCascadeCollection( object collection ) { ! // saves/updates don't cascade to uninitialized collections ! return CollectionIsInitialized( collection ); } --- 169,175 ---- } ! public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) { ! return Cascades.GetLoadedElementsCollection( collectionType, collection ); } *************** *** 171,174 **** --- 181,208 ---- /// <summary></summary> + public static CascadingAction ActionCopy = new ActionCopyClass(); + + private class ActionCopyClass : CascadingAction + { + public override void Cascade( ISessionImplementor session, object child, object anything ) + { + log.Debug( "cascading to Replicate()" ); + // TODO: 2.1 implement copy + //session.Copy( child, (ReplicationMode) anything ); + } + + public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) + { + return Cascades.GetLoadedElementsCollection( collectionType, collection ); + } + + public override bool DeleteOrphans() + { + // orphans should not be deleted during copy??? + return false; + } + } + + /// <summary></summary> public static CascadingAction ActionReplicate = new ActionReplicateClass(); *************** *** 182,189 **** } ! public override bool ShouldCascadeCollection( object collection ) { ! // replicate does cascade to uninitialized collections ! return true; } --- 216,222 ---- } ! public override ICollection CascadableChildrenCollection( PersistentCollectionType collectionType, object collection ) { ! return Cascades.GetLoadedElementsCollection( collectionType, collection ); } *************** *** 193,201 **** } } ! private static bool CollectionIsInitialized( object collection ) ! { ! return !( collection is PersistentCollection ) || ( ( PersistentCollection ) collection ).WasInitialized; ! } } --- 226,234 ---- } } + } ! private static bool CollectionIsInitialized( object collection ) ! { ! return !( collection is PersistentCollection ) || ( ( PersistentCollection ) collection ).WasInitialized; } *************** *** 215,227 **** public abstract bool DoCascade( CascadingAction action ); ! //TODO: H2.0.3 - it looks like the CascadeStyle subclasses are defined outside of the CascadeStyle ! // class /// <summary> ! /// Save/Delete/Update/Evict + delete orphans /// </summary> ! public static CascadeStyle StyleAllGC = new StyleAllGCClass(); ! private class StyleAllGCClass : CascadeStyle { public override bool DoCascade( CascadingAction action ) --- 248,265 ---- public abstract bool DoCascade( CascadingAction action ); ! /// <summary> ! /// Do we delete orphans automatically? ! /// </summary> ! public virtual bool HasOrphanDelete ! { ! get { return false; } ! } /// <summary> ! /// Save / Delete / Update / Evict / Lock / Replicate + delete orphans /// </summary> ! public static CascadeStyle StyleAllDeleteOrphan = new StyleAllDeleteOrphanClass(); ! private class StyleAllDeleteOrphanClass : CascadeStyle { public override bool DoCascade( CascadingAction action ) *************** *** 229,236 **** return true; } } /// <summary> ! /// Save / Delete / Update / Evict /// </summary> public static CascadeStyle StyleAll = new StyleAllClass(); --- 267,279 ---- return true; } + + public override bool HasOrphanDelete + { + get { return true; } + } } /// <summary> ! /// Save / Delete / Update / Evict / Lock / Replicate /// </summary> public static CascadeStyle StyleAll = new StyleAllClass(); *************** *** 246,250 **** /// <summary> ! /// Save / Update /// </summary> public static CascadeStyle StyleSaveUpdate = new StyleSaveUpdateClass(); --- 289,293 ---- /// <summary> ! /// Save / Update / Lock / Replicate /// </summary> public static CascadeStyle StyleSaveUpdate = new StyleSaveUpdateClass(); *************** *** 254,260 **** public override bool DoCascade( CascadingAction action ) { ! return action == CascadingAction.ActionSaveUpdate ! || action == CascadingAction.ActionLock; ! // TODO: H2.1 also includes Copy and Replicate actions here } } --- 297,304 ---- public override bool DoCascade( CascadingAction action ) { ! return action == CascadingAction.ActionSaveUpdate || ! action == CascadingAction.ActionLock || ! action == CascadingAction.ActionReplicate || ! action == CascadingAction.ActionCopy; } } *************** *** 275,278 **** --- 319,340 ---- /// <summary> + /// Delete + delete orphans + /// </summary> + public static CascadeStyle StyleDeleteOrphan = new StyleDeleteOrphanClass(); + + private class StyleDeleteOrphanClass : CascadeStyle + { + public override bool DoCascade( CascadingAction action ) + { + return action == CascadingAction.ActionDelete; + } + + public override bool HasOrphanDelete + { + get { return true; } + } + } + + /// <summary> /// No Cascades /// </summary> *************** *** 283,287 **** public override bool DoCascade( CascadingAction action ) { ! return false; } } --- 345,349 ---- public override bool DoCascade( CascadingAction action ) { ! return action == CascadingAction.ActionReplicate; } } *************** *** 295,299 **** public class IdentifierValue { ! private object value; /// <summary></summary> --- 357,361 ---- public class IdentifierValue { ! private readonly object value; /// <summary></summary> *************** *** 369,374 **** } /// <summary> ! /// Cascade an action to the Child. /// </summary> /// <param name="session"></param> --- 431,529 ---- } + /// <summary> ! /// A strategy for determining if a version value is an version of ! /// a new transient instance or a previously persistent transient instance. ! /// The strategy is determined by the <c>Unsaved-Value</c> attribute in the mapping file. ! /// </summary> ! public class VersionValue ! { ! private readonly object value; ! ! /// <summary></summary> ! protected VersionValue() ! { ! this.value = null; ! } ! ! /// <summary> ! /// Assume the transient instance is newly instantiated if its version is null or ! /// equal to <c>Value</c> ! /// </summary> ! /// <param name="value"></param> ! public VersionValue( object value ) ! { ! this.value = value; ! } ! ! /// <summary> ! /// Does the given identifier belong to a new instance ! /// </summary> ! public virtual bool IsUnsaved( object version ) ! { ! if( log.IsDebugEnabled ) ! { ! log.Debug( "unsaved-value: " + value ); ! } ! return version == null || value.Equals( version ); ! } ! ! /// <summary> ! /// Assume the transient instance is newly instantiated if the version ! /// is null, otherwise assume it is a detached instance. ! /// </summary> ! public static VersionValue VersionNull = new VersionNullClass(); ! ! private class VersionNullClass : VersionValue ! { ! public override bool IsUnsaved( object version ) ! { ! log.Debug( "version unsaved-value strategy NULL" ); ! return version == null; ! } ! } ! ! /* ! /// <summary> ! /// Assume the transient instance is newly instantiated if the version ! /// is null, otherwise defer to the identifier unsaved-value. ! /// </summary> ! public static VersionValue VersionUndefined = new VersionUndefinedClass(); ! ! private class SaveNoneClass : IdentifierValue ! { ! public override bool IsUnsaved( object id ) ! { ! log.Debug( "version unsaved-value strategy UNDEFINED" ); ! return false; ! } ! } ! */ ! ! /// <summary> ! /// Assume the transient instance is newly instantiated if the identifier ! /// is null. ! /// </summary> ! public static VersionValue VersionNegative = new VersionNegativeClass(); ! ! private class VersionNegativeClass : VersionValue ! { ! public override bool IsUnsaved( object version ) ! { ! log.Debug( "version unsaved-value strategy NEGATIVE" ); ! if ( version is short || version is int || version is long ) ! { ! return (long) version < 1; ! } ! else ! { ! throw new MappingException( "unsaved-value strategy NEGATIVE may only be used with short, int and long types" ); ! } ! } ! } ! } ! ! /// <summary> ! /// Cascade an action to the child or children /// </summary> /// <param name="session"></param> *************** *** 376,383 **** /// <param name="type"></param> /// <param name="action"></param> /// <param name="cascadeTo"></param> - /// <param name="deleteOrphans"></param> /// <param name="anything"></param> ! private static void Cascade( ISessionImplementor session, object child, IType type, CascadingAction action, CascadePoint cascadeTo, bool deleteOrphans, object anything ) { if( child != null ) --- 531,545 ---- /// <param name="type"></param> /// <param name="action"></param> + /// <param name="style"></param> /// <param name="cascadeTo"></param> /// <param name="anything"></param> ! private static void Cascade( ! ISessionImplementor session, ! object child, ! IType type, ! CascadingAction action, ! CascadeStyle style, ! CascadePoint cascadeTo, ! object anything ) { if( child != null ) *************** *** 402,406 **** cascadeVia = cascadeTo; } - PersistentCollectionType pctype = ( PersistentCollectionType ) type; ICollectionPersister persister = session.Factory.GetCollectionPersister( pctype.Role ); --- 564,567 ---- *************** *** 408,463 **** // cascade to current collection elements ! ICollection iter; ! if( action.ShouldCascadeCollection( child ) ) ! { ! if( log.IsDebugEnabled ) ! { ! log.Debug( "cascading to collection: " + pctype.Role ); ! } ! iter = pctype.GetElementsCollection( child ); ! } ! else ! { ! //TODO: this hack assumes that shouldCascadeCollection() always ! // returns true for an initialized collection, which is corruption ! // of the semantics - what we need is to change ! // shouldCascadeCollection() to getCollectionCascadeIterator() ! if( child is PersistentCollection ) ! { ! PersistentCollection pc = ( PersistentCollection ) child; ! if( pc.HasQueuedAdds ) ! { ! iter = pc.QueuedAddsCollection; ! } ! else ! { ! iter = null; ! } ! } ! else ! { ! iter = null; ! } ! } ! if( iter != null ) ! { ! foreach( object obj in iter ) ! { ! Cascade( session, obj, elemType, action, cascadeVia, false, anything ); ! } ! } ! ! // handle oprhaned entities!! ! if( deleteOrphans && action.DeleteOrphans() && child is PersistentCollection ) { ! PersistentCollection pc = ( PersistentCollection ) child; ! if( pc.WasInitialized ) ! { ! ICollection orphanColl = session.GetOrphans( pc ); ! foreach( object obj in orphanColl ) ! { ! session.Delete( obj ); ! } ! } } } --- 569,575 ---- // cascade to current collection elements ! if ( elemType.IsEntityType || elemType.IsObjectType || elemType.IsComponentType ) { ! CascadeCollection( action, style, pctype, elemType, child, cascadeVia, session, anything ); } } *************** *** 471,477 **** for( int i = 0; i < types.Length; i++ ) { ! if( ctype.Cascade( i ).DoCascade( action ) ) { ! Cascade( session, children[ i ], types[ i ], action, cascadeTo, deleteOrphans, anything ); } } --- 583,590 ---- for( int i = 0; i < types.Length; i++ ) { ! CascadeStyle componentPropertyStyle = ctype.Cascade( i ); ! if( componentPropertyStyle.DoCascade( action ) ) { ! Cascade( session, children[ i ], types[ i ], action, componentPropertyStyle, cascadeTo, anything ); } } *************** *** 481,484 **** --- 594,610 ---- /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="persister"></param> + /// <param name="parent"></param> + /// <param name="action"></param> + /// <param name="cascadeTo"></param> + public static void Cascade( ISessionImplementor session, IClassPersister persister, object parent, CascadingAction action, CascadePoint cascadeTo ) + { + Cascade( session, persister, parent, action, cascadeTo, null ); + } + + /// <summary> /// Cascade an action from the parent object to all its children. /// </summary> *************** *** 501,507 **** for( int i = 0; i < types.Length; i++ ) { ! if( cascadeStyles[ i ].DoCascade( action ) ) { ! Cascade( session, persister.GetPropertyValue( parent, i ), types[ i ], action, cascadeTo, cascadeStyles[ i ] == CascadeStyle.StyleAllGC, anything ); } } --- 627,634 ---- for( int i = 0; i < types.Length; i++ ) { ! CascadeStyle style = cascadeStyles[ i ]; ! if( style.DoCascade( action ) ) { ! Cascade( session, persister.GetPropertyValue( parent, i ), types[ i ], action, style, cascadeTo, anything ); } } *************** *** 512,515 **** --- 639,716 ---- } } + + /// <summary> + /// Cascade to the collection elements + /// </summary> + /// <param name="action"></param> + /// <param name="style"></param> + /// <param name="collectionType"></param> + /// <param name="elemType"></param> + /// <param name="child"></param> + /// <param name="cascadeVia"></param> + /// <param name="session"></param> + /// <param name="anything"></param> + private static void CascadeCollection( + CascadingAction action, + CascadeStyle style, + PersistentCollectionType collectionType, + IType elemType, + object child, + CascadePoint cascadeVia, + ISessionImplementor session, + object anything ) + { + // cascade to current collection elements + if( log.IsDebugEnabled ) + { + log.Debug( "cascading to collection: " + collectionType.Role ); + } + ICollection iter = action.CascadableChildrenCollection( collectionType, child ); + foreach( object obj in iter ) + { + Cascade( session, obj, elemType, action, style, cascadeVia, anything ); + } + + // handle oprhaned entities!! + if( style.HasOrphanDelete && action.DeleteOrphans() && child is PersistentCollection ) + { + // We can do the cast since orphan-delete does not apply to: + // 1. newly instatiated collections + // 2. arrays ( we can't track orphans for detached arrays) + DeleteOrphans( child as PersistentCollection, session ); + } + } + + private static void DeleteOrphans( PersistentCollection pc, ISessionImplementor session ) + { + if( pc.WasInitialized ) // can't be any orphans if it was not initialized + { + ICollection orphanColl = session.GetOrphans( pc ); + foreach( object obj in orphanColl ) + { + session.Delete( obj ); + } + } + } + + internal static ICollection GetLoadedElementsCollection( PersistentCollectionType collectionType, object collection ) + { + if ( CollectionIsInitialized( collection ) ) + { + // handles arrays and newly instantiated collections + return collectionType.GetElementsCollection( collection ); + } + else + { + // does not handle arrays (that's ok, cos they can't be lazy) + // or newly instantiated collections so we can do the cast + return ( (PersistentCollection) collection).QueuedAddsCollection; + } + } + + internal static ICollection GetAllElementsCollection( PersistentCollectionType collectionType, object collection ) + { + return collectionType.GetElementsCollection( collection ); + } } } \ No newline at end of file |