Exemple #1
0
        /// <inheritdoc/>
        protected override object TransformForSerialization(ITypeDescriptor descriptor, object collection)
        {
            var instance = CreatEmptyContainer(descriptor);
            CollectionItemIdentifiers identifier;

            if (!CollectionItemIdHelper.TryGetCollectionItemIds(collection, out identifier))
            {
                identifier = new CollectionItemIdentifiers();
            }
            var i = 0;

            foreach (var item in (IEnumerable)collection)
            {
                ItemId id;
                if (!identifier.TryGet(i, out id))
                {
                    id = ItemId.New();
                    identifier.Add(i, id);
                }
                instance.Add(id, item);
                ++i;
            }

            return(instance);
        }
Exemple #2
0
        protected override void UpdateAssetFromSource(ModelAsset assetToMerge)
        {
            // Create a dictionary containing all new and old materials, favoring old ones to maintain existing references
            var dictionary = assetToMerge.Materials.ToDictionary(x => x.Name, x => x);

            Asset.Materials.ForEach(x => dictionary[x.Name] = x);

            // Create a dictionary mapping existing materials to their item id, to attempt to maintain existing ids and avoid unnecessary changes.
            var ids = CollectionItemIdHelper.GetCollectionItemIds(Asset.Materials).ToDictionary(x => Asset.Materials[(int)x.Key].Name, x => x.Value);

            // Remove currently existing materials, one by one because Quantum does not provide a Clear method.
            var materialsNode = AssetRootNode[nameof(ModelAsset.Materials)].Target;

            while (Asset.Materials.Count > 0)
            {
                materialsNode.Remove(Asset.Materials[0], new NodeIndex(0));
            }

            // Repopulate the list of materials
            for (var i = 0; i < assetToMerge.Materials.Count; ++i)
            {
                // Retrieve or create an id for the material
                ItemId id;
                if (!ids.TryGetValue(assetToMerge.Materials[i].Name, out id))
                {
                    id = ItemId.New();
                }

                // Use Restore to allow to set manually the id.
                materialsNode.Restore(dictionary[assetToMerge.Materials[i].Name], new NodeIndex(i), id);
            }
        }
Exemple #3
0
 private IEnumerable <Item> _getItems(IEnumerable <RawFileData> files, IProgressionHandler progress)
 {
     try
     {
         var filteredFiles = files.Where(file => file.Type == FileType.Model).ToArray();
         var hashes        = filteredFiles.Select(x => x.Hash).ToArray();
         var fileCount     = filteredFiles.Count();
         _logger.LogTrace("creating {0} items: {1}", fileCount, hashes);
         var res = filteredFiles
                   .GroupBy(fileEx => fileEx.HashKey)
                   .Select(fileGroup =>
         {
             var itemId = ItemId.New();
             return(new Item(
                        ItemName.From(fileGroup.First().Path.GetFilenameWithoutExtension().Value),
                        null,
                        new ItemVersion(
                            itemId,
                            fileGroup.Key,
                            new Version(1, 0, 0),
                            fileGroup.Select(file => file.GetFileData())
                            ).AsArray(),
                        itemId));
         }).ToArray();
         progress.Current++;
         _logger.LogInformation("created {0} items with a total of {1} Versions", res.Count(), res.SelectMany(item => item.Versions).Count());
         return(res);
     }
     catch (Exception ex)
     {
         _logger.LogError(ex, "item-creation failed");
         return(null);
     }
 }
        /// <inheritdoc/>
        protected override object TransformForSerialization(ITypeDescriptor descriptor, object collection)
        {
            var dictionaryDescriptor = (DictionaryDescriptor)descriptor;
            var instance             = CreatEmptyContainer(descriptor);

            CollectionItemIdentifiers identifier;

            if (!CollectionItemIdHelper.TryGetCollectionItemIds(collection, out identifier))
            {
                identifier = new CollectionItemIdentifiers();
            }
            var keyWithIdType = typeof(KeyWithId <>).MakeGenericType(dictionaryDescriptor.KeyType);

            foreach (var item in dictionaryDescriptor.GetEnumerator(collection))
            {
                ItemId id;
                if (!identifier.TryGet(item.Key, out id))
                {
                    id = ItemId.New();
                    identifier.Add(item.Key, id);
                }
                var keyWithId = Activator.CreateInstance(keyWithIdType, id, item.Key);
                instance.Add(keyWithId, item.Value);
            }

            return(instance);
        }
 private Item createTestEntity()
 => new Item(
     ItemId.New(),
     (ItemName)"itenName",
     new string[] { "tag 1", "tag 2" }.Select(x => (Tag)x).ToArray(),
     DateTime.Now.AddMinutes(-5),
     DateTime.Now);
Exemple #6
0
 public Item(
     ItemName name,
     IEnumerable <Tag> tags             = null,
     IEnumerable <ItemVersion> versions = null,
     ItemId?id = null)
     : this(id ?? ItemId.New(), name, tags, versions, DateTime.Now)
 {
 }
Exemple #7
0
        public static YamlAssetPath FromMemberPath([NotNull] MemberPath path, object root)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            var result = new YamlAssetPath();
            var clone  = new MemberPath();

            foreach (var item in path.Decompose())
            {
                if (item.MemberDescriptor != null)
                {
                    clone.Push(item.MemberDescriptor);
                    var member = item.MemberDescriptor.Name;
                    result.PushMember(member);
                }
                else
                {
                    object index = null;
                    if (item is MemberPath.ArrayPathItem arrayItem)
                    {
                        clone.Push(arrayItem.Descriptor, arrayItem.Index);
                        index = arrayItem.Index;
                    }
                    else if (item is MemberPath.CollectionPathItem collectionItem)
                    {
                        clone.Push(collectionItem.Descriptor, collectionItem.Index);
                        index = collectionItem.Index;
                    }
                    else if (item is MemberPath.DictionaryPathItem dictionaryItem)
                    {
                        clone.Push(dictionaryItem.Descriptor, dictionaryItem.Key);
                        index = dictionaryItem.Key;
                    }
                    else if (item is MemberPath.SetPathItem setItem)
                    {
                        clone.Push(setItem.Descriptor, setItem.Index);
                        index = setItem.Index;
                    }
                    if (!CollectionItemIdHelper.TryGetCollectionItemIds(clone.GetValue(root), out CollectionItemIdentifiers ids))
                    {
                        result.PushIndex(index);
                    }
                    else
                    {
                        var id = ids[index];
                        // Create a new id if we don't have any so far
                        if (id == ItemId.Empty)
                        {
                            id = ItemId.New();
                        }
                        result.PushItemId(id);
                    }
                }
            }
            return(result);
        }
 private FileItemLink createTestEntity()
 => new FileItemLink(
     FileItemLinkId.New(),
     ItemId.New(),
     new FileInfoHashKey(FileInfoDtoTests.createTestEntity()),
     null,
     new Version(1, 2, 3),
     DateTime.Now.AddMinutes(-5),
     DateTime.Now);
        private ElementInfo GetElement(string name)
        {
            _elementInfoId++;

            return
                (new ElementInfo(
                     new ProductInfo(_elementInfoId, name),
                     ItemId.New(),
                     1));
        }
Exemple #10
0
 public override void VisitDictionary(object dictionary, DictionaryDescriptor descriptor)
 {
     if (ShouldGenerateItemIdCollection(dictionary))
     {
         var itemIds = CollectionItemIdHelper.GetCollectionItemIds(dictionary);
         foreach (var element in descriptor.GetEnumerator(dictionary))
         {
             itemIds.Add(element.Key, ItemId.New());
         }
     }
 }
