From: <mcu...@us...> - 2007-09-01 19:12:15
|
Revision: 1110 http://orm.svn.sourceforge.net/orm/?rev=1110&view=rev Author: mcurland Date: 2007-09-01 12:12:14 -0700 (Sat, 01 Sep 2007) Log Message: ----------- Subtypes with no resolvable preferred identifier were considered eligible for absorption. Modify ORMElementGateway to block object types that do not resolve to a preferred identifier. refs #327 Modified Paths: -------------- trunk/Oial/ORMOialBridge/ORMElementGateway.cs trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.cs trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.xml Modified: trunk/Oial/ORMOialBridge/ORMElementGateway.cs =================================================================== --- trunk/Oial/ORMOialBridge/ORMElementGateway.cs 2007-09-01 19:01:35 UTC (rev 1109) +++ trunk/Oial/ORMOialBridge/ORMElementGateway.cs 2007-09-01 19:12:14 UTC (rev 1110) @@ -133,6 +133,40 @@ } } } + else if (!objectType.IsValueType) + { + // If this is a subtype, then we need to resolve + // the preferred identifier back to a non-excluded super type + ObjectType preferridentifierFrom = null; + ObjectType.WalkSupertypes( + objectType, + delegate(ObjectType type, int depth, bool isPrimary) + { + ObjectTypeVisitorResult result = ObjectTypeVisitorResult.Continue; + if (isPrimary) + { + if (IsElementExcluded(type)) + { + result = ObjectTypeVisitorResult.Stop; + } + else if (type.PreferredIdentifier != null) + { + preferridentifierFrom = type; + result = ObjectTypeVisitorResult.Stop; + } + else + { + result = ObjectTypeVisitorResult.SkipFollowingSiblings; // We already have the primary, no need to look further at this level + } + } + else if (depth != 0) + { + result = ObjectTypeVisitorResult.SkipChildren; + } + return result; + }); + return preferridentifierFrom != null; + } return true; } return false; @@ -275,6 +309,8 @@ { exclusionLink.Delete(); AddObjectType(objectType); + + // Consider readding associated fact types foreach (Role playedRole in objectType.PlayedRoleCollection) { FactType factType = playedRole.FactType; @@ -292,6 +328,33 @@ } } } + + // Consider readding subtypes excluded because this element was excluded + if (!objectType.IsValueType) + { + // Excluding an object type can leave a downstream subtype without an + // identifier, which excludes them. Note we only go one level deep + // as this will recurse naturally on the next level. + ObjectType.WalkSubtypes(objectType, delegate(ObjectType type, int depth, bool isPrimary) + { + switch (depth) + { + case 0: + return ObjectTypeVisitorResult.Continue; + case 1: + if (isPrimary) + { + if (type.PreferredIdentifier == null) + { + FilterModifiedObjectType(type); + } + } + return ObjectTypeVisitorResult.SkipChildren; + default: + return ObjectTypeVisitorResult.Stop; + } + }); + } } } else if (exclusionLink == null) @@ -348,6 +411,9 @@ { notifyExcluded(objectType); } + + // Excluding an object type leaves a FactType with a null role player, + // so the associated fact types also need to be excluded. foreach (Role playedRole in objectType.PlayedRoleCollection) { ExcludeFactType(playedRole.FactType, model, false, notifyExcluded); @@ -357,6 +423,32 @@ ExcludeFactType(proxy.FactType, model, false, notifyExcluded); } } + + if (!objectType.IsValueType) + { + // Excluding an object type can leave a downstream subtype without an + // identifier, so exclude those as well. Note we only go one level deep + // as this will recurse naturally on the next level. + ObjectType.WalkSubtypes(objectType, delegate(ObjectType type, int depth, bool isPrimary) + { + switch (depth) + { + case 0: + return ObjectTypeVisitorResult.Continue; + case 1: + if (isPrimary) + { + if (type.PreferredIdentifier == null) + { + ExcludeObjectType(type, model, false, notifyExcluded); + } + } + return ObjectTypeVisitorResult.SkipChildren; + default: + return ObjectTypeVisitorResult.Stop; + } + }); + } } } #endregion // Exclude* methods, exclude elements from absorption consideration @@ -575,6 +667,27 @@ } } #endregion // Model error tracking rules + #region Preferred Identifier Tracking Rules + /// <summary> + /// AddRule: typeof(Neumont.Tools.ORM.ObjectModel.EntityTypeHasPreferredIdentifier) + /// Handle cases where subtypes have no preferred identifier. Note that this + /// is not necessarily an error condition in the core model, so we will not always + /// an error deleting notification on this object type, but this condition blocks + /// absorption on directly and indirectly subtyped objects that now need to be reconsidered. + /// </summary> + private static void PreferredIdentifierAddedRule(ElementAddedEventArgs e) + { + ObjectType objectType = ((EntityTypeHasPreferredIdentifier)e.ModelElement).PreferredIdentifierFor; + ObjectType.WalkSubtypes(objectType, delegate(ObjectType type, int depth, bool isPrimary) + { + if (isPrimary || depth == 0) + { + FilterModifiedObjectType(type); + } + return ObjectTypeVisitorResult.Continue; + }); + } + #endregion // Preferred Identifier Tracking Rules #region RolePlayer tracking rules /// <summary> /// AddRule: typeof(Neumont.Tools.ORM.ObjectModel.ObjectTypePlaysRole) Modified: trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.cs =================================================================== --- trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.cs 2007-09-01 19:01:35 UTC (rev 1109) +++ trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.cs 2007-09-01 19:12:14 UTC (rev 1110) @@ -41,6 +41,7 @@ typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("ObjectTypeAddedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("ObjectTypeErrorAddedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("ObjectTypeErrorDeletedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), + typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("PreferredIdentifierAddedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("RolePlayerAddedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("RolePlayerDeletedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), typeof(AbstractionModelIsForORMModel).GetNestedType("ORMElementGateway", BindingFlags.Public | BindingFlags.NonPublic).GetNestedType("RolePlayerRolePlayerChangedRuleClass", BindingFlags.Public | BindingFlags.NonPublic), @@ -90,7 +91,7 @@ { Microsoft.VisualStudio.Modeling.RuleManager ruleManager = store.RuleManager; Type[] disabledRuleTypes = ORMToORMAbstractionBridgeDomainModel.CustomDomainModelTypes; - for (int i = 0; i < 23; ++i) + for (int i = 0; i < 24; ++i) { ruleManager.EnableRule(disabledRuleTypes[i]); } @@ -309,6 +310,32 @@ Neumont.Tools.Modeling.Diagnostics.TraceUtility.TraceRuleEnd(e.ModelElement.Store, "Neumont.Tools.ORMToORMAbstractionBridge.AbstractionModelIsForORMModel.ORMElementGateway.ObjectTypeErrorDeletedRule"); } } + [Microsoft.VisualStudio.Modeling.RuleOn(typeof(Neumont.Tools.ORM.ObjectModel.EntityTypeHasPreferredIdentifier), Priority=Neumont.Tools.Modeling.FrameworkDomainModel.InlineRulePriority)] + private sealed class PreferredIdentifierAddedRuleClass : Microsoft.VisualStudio.Modeling.AddRule + { + [System.Diagnostics.DebuggerStepThrough()] + public PreferredIdentifierAddedRuleClass() + { + base.IsEnabled = false; + } + /// <summary> + /// Provide the following method in class: + /// Neumont.Tools.ORMToORMAbstractionBridge.AbstractionModelIsForORMModel.ORMElementGateway + /// /// <summary> + /// /// AddRule: typeof(Neumont.Tools.ORM.ObjectModel.EntityTypeHasPreferredIdentifier) + /// /// </summary> + /// private static void PreferredIdentifierAddedRule(ElementAddedEventArgs e) + /// { + /// } + /// </summary> + [System.Diagnostics.DebuggerStepThrough()] + public override void ElementAdded(Microsoft.VisualStudio.Modeling.ElementAddedEventArgs e) + { + Neumont.Tools.Modeling.Diagnostics.TraceUtility.TraceRuleStart(e.ModelElement.Store, "Neumont.Tools.ORMToORMAbstractionBridge.AbstractionModelIsForORMModel.ORMElementGateway.PreferredIdentifierAddedRule"); + ORMElementGateway.PreferredIdentifierAddedRule(e); + Neumont.Tools.Modeling.Diagnostics.TraceUtility.TraceRuleEnd(e.ModelElement.Store, "Neumont.Tools.ORMToORMAbstractionBridge.AbstractionModelIsForORMModel.ORMElementGateway.PreferredIdentifierAddedRule"); + } + } [Microsoft.VisualStudio.Modeling.RuleOn(typeof(Neumont.Tools.ORM.ObjectModel.ObjectTypePlaysRole), Priority=Neumont.Tools.Modeling.FrameworkDomainModel.InlineRulePriority)] private sealed class RolePlayerAddedRuleClass : Microsoft.VisualStudio.Modeling.AddRule { Modified: trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.xml =================================================================== --- trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.xml 2007-09-01 19:01:35 UTC (rev 1109) +++ trunk/Oial/ORMOialBridge/ORMOialBridge.AttachRules.xml 2007-09-01 19:12:14 UTC (rev 1110) @@ -48,6 +48,9 @@ <arg:RuleOn targetType="ObjectTypeHasObjectTypeRequiresPrimarySupertypeError" targetTypeQualifier="Neumont.Tools.ORM.ObjectModel"/> <arg:RuleOn targetType="ValueTypeHasUnspecifiedDataTypeError" targetTypeQualifier="Neumont.Tools.ORM.ObjectModel"/> </arg:DeleteRule> + <arg:AddRule methodName="PreferredIdentifierAddedRule"> + <arg:RuleOn targetType="EntityTypeHasPreferredIdentifier" targetTypeQualifier="Neumont.Tools.ORM.ObjectModel"/> + </arg:AddRule> <arg:AddRule methodName="RolePlayerAddedRule"> <arg:RuleOn targetType="ObjectTypePlaysRole" targetTypeQualifier="Neumont.Tools.ORM.ObjectModel"/> </arg:AddRule> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |