예제 #1
0
 /// <summary>
 /// Merges the <paramref name="other"/> hierarchy into this hierarchy.
 /// </summary>
 /// <remarks>
 /// This method does not check whether the two hierarchies have independent parts and will fail otherwise.
 /// </remarks>
 /// <typeparam name="TAssetPartDesign">The type used for the design information of a part.</typeparam>
 /// <typeparam name="TAssetPart">The type used for the actual parts,</typeparam>
 /// <param name="asset">This hierarchy.</param>
 /// <param name="other">The other hierarchy which parts will added to this hierarchy.</param>
 public static void MergeInto <TAssetPartDesign, TAssetPart>([NotNull] this AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> asset,
                                                             [NotNull] AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> other)
     where TAssetPartDesign : class, IAssetPartDesign <TAssetPart>
     where TAssetPart : class, IIdentifiable
 {
     if (asset == null)
     {
         throw new ArgumentNullException(nameof(asset));
     }
     asset.RootParts.AddRange(other.RootParts);
     foreach (var part in other.Parts)
     {
         asset.Parts.Add(part.Value);
     }
 }
예제 #2
0
        /// <summary>
        /// Clones a sub-hierarchy of this asset.
        /// </summary>
        /// <param name="sourceRootIds">The ids that are the roots of the sub-hierarchies to clone.</param>
        /// <param name="cleanReference">If true, any reference to a part external to the cloned hierarchy will be set to null.</param>
        /// <param name="idRemapping">A dictionary containing the mapping of ids from the source parts to the new parts.</param>
        /// <returns>A <see cref="AssetCompositeHierarchyData{TAssetPartDesign, TAssetPart}"/> corresponding to the cloned parts.</returns>
        /// <remarks>The parts passed to this methods must be independent in the hierarchy.</remarks>
        public AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> CloneSubHierarchies(IEnumerable <Guid> sourceRootIds, bool cleanReference, out Dictionary <Guid, Guid> idRemapping)
        {
            // Note: Instead of copying the whole asset (with its potentially big hierarchy),
            // we first copy the asset only (without the hierarchy), then the sub-hierarchy to extract.
            var subTreeHierarchy = new AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart>();

            foreach (var rootId in sourceRootIds)
            {
                if (!Hierarchy.Parts.ContainsKey(rootId))
                {
                    throw new ArgumentException(@"The source root parts must be parts of this asset.", nameof(sourceRootIds));
                }

                subTreeHierarchy.RootPartIds.Add(rootId);

                subTreeHierarchy.Parts.Add(Hierarchy.Parts[rootId]);
                foreach (var subTreePart in EnumerateChildParts(Hierarchy.Parts[rootId].Part, true))
                {
                    subTreeHierarchy.Parts.Add(Hierarchy.Parts[subTreePart.Id]);
                }
            }
            // clone the parts of the sub-tree
            var clonedHierarchy = AssetCloner.Clone(subTreeHierarchy);

            foreach (var rootEntity in clonedHierarchy.RootPartIds)
            {
                PostClonePart(clonedHierarchy.Parts[rootEntity].Part);
            }
            if (cleanReference)
            {
                ClearPartReferences(clonedHierarchy);
            }
            // Generate part mapping
            idRemapping = new Dictionary <Guid, Guid>();
            foreach (var partDesign in clonedHierarchy.Parts)
            {
                // Generate new Id
                var newId = Guid.NewGuid();
                // Update mappings
                idRemapping.Add(partDesign.Part.Id, newId);
                // Update part with new id
                partDesign.Part.Id = newId;
            }
            // Rewrite part references
            // Should we nullify invalid references?
            AssetPartsAnalysis.RemapPartsId(clonedHierarchy, idRemapping);
            return(clonedHierarchy);
        }
        public AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> GenerateHierarchyFromPart([NotNull] TAssetPartDesign partDesign)
        {
            if (partDesign == null)
            {
                throw new ArgumentNullException(nameof(partDesign));
            }
            var result = new AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart>();

            foreach (var child in EnumerateChildParts(partDesign, Hierarchy, true))
            {
                result.Parts.Add(child);
            }
            result.Parts.Add(partDesign);
            result.RootPartIds.Add(partDesign.Part.Id);
            return(result);
        }
예제 #4
0
 /// <summary>
 /// Enumerates design parts that are children of the given design part.
 /// </summary>
 /// <param name="partDesign">The design part for which to enumerate child parts.</param>
 /// <param name="hierarchyData">The hierarchy data object in which the design parts can be retrieved.</param>
 /// <param name="isRecursive">If true, child design parts will be enumerated recursively.</param>
 /// <returns>A sequence containing the child design parts of the given design part.</returns>
 public IEnumerable<TAssetPartDesign> EnumerateChildParts(TAssetPartDesign partDesign, AssetCompositeHierarchyData<TAssetPartDesign, TAssetPart> hierarchyData, bool isRecursive)
 {
     return EnumerateChildParts(partDesign.Part, isRecursive).Select(e => hierarchyData.Parts[e.Id]);
 }
        /// <summary>
        /// Clones a sub-hierarchy of this asset.
        /// </summary>
        /// <param name="sourceRootIds">The ids that are the roots of the sub-hierarchies to clone.</param>
        /// <param name="cleanReference">If true, any reference to a part external to the cloned hierarchy will be set to null.</param>
        /// <param name="generateNewIdsForIdentifiableObjects">If true, the cloned objects that implement <see cref="IIdentifiable"/> will have new ids.</param>
        /// <param name="idRemapping">A dictionary containing the remapping of <see cref="IIdentifiable.Id"/> if <see cref="AssetClonerFlags.GenerateNewIdsForIdentifiableObjects"/> has been passed to the cloner.</param>
        /// <returns>A <see cref="AssetCompositeHierarchyData{TAssetPartDesign, TAssetPart}"/> corresponding to the cloned parts.</returns>
        /// <remarks>The parts passed to this methods must be independent in the hierarchy.</remarks>
        public AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> CloneSubHierarchies(IEnumerable <Guid> sourceRootIds, bool cleanReference, bool generateNewIdsForIdentifiableObjects, bool generateNewBaseInstanceIds, out Dictionary <Guid, Guid> idRemapping)
        {
            // Note: Instead of copying the whole asset (with its potentially big hierarchy),
            // we first copy the asset only (without the hierarchy), then the sub-hierarchy to extract.
            var subTreeHierarchy = new AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart>();

            foreach (var rootId in sourceRootIds)
            {
                if (!Hierarchy.Parts.ContainsKey(rootId))
                {
                    throw new ArgumentException(@"The source root parts must be parts of this asset.", nameof(sourceRootIds));
                }

                subTreeHierarchy.RootPartIds.Add(rootId);

                subTreeHierarchy.Parts.Add(Hierarchy.Parts[rootId]);
                foreach (var subTreePart in EnumerateChildParts(Hierarchy.Parts[rootId].Part, true))
                {
                    subTreeHierarchy.Parts.Add(Hierarchy.Parts[subTreePart.Id]);
                }
            }
            // clone the parts of the sub-tree
            var clonedHierarchy = AssetCloner.Clone(subTreeHierarchy, generateNewIdsForIdentifiableObjects ? AssetClonerFlags.GenerateNewIdsForIdentifiableObjects : AssetClonerFlags.None, out idRemapping);

            // Remap ids from the root id collection to the new ids generated during cloning
            AssetPartsAnalysis.RemapPartsId(clonedHierarchy, idRemapping);

            foreach (var rootEntity in clonedHierarchy.RootPartIds)
            {
                PostClonePart(clonedHierarchy.Parts[rootEntity].Part);
            }
            if (cleanReference)
            {
                // set to null reference outside of the sub-tree
                var tempAsset = (AssetCompositeHierarchy <TAssetPartDesign, TAssetPart>)Activator.CreateInstance(GetType());
                tempAsset.Hierarchy = clonedHierarchy;
                tempAsset.FixupPartReferences();
            }
            else
            {
                // restore initial ids for reference outside of the subtree, so they can be fixed up later.
                var tempAsset = (AssetCompositeHierarchy <TAssetPartDesign, TAssetPart>)Activator.CreateInstance(GetType());
                tempAsset.Hierarchy = clonedHierarchy;
                var visitor = new AssetCompositePartReferenceCollector();
                visitor.VisitAsset(tempAsset);
                var references        = visitor.Result;
                var revertedIdMapping = idRemapping.ToDictionary(x => x.Value, x => x.Key);
                foreach (var referencedPart in references.Select(x => x.AssetPart).OfType <IIdentifiable>())
                {
                    var realPart = tempAsset.ResolvePartReference(referencedPart);
                    if (realPart == null)
                    {
                        referencedPart.Id = revertedIdMapping[referencedPart.Id];
                    }
                }
            }

            if (generateNewBaseInstanceIds)
            {
                AssetPartsAnalysis.GenerateNewBaseInstanceIds(clonedHierarchy);
            }

            return(clonedHierarchy);
        }
예제 #6
0
 /// <summary>
 /// Clears the part references on the cloned hierarchy. Called by <see cref="CloneSubHierarchies"/> when parameter <i>cleanReference</i> is <c>true</c>.
 /// </summary>
 /// <param name="clonedHierarchy">The cloned hierarchy.</param>
 protected virtual void ClearPartReferences(AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> clonedHierarchy)
 {
     // default implementation does nothing
 }
예제 #7
0
 public static IEnumerable <TAssetPartDesign> EnumerateRootPartDesigns <TAssetPartDesign, TAssetPart>([NotNull] this AssetCompositeHierarchyData <TAssetPartDesign, TAssetPart> asset)
     where TAssetPartDesign : class, IAssetPartDesign <TAssetPart>
     where TAssetPart : class, IIdentifiable
 {
     if (asset == null)
     {
         throw new ArgumentNullException(nameof(asset));
     }
     return(asset.RootParts.Select(x => asset.Parts[x.Id]));
 }