Exemple #11
0
 public override void VisitArray(Array array, ArrayDescriptor descriptor)
 {
     if (ShouldGenerateItemIdCollection(array))
     {
         var itemIds = CollectionItemIdHelper.GetCollectionItemIds(array);
         for (var i = 0; i < array.Length; ++i)
         {
             itemIds.Add(i, ItemId.New());
         }
     }
     base.VisitArray(array, descriptor);
 }
        public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType)
        {
            var currentNode = (AssetNode)path.RootNode;
            var result      = new YamlAssetPath();
            var i           = 0;

            foreach (var item in path.Path)
            {
                switch (item.Type)
                {
                case GraphNodePath.ElementType.Member:
                    var member = (string)item.Value;
                    result.PushMember(member);
                    currentNode = (AssetNode)((IGraphNode)currentNode).TryGetChild(member);
                    break;

                case GraphNodePath.ElementType.Target:
                    if (i < path.Path.Count - 1)
                    {
                        currentNode = (AssetNode)((IGraphNode)currentNode).Target;
                    }
                    break;

                case GraphNodePath.ElementType.Index:
                    var index = (Index)item.Value;
                    if (inNonIdentifiableType > 0 || currentNode.IsNonIdentifiableCollectionContent)
                    {
                        result.PushIndex(index.Value);
                    }
                    else
                    {
                        var id = currentNode.IndexToId(index);
                        // Create a new id if we don't have any so far
                        if (id == ItemId.Empty)
                        {
                            id = ItemId.New();
                        }
                        result.PushItemId(id);
                    }
                    if (i < path.Path.Count - 1)
                    {
                        currentNode = (AssetNode)((IGraphNode)currentNode).IndexedTarget(index);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                ++i;
            }
            return(result);
        }
 public override void VisitSet(IEnumerable set, SetDescriptor descriptor)
 {
     if (ShouldGenerateItemIdCollection(set))
     {
         IEnumerator enumerator = (set as IEnumerable).GetEnumerator();
         var         itemIds    = CollectionItemIdHelper.GetCollectionItemIds(set);
         while (enumerator.MoveNext())
         {
             itemIds.Add(enumerator.Current, ItemId.New());
         }
     }
     base.VisitSet(set, descriptor);
 }
Exemple #14
0
 public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
 {
     if (ShouldGenerateItemIdCollection(collection))
     {
         var itemIds = CollectionItemIdHelper.GetCollectionItemIds(collection);
         var count = descriptor.GetCollectionCount(collection);
         for (var i = 0; i < count; ++i)
         {
             itemIds.Add(i, ItemId.New());
         }
     }
     base.VisitCollection(collection, descriptor);
 }
        public override void VisitArray(Array array, ArrayDescriptor descriptor)
        {
            CollectionItemIdentifiers itemIds;

            if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(array, out itemIds))
            {
                itemIds = CollectionItemIdHelper.GetCollectionItemIds(array);
                for (var i = 0; i < array.Length; ++i)
                {
                    itemIds.Add(i, ItemId.New());
                }
            }
            base.VisitArray(array, descriptor);
        }
        public override void VisitDictionary(object dictionary, DictionaryDescriptor descriptor)
        {
            CollectionItemIdentifiers itemIds;

            if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(dictionary, out itemIds))
            {
                itemIds = CollectionItemIdHelper.GetCollectionItemIds(dictionary);
                foreach (var element in descriptor.GetEnumerator(dictionary))
                {
                    itemIds.Add(element.Key, ItemId.New());
                }
            }
            base.VisitDictionary(dictionary, descriptor);
        }
        public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
        {
            CollectionItemIdentifiers itemIds;

            if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(collection, out itemIds))
            {
                itemIds = CollectionItemIdHelper.GetCollectionItemIds(collection);
                var count = descriptor.GetCollectionCount(collection);
                for (var i = 0; i < count; ++i)
                {
                    itemIds.Add(i, ItemId.New());
                }
            }
            base.VisitCollection(collection, descriptor);
        }
Exemple #18
0
            /// <summary>
            /// Fixes up the <see cref="CollectionItemIdentifiers"/> of a collection by generating new ids if there are any duplicate.
            /// </summary>
            /// <param name="collection">The collection to fix up.</param>
            /// <remarks>This method doesn't handle collections in derived objects that will be desynchronized afterwards.</remarks>
            private void Fixup(object collection)
            {
                CollectionItemIdentifiers itemIds;

                if (CollectionItemIdHelper.TryGetCollectionItemIds(collection, out itemIds))
                {
                    var items     = new HashSet <ItemId>();
                    var localCopy = new CollectionItemIdentifiers();
                    itemIds.CloneInto(localCopy, null);
                    foreach (var id in localCopy)
                    {
                        if (!items.Add(id.Value))
                        {
                            logger?.Warning($"Duplicate item identifier [{id.Value}] in collection {CurrentPath} of asset [{assetItem.Location}]. Generating a new identifier to remove the duplicate entry.");
                            itemIds[id.Key] = ItemId.New();
                        }
                    }
                }
            }
        public TestEnvironmentObject(TestEnvironmentCreateContext createContext, ITestMocks mocks)
        {
            _productsTable = createContext.Products;

            ElementInfos = new TestDbObjectList <string, ElementInfo>(
                k =>
            {
                var p = Products.Get(k);
                return(new ElementInfo(p.Info, ItemId.New(), 1));
            });

            //Prices = new Dictionary<string, ElementPrice>();

            SalesOrderEntities = createContext.Documents.SalesOrderEntities;

            DocumentFactories = new DocumentFactoryProvider(this);

            Products = new ProductsProvider(createContext.Products);

            Mocks = mocks;
        }
