// ----------------------------------------------------------------------------------------- public void DetermineSourceChildren(IModelEntity Source) { if (!this.EquivalentEntities.AddNew(Source, null)) { return; } // PENDING: GET ONLY THE MINIMUM OWNED AND DOMINANT OBJECTS foreach (var PropDef in Source.ClassDefinition.Properties) { if (!PropDef.IsStoreBoxBased) { var ValueObject = PropDef.Read(Source); if (ValueObject == null) { continue; } var ValueEntity = ValueObject as IModelEntity; if (ValueEntity == null) { var ValueAssignment = ValueObject as MAssignment; if (ValueAssignment != null) { ValueEntity = ValueAssignment.AssignedValue as IModelEntity; } /* Not required (the owner is outside the owned children and dominant dependencies) * else * { * var ValueOwnership = ValueObject as MOwnership; * if (ValueOwnership != null) * ValueEntity = ValueOwnership.Owner as IModelEntity; * } */ } if (ValueEntity != null) { DetermineSourceChildren(ValueEntity); } else { Console.WriteLine("Prop{{" + PropDef.QualifiedTechName + "}}: [" + ValueObject.ToStringAlways() + "]"); } } } // Collections are typically owned foreach (var CollDef in Source.ClassDefinition.Collections) { var SourceCollection = (EditableCollection)CollDef.Read(Source) as IEnumerable <object>; if (SourceCollection == null) { continue; } var Index = 0; foreach (var Item in SourceCollection) { var EntityItem = Item as IModelEntity; if (EntityItem != null) { DetermineSourceChildren(EntityItem); } else if (Item != null) { Console.WriteLine("CollItem{{" + CollDef.QualifiedTechName + "(" + Index.ToString() + ")}}: [" + Item.ToStringAlways() + "]"); } Index++; } } }
// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Fixes any Unique-Element duplicated Global-Id. /// </summary> private static bool ModelRev8_FixDuplicatedGlobalIds(Composition TargetCompo, string Route = null, IList <IMModelClass> ExaminedInstances = null, IMModelClass Target = null) { if (Route == null) { Route = "\\\\"; } if (ExaminedInstances == null) { ExaminedInstances = new List <IMModelClass>(); } if (Target == null) { Target = TargetCompo; } if (ExaminedInstances.Contains(Target)) { return(false); } ExaminedInstances.Add(Target); Route = Route + Target.ToHashCodeAndString() + "~"; var PropertyDefs = Target.ClassDefinition.Properties; foreach (var PropDef in PropertyDefs) { var Value = PropDef.Read(Target); var PropValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (PropValue != null) { ModelRev8_FixDuplicatedGlobalIds(TargetCompo, Route + PropDef.TechName + "=", ExaminedInstances, PropValue); } } var CollectionDefs = Target.ClassDefinition.Collections; foreach (var CollDef in CollectionDefs) { var Collection = (EditableCollection)CollDef.Read(Target); var CollList = Collection as IList; if (CollList != null) { var Duplicates = new List <UniqueElement>(); var Index = -1; foreach (var Item in CollList) { Index++; var CollItem = (Item is MOwnership ? ((MOwnership)Item).Owner : (Item is MAssignment ? ((MAssignment)Item).AssignedValue : Item)) as IMModelClass; if (CollItem != null) { var ItemId = CollDef.TechName + "[" + Index.ToString() + "]=" + CollItem.ToHashCodeAndString() + "\\"; if (Item is UniqueElement) { var Items = ((IEnumerable <object>)CollList).CastAs <UniqueElement, object>(); if (Items.Any(item => item != Item && item.GlobalId == ((UniqueElement)Item).GlobalId)) { Duplicates.Add((UniqueElement)Item); //T Console.WriteLine("%" + Route + ItemId + "=" + ((UniqueElement)Item).GlobalId.ToString() + (Item is FormalElement ? (((FormalElement)Item).Version != null ? "::" + ((FormalElement)Item).Version.Creation.ToString("yyyyMMdd.hhmmss") : "") : "")); } } ModelRev8_FixDuplicatedGlobalIds(TargetCompo, ItemId, ExaminedInstances, CollItem); } } foreach (var Duplicate in Duplicates.Skip(1)) { Duplicate.GlobalId = Guid.NewGuid(); } } else { var CollDict = Collection as IDictionary; if (CollDict != null) { var Duplicates = new List <UniqueElement>(); var Index = -1; foreach (var Key in CollDict.Keys) { Index++; var CollKey = (Key is MOwnership ? ((MOwnership)Key).Owner : (Key is MAssignment ? ((MAssignment)Key).AssignedValue : Key)) as IMModelClass; if (CollKey != null) { var ItemId = CollDef.TechName + "[" + Index.ToString() + "]K=" + CollKey.ToHashCodeAndString() + "\\"; if (CollKey is UniqueElement) { var Items = ((IEnumerable <object>)CollList).CastAs <UniqueElement, object>(); if (Items.Any(item => item != CollKey && item.GlobalId == ((UniqueElement)CollKey).GlobalId)) { Duplicates.Add((UniqueElement)CollKey); //T Console.WriteLine("%" + Route + ItemId + "=" + ((UniqueElement)CollKey).GlobalId.ToString() + (CollKey is FormalElement ? (((FormalElement)CollKey).Version != null ? "::" + ((FormalElement)CollKey).Version.Creation.ToString("yyyyMMdd.hhmmss") : "") : "")); } } ModelRev8_FixDuplicatedGlobalIds(TargetCompo, ItemId, ExaminedInstances, CollKey); } } Index = -1; foreach (var Value in CollDict.Values) { Index++; var CollValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (CollValue != null) { var ItemId = CollDef.TechName + "[" + Index.ToString() + "]V=" + CollValue.ToHashCodeAndString() + "\\"; if (CollValue is UniqueElement) { var Items = ((IEnumerable <object>)CollList).CastAs <UniqueElement, object>(); if (Items.Any(item => item != CollValue && item.GlobalId == ((UniqueElement)CollValue).GlobalId)) { Duplicates.Add((UniqueElement)CollValue); //T Console.WriteLine("%" + Route + ItemId + "=" + ((UniqueElement)CollValue).GlobalId.ToString() + (CollValue is FormalElement ? (((FormalElement)CollValue).Version != null ? "::" + ((FormalElement)CollValue).Version.Creation.ToString("yyyyMMdd.hhmmss") : "") : "")); } } ModelRev8_FixDuplicatedGlobalIds(TargetCompo, ItemId, ExaminedInstances, CollValue); } } foreach (var Duplicate in Duplicates.Skip(1)) { Duplicate.GlobalId = Guid.NewGuid(); } } } } return(true); }
/// <summary> /// Fixes references to owner, which are not pointing to the real ones (resulting of old-buggy cloning operation). /// </summary> private static bool ModelRev7_ApplyFixOwnerReferences(Composition TargetCompo, string Route, IList <IMModelClass> ExaminedInstances, List <Tuple <IMModelClass, MModelPropertyDefinitor, object> > Fixes, IMModelClass Target, IMModelClass DirectOwner = null, int Level = 0) { if (ExaminedInstances.Contains(Target)) { return(false); } ExaminedInstances.Add(Target); Route = Route + Target.ToHashCodeAndString() + "~"; var PropertyDefs = Target.ClassDefinition.Properties; foreach (var PropDef in PropertyDefs) { var Value = PropDef.Read(Target); var PropValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (PropValue != null) { if (PropDef.ReferencesOwner.HasValue && DirectOwner != null) { var Change = ModelRev7_EvaluateOwnershipDisconnection(TargetCompo, Target, Route, DirectOwner, PropValue); if (Change) { // PENDING: Ensure there is only one claiming owner // (not needed if THE-WHOLE-PROCESS is invoked by 2nd time without generating new changes) object Referencer = null; var IsValid = true; // just until all type-validations are implemented Referencer = (Value is MOwnership ? (object)(((MOwnership)Value).CreateClone(DirectOwner)) : (Value is MAssignment ? (object)(((MAssignment)Value).CreateClone(DirectOwner)) : DirectOwner)); // Ensure coherence per each treated type var TableOwner = DirectOwner as Table; var TableRefer = PropValue as Table; if (TableOwner != null) { if (TableOwner.AssignedDesignator.Value != TableRefer.AssignedDesignator.Value) { IsValid = false; } } /* var RelDefOwner = DirectOwner as RelationshipDefinition; * var RelDefRefer = PropValue as RelationshipDefinition; * if (IsValid && RelDefOwner != null) * { * // validate for reldef * IsValid = true; * } */ if (Referencer != null && IsValid) { Fixes.Add(Tuple.Create(Target, PropDef, Referencer)); //T Console.WriteLine("TYPES of Target=[{0}], NewRef=[{1}]", Target.GetType().Name, Referencer.GetType().Name); } } } if (PropDef.Membership != EEntityMembership.External) { ModelRev7_ApplyFixOwnerReferences(TargetCompo, Route + PropDef.TechName + "=", ExaminedInstances, Fixes, PropValue, (PropDef.Membership == EEntityMembership.External ? null : Target), Level + 1); } } } var CollectionDefs = Target.ClassDefinition.Collections; foreach (var CollDef in CollectionDefs) { if (CollDef.Membership == EEntityMembership.External) { continue; } var Collection = (EditableCollection)CollDef.Read(Target); var CollList = Collection as IList; if (CollList != null) { var Index = -1; foreach (var Item in CollList) { Index++; var CollItem = (Item is MOwnership ? ((MOwnership)Item).Owner : (Item is MAssignment ? ((MAssignment)Item).AssignedValue : Item)) as IMModelClass; if (CollItem != null) { ModelRev7_ApplyFixOwnerReferences(TargetCompo, Route + CollDef.TechName + "[" + Index.ToString() + "]=", ExaminedInstances, Fixes, CollItem, (CollDef.Membership == EEntityMembership.External ? null : Target), Level + 1); } } } else { var CollDict = Collection as IDictionary; if (CollDict != null) { var Index = -1; foreach (var Key in CollDict.Keys) { Index++; var CollKey = (Key is MOwnership ? ((MOwnership)Key).Owner : (Key is MAssignment ? ((MAssignment)Key).AssignedValue : Key)) as IMModelClass; if (CollKey != null) { ModelRev7_ApplyFixOwnerReferences(TargetCompo, Route + CollDef.TechName + "[" + Index.ToString() + "]K=", ExaminedInstances, Fixes, CollKey, (CollDef.Membership == EEntityMembership.External ? null : Target), Level + 1); } } Index = -1; foreach (var Value in CollDict.Values) { Index++; var CollValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (CollValue != null) { ModelRev7_ApplyFixOwnerReferences(TargetCompo, Route + CollDef.TechName + "[" + Index.ToString() + "]V=", ExaminedInstances, Fixes, CollValue, (CollDef.Membership == EEntityMembership.External ? null : Target), Level + 1); } } } } } return(true); }
private static void ModelRev7_FindLocationsOf(IList <IMModelClass> ExaminedInstances, string Route, ref List <string> Results, IMModelClass Target, IMModelClass SearchedObject) { if (ExaminedInstances == null) { ExaminedInstances = new List <IMModelClass>(); } if (ExaminedInstances.Contains(Target)) { return; } if (Target == SearchedObject) { Results.Add(Route + Target.ToHashCodeAndString()); } ExaminedInstances.Add(Target); Route = Route + Target.ToHashCodeAndString() + "~"; var PropertyDefs = Target.ClassDefinition.Properties; foreach (var PropDef in PropertyDefs) { var Value = PropDef.Read(Target); var PropValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (PropValue != null) { ModelRev7_FindLocationsOf(ExaminedInstances, Route + PropDef.TechName + "=", ref Results, PropValue, SearchedObject); } } var CollectionDefs = Target.ClassDefinition.Collections; foreach (var CollDef in CollectionDefs) { var Collection = (EditableCollection)CollDef.Read(Target); var CollList = Collection as IList; if (CollList != null) { var Index = -1; foreach (var Item in CollList) { Index++; var CollItem = (Item is MOwnership ? ((MOwnership)Item).Owner : (Item is MAssignment ? ((MAssignment)Item).AssignedValue : Item)) as IMModelClass; if (CollItem != null) { ModelRev7_FindLocationsOf(ExaminedInstances, Route + CollDef.TechName + "[" + Index.ToString() + "]=" + CollItem.ToHashCodeAndString() + "\\", ref Results, CollItem, SearchedObject); } } } else { var CollDict = Collection as IDictionary; if (CollDict != null) { var Index = -1; foreach (var Key in CollDict.Keys) { Index++; var CollKey = (Key is MOwnership ? ((MOwnership)Key).Owner : (Key is MAssignment ? ((MAssignment)Key).AssignedValue : Key)) as IMModelClass; if (CollKey != null) { ModelRev7_FindLocationsOf(ExaminedInstances, Route + CollDef.TechName + "[" + Index.ToString() + "]K=" + CollKey.ToHashCodeAndString() + "\\", ref Results, CollKey, SearchedObject); } } Index = -1; foreach (var Value in CollDict.Values) { Index++; var CollValue = (Value is MOwnership ? ((MOwnership)Value).Owner : (Value is MAssignment ? ((MAssignment)Value).AssignedValue : Value)) as IMModelClass; if (CollValue != null) { ModelRev7_FindLocationsOf(ExaminedInstances, Route + CollDef.TechName + "[" + Index.ToString() + "]V=" + CollValue.ToHashCodeAndString() + "\\", ref Results, CollValue, SearchedObject); } } } } } }
/// <summary> /// Populates properties of a target model instance, plus returning it, with these from the supplied one. /// </summary> /// <param name="Target">Target model instance for which populate/overwrite property values.</param> /// <param name="Source">Source model instance from which get property values.</param> /// /// <param name="TargetOwner">Model instance owning the Target (intended to update owner references of the Source).</param> /// <param name="CloningScope">Indicates to make a copy of the populated value through the dependant object hierarchy.</param> /// <param name="IsForCloning">Indicates whether the population will be performed on a clone.</param> // See below /// <param name="AsActive">Indicates whether the new clone will be active (i.e. will notify changes and store them for undo/redo).</param> /// <param name="MemberNames">Optional explicit member names to be populated (when empty, all members are populated).</param> /// <returns>The populated target model instance.</returns> public TModelClass PopulateInstance(TModelClass Target, TModelClass Source, IMModelClass TargetOwner, ECloneOperationScope CloningScope = ECloneOperationScope.Slight, bool IsForCloning = false, bool AsActive = true, params string[] MemberNames) { General.ContractRequiresNotNull(Target, Source); if (!AsActive) { MModelClassDefinitor.RegisterPassiveInstance(Target); } /*T * var SouCD = Source.ClassDefinition; * var TarCD = Target.ClassDefinition; * var AreEq = (SouCD == TarCD); * * string PopulatingKind = null; * * var PopulatingPrefix = " ".Replicate(PopulationLevel * 2); * * if (Target is IMModelEntityAgent) * PopulatingKind = "ENT->AGT"; * else * PopulatingKind = "AGT->ENT"; * * Console.WriteLine(PopulatingPrefix + "AT-POPULATE (" + PopulatingKind + ")... Source=[{0}:{1}], Target=[{2}:{3}], ClassDefsAreEqual=[{4}], Scope={5}, Members={6}", * SouCD, Source.GetHashCode(), TarCD, Target.GetHashCode(), AreEq, CloningScope, * (MemberNames == null || MemberNames.Length < 1 ? "<ALL>" : MemberNames.GetConcatenation(null,";"))); */ if (!Target.ClassDefinition.DeclaringType.InheritsFrom(this.DeclaringType)) { throw new UsageAnomaly("The supplied Target instance is not defined by this model class definitor", new DataWagon("target-ClassDef", this).Add("Target instance", Target)); } if (!this.IsCompatibleClassDefinition(Source.ClassDefinition)) { throw new UsageAnomaly("Cannot populate a model class instance from an incompatible one (must be of the same type or descendant of it)", new DataWagon("target-ClassDef", this).Add("source-ClassDef", Source.ClassDefinition)); } // Determine properties to be populated var TargetProperties = (MemberNames == null || MemberNames.Length < 1 ? Source.ClassDefinition.Properties // IMPORTANT: Do not use 'this.Collections' (that way descendants members are not considered!) : Source.ClassDefinition.Properties.Where(prop => prop.TechName.IsOneOf(MemberNames))); // First, populate relevant properties, such as owner referencers var InitialProperties = TargetProperties.Where(prop => prop.ReferencesOwner.HasValue).ToArray(); // PENDING: Treat Sub-Owners properly (reappoint cloned references to the cloned sub-owners, not to the original ones) PopulateProperties(Target, Source, (CloningScope == ECloneOperationScope.DeepAndEquivalent ? null : TargetOwner), CloningScope, IsForCloning, InitialProperties); // Second, populate all collections (some of the remaining properties depends on some of them) var TargetCollections = (MemberNames == null || MemberNames.Length < 1 ? Source.ClassDefinition.Collections // IMPORTANT: Do not use 'this.Collections' (that way descendants members are not considered!) : Source.ClassDefinition.Collections.Where(coll => coll.TechName.IsOneOf(MemberNames))).ToArray(); foreach (var CollDef in TargetCollections) { var TargetCollection = (EditableCollection)CollDef.Read(Target); var SourceCollection = (EditableCollection)CollDef.Read(Source); /*T if (TargetCollection != null && TargetCollection.Name == "MarkerDefinitions") * { * Console.WriteLine(CallingPrefix + "........................................................................"); * Console.WriteLine(CallingPrefix + "MarkerDefs are the same: {0}", TargetCollection.IsEqual(SourceCollection)); * Console.WriteLine(CallingPrefix + "Source: HC={0}, ItemsCnt={1}", SourceCollection.GetHashCode(), SourceCollection.Count); * Console.WriteLine(CallingPrefix + "Target: HC={0}, ItemsCnt={1}", TargetCollection.GetHashCode(), TargetCollection.Count); * } */ /*T if (TargetCollection != null && TargetCollection.Name == "TextFormats") * { * Console.WriteLine("Populating coll TextFormats >>>>>>>>>>>>>>>>>>>>>"); * Console.WriteLine("SourceEnt: {0}, TargetEnt: {1}", Source.GetHashCode(), Target.GetHashCode()); * Console.WriteLine("TextFormats are the same: {0}", TargetCollection.IsEqual(SourceCollection)); * Console.WriteLine("SourceColl: HC={0}, ItemsCnt={1}", SourceCollection.GetHashCode(), SourceCollection.Count); * Console.WriteLine("TargetColl: HC={0}, ItemsCnt={1}", TargetCollection.GetHashCode(), TargetCollection.Count); * Console.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); * } */ if (SourceCollection == null) { CollDef.Write(Target, SourceCollection); continue; } // IMPORTANT: Remember that SourceCollection, if not cloned, // will still be pointing to its original Variating-Instance. var DoClone = CollDef.IsCloneableFor(CloningScope, Source); if (DoClone.Item1) { //T PopulationLevel++; CollDef.Write(Target, SourceCollection.DuplicateFor(Target as IModelEntity, Target, DoClone.Item2)); //T PopulationLevel--; } else { CollDef.Write(Target, SourceCollection); //? Consider: TargetCollection.UpdateContentFrom(SourceCollection); } } // Third, populate the remaining properties (remember that some of these depend on collections) var RemainingProperties = TargetProperties.Where(prop => !prop.ReferencesOwner.HasValue).ToArray(); PopulateProperties(Target, Source, (CloningScope == ECloneOperationScope.DeepAndEquivalent ? null : TargetOwner), CloningScope, IsForCloning, RemainingProperties); if (CloningScope != ECloneOperationScope.DeepAndEquivalent) { // Generate new GUID for Unique-Element's Global-Id. var TargetElement = Target as UniqueElement; if (TargetElement != null) { TargetElement.GlobalId = Guid.NewGuid(); } } return(Target); }