Exemple #20
0
        protected override void UpdateAssetFromSource(SkeletonAsset assetToMerge)
        {
            // Create a dictionary containing all new and old nodes, favoring old ones to maintain existing references
            var dictionary = assetToMerge.Nodes.ToDictionary(x => x.Name, x => x);

            Asset.Nodes.ForEach(x => dictionary[x.Name] = x);

            // Create a dictionary mapping existing materials to their item id, to attempt to maintain existing ids and avoid unnecessary changes.
            var ids = CollectionItemIdHelper.GetCollectionItemIds(Asset.Nodes).ToDictionary(x => Asset.Nodes[(int)x.Key].Name, x => x.Value);

            // Remove currently existing nodes, one by one because Quantum does not provide a Clear method.
            var skeletonNodes = AssetRootNode[nameof(SkeletonAsset.Nodes)].Target;

            while (Asset.Nodes.Count > 0)
            {
                skeletonNodes.Remove(Asset.Nodes[0], new NodeIndex(0));
            }

            // Repopulate the list of nodes
            for (var i = 0; i < assetToMerge.Nodes.Count; ++i)
            {
                // Information such as Depth has to come from the new asset
                var newNode = assetToMerge.Nodes[i];
                // Information such as Preserve should come from the merged dictionary.
                newNode.Preserve = dictionary[assetToMerge.Nodes[i].Name].Preserve;

                // Retrieve or create an id for the node
                ItemId id;
                if (!ids.TryGetValue(assetToMerge.Nodes[i].Name, out id))
                {
                    id = ItemId.New();
                }

                skeletonNodes.Restore(newNode, new NodeIndex(i), id);
            }
        }
Exemple #21
0
 public Item()
 {
     Id = ItemId.New();
 }
        internal void OnItemChanged(object sender, ItemChangeEventArgs e)
        {
            var value = node.Retrieve();

            if (!CollectionItemIdHelper.HasCollectionItemIds(value))
            {
                return;
            }

            // Make sure that we have item ids everywhere we're supposed to.
            AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Collection.Retrieve());

            // Clear the cached item identifier collection.
            collectionItemIdentifiers = null;

            // Create new ids for collection items
            var baseNode             = (AssetObjectNode)BaseNode;
            var removedId            = ItemId.Empty;
            var isOverriding         = baseNode != null && !PropertyGraph.UpdatingPropertyFromBase;
            var itemIds              = CollectionItemIdHelper.GetCollectionItemIds(value);
            var collectionDescriptor = node.Descriptor as CollectionDescriptor;

            switch (e.ChangeType)
            {
            case ContentChangeType.CollectionUpdate:
                break;

            case ContentChangeType.CollectionAdd:
            {
                // Compute the id we will add for this item
                var itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New();
                // Add the id to the proper location (insert or add)
                if (collectionDescriptor != null)
                {
                    if (e.Index == Index.Empty)
                    {
                        throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection.");
                    }

                    itemIds.Insert(e.Index.Int, itemId);
                }
                else
                {
                    itemIds[e.Index.Value] = itemId;
                }
                break;
            }

            case ContentChangeType.CollectionRemove:
            {
                var itemId = itemIds[e.Index.Value];
                // update isOverriding, it should be true only if the item being removed exist in the base.
                isOverriding = isOverriding && baseNode.HasId(itemId);
                removedId    = collectionDescriptor != null?itemIds.DeleteAndShift(e.Index.Int, isOverriding) : itemIds.Delete(e.Index.Value, isOverriding);

                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }


            // Don't update override if propagation from base is disabled.
            if (PropertyGraph?.Container?.PropagateChangesFromBase == false)
            {
                return;
            }

            // Mark it as New if it does not come from the base
            if (!ResettingOverride)
            {
                if (e.ChangeType != ContentChangeType.CollectionRemove && isOverriding)
                {
                    // If it's an add or an updating, there is no scenario where we can be "un-overriding" without ResettingOverride, so we pass true.
                    OverrideItem(true, e.Index);
                }
                else if (e.ChangeType == ContentChangeType.CollectionRemove)
                {
                    // If it's a delete, it could be an item that was previously added as an override, and that should not be marked as "deleted-overridden", so we pass isOverriding
                    OverrideDeletedItem(isOverriding, removedId);
                }
            }
        }
Exemple #23
0
        /// <inheritdoc/>
        protected override void TransformObjectAfterRead(ref ObjectContext objectContext)
        {
            if (!AreCollectionItemsIdentifiable(ref objectContext))
            {
                base.TransformObjectAfterRead(ref objectContext);
                return;
            }

            var info = (InstanceInfo)objectContext.Properties[InstanceInfoKey];

            // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item
            if (info.Instance != null)
            {
                ICollection <ItemId> deletedItems;
                objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems);
                TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, info.Instance, deletedItems);
            }
            objectContext.Instance = info.Instance;

            var enumerable = objectContext.Instance as IEnumerable;

            if (enumerable != null)
            {
                var ids        = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance);
                var descriptor = (DictionaryDescriptor)info.Descriptor;
                foreach (var item in descriptor.GetEnumerator(objectContext.Instance))
                {
                    ItemId id;
                    if (ids.TryGet(item.Key, out id) && id != ItemId.Empty)
                    {
                        continue;
                    }

                    var guid = item.Value != null?IdentifiableHelper.GetId(item.Value) : Guid.NewGuid();

                    ids[item.Key] = guid != Guid.Empty ? new ItemId(guid.ToByteArray()) : ItemId.New();
                }
            }

            base.TransformObjectAfterRead(ref objectContext);
        }
Exemple #24
0
        private void ContentChanged(object sender, ContentChangeEventArgs e)
        {
            // Make sure that we have item ids everywhere we're supposed to.
            AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Content.Retrieve());

            var node = (AssetNode)e.Content.OwnerNode;

            if (node.IsNonIdentifiableCollectionContent)
            {
                return;
            }

            // Create new ids for collection items
            var baseNode     = (AssetNode)BaseContent?.OwnerNode;
            var isOverriding = !baseNode?.contentUpdating == true;
            var removedId    = ItemId.Empty;

            switch (e.ChangeType)
            {
            case ContentChangeType.ValueChange:
                break;

            case ContentChangeType.CollectionAdd:
            {
                var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor;
                var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                // Compute the id we will add for this item
                ItemId itemId;
                if (baseNode?.contentUpdating == true)
                {
                    var baseCollection = baseNode.Content.Retrieve();
                    var baseIds        = CollectionItemIdHelper.GetCollectionItemIds(baseCollection);
                    itemId = itemIds.FindMissingId(baseIds);
                }
                else
                {
                    itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New();
                }
                // Add the id to the proper location (insert or add)
                if (collectionDescriptor != null)
                {
                    if (e.Index != Index.Empty)
                    {
                        itemIds.Insert(e.Index.Int, itemId);
                    }
                    else
                    {
                        throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection.");
                    }
                }
                else
                {
                    itemIds[e.Index.Value] = itemId;
                }
            }
            break;

            case ContentChangeType.CollectionRemove:
            {
                var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor;
                if (collectionDescriptor != null)
                {
                    var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                    removedId = itemIds.DeleteAndShift(e.Index.Int, isOverriding);
                }
                else
                {
                    var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                    removedId = itemIds.Delete(e.Index.Value, isOverriding);
                }
            }
            break;

            default:
                throw new ArgumentOutOfRangeException();
            }


            // Don't update override if propagation from base is disabled.
            if (PropertyGraph?.Container?.PropagateChangesFromBase == false)
            {
                return;
            }

            // Mark it as New if it does not come from the base
            if (!baseNode?.contentUpdating == true && !ResettingOverride)
            {
                if (e.ChangeType != ContentChangeType.CollectionRemove)
                {
                    if (e.Index == Index.Empty)
                    {
                        OverrideContent(!ResettingOverride);
                    }
                    else
                    {
                        OverrideItem(!ResettingOverride, e.Index);
                    }
                }
                else
                {
                    OverrideDeletedItem(true, removedId);
                }
            }
        }
Exemple #25
0
        public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType)
        {
            var currentNode = (IAssetNode)path.RootNode;
            var result      = new YamlAssetPath();
            var i           = 0;

            foreach (var item in path.Path)
            {
                switch (item.Type)
                {
                case GraphNodePath.ElementType.Member:
                    var member = (string)item.Value;
                    result.PushMember(member);
                    var objectNode = currentNode as IObjectNode;
                    if (objectNode == null)
                    {
                        throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                    }
                    currentNode = (IAssetNode)objectNode.TryGetChild(member);
                    break;

                case GraphNodePath.ElementType.Target:
                    if (i < path.Path.Count - 1)
                    {
                        var targetingMemberNode = currentNode as IMemberNode;
                        if (targetingMemberNode == null)
                        {
                            throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
                        }
                        currentNode = (IAssetNode)targetingMemberNode.Target;
                    }
                    break;

                case GraphNodePath.ElementType.Index:
                    var index      = (Index)item.Value;
                    var memberNode = currentNode as AssetMemberNode;
                    if (memberNode == null)
                    {
                        throw new InvalidOperationException($"An AssetMemberNode was expected when processing the path [{path}]");
                    }
                    if (inNonIdentifiableType > 0 || memberNode.IsNonIdentifiableCollectionContent)
                    {
                        result.PushIndex(index.Value);
                    }
                    else
                    {
                        var id = memberNode.IndexToId(index);
                        // Create a new id if we don't have any so far
                        if (id == ItemId.Empty)
                        {
                            id = ItemId.New();
                        }
                        result.PushItemId(id);
                    }
                    if (i < path.Path.Count - 1)
                    {
                        currentNode = (IAssetNode)currentNode.IndexedTarget(index);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                ++i;
            }
            return(result);
        }
Exemple #26
0
        /// <inheritdoc/>
        protected override void TransformObjectAfterRead(ref ObjectContext objectContext)
        {
            InstanceInfo info;

            if (!objectContext.Properties.TryGetValue(InstanceInfoKey, out info))
            {
                base.TransformObjectAfterRead(ref objectContext);

                if (AreCollectionItemsIdentifiable(ref objectContext))
                {
                    // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item
                    var enumerable = objectContext.Instance as IEnumerable;
                    if (enumerable != null)
                    {
                        var ids = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance);
                        var i   = 0;
                        foreach (var item in enumerable)
                        {
                            var id = item != null?IdentifiableHelper.GetId(item) : Guid.NewGuid();

                            ids[i] = id != Guid.Empty ? new ItemId(id.ToByteArray()) : ItemId.New();
                            ++i;
                        }
                    }
                }
                return;
            }

            var instance = info.Instance ?? objectContext.SerializerContext.ObjectFactory.Create(info.Descriptor.Type);
            ICollection <ItemId> deletedItems;

            objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems);
            TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, instance, deletedItems);
            objectContext.Instance = instance;

            base.TransformObjectAfterRead(ref objectContext);
        }
        public static YamlAssetPath ConvertPath([NotNull] GraphNodePath path, int inNonIdentifiableType = 0)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            var currentNode = (IAssetNode)path.RootNode;
            var result      = new YamlAssetPath();
            var i           = 0;

            foreach (var item in path.Path)
            {
                switch (item.Type)
                {
                case GraphNodePath.ElementType.Member:
                {
                    var member = item.Name;
                    result.PushMember(member);
                    var objectNode = currentNode as IObjectNode;
                    if (objectNode == null)
                    {
                        throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                    }
                    currentNode = (IAssetNode)objectNode.TryGetChild(member);
                    break;
                }

                case GraphNodePath.ElementType.Target:
                {
                    if (i < path.Path.Count - 1)
                    {
                        var targetingMemberNode = currentNode as IMemberNode;
                        if (targetingMemberNode == null)
                        {
                            throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]");
                        }
                        currentNode = (IAssetNode)targetingMemberNode.Target;
                    }
                    break;
                }

                case GraphNodePath.ElementType.Index:
                {
                    var index      = item.Index;
                    var objectNode = currentNode as AssetObjectNode;
                    if (objectNode == null)
                    {
                        throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]");
                    }
                    if (inNonIdentifiableType > 0 || !CollectionItemIdHelper.HasCollectionItemIds(objectNode.Retrieve()))
                    {
                        result.PushIndex(index.Value);
                    }
                    else
                    {
                        var id = objectNode.IndexToId(index);
                        // Create a new id if we don't have any so far
                        if (id == ItemId.Empty)
                        {
                            id = ItemId.New();
                        }
                        result.PushItemId(id);
                    }
                    if (i < path.Path.Count - 1)
                    {
                        currentNode = (IAssetNode)objectNode.IndexedTarget(index);
                    }
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }
                ++i;
            }
            return(result);
        }