Пример #1
0
        /// <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);
        }
Пример #2
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);
        }
Пример #3
0
        public void Restore(object restoredItem, ItemId id)
        {
            CollectionItemIdentifiers oldIds = null;
            CollectionItemIdentifiers ids;

            if (!IsNonIdentifiableCollectionContent && TryGetCollectionItemIds(Content.Retrieve(), out ids))
            {
                // Remove the item from deleted ids if it was here.
                ids.UnmarkAsDeleted(id);
                // Get a clone of the CollectionItemIdentifiers before we add back the item.
                oldIds = new CollectionItemIdentifiers();
                ids.CloneInto(oldIds, null);
            }
            // Actually restore the item.
            Content.Add(restoredItem);

            if (TryGetCollectionItemIds(Content.Retrieve(), out ids) && oldIds != null)
            {
                // Find the new id that has been generated by the Add
                var idToReplace = oldIds.FindMissingId(ids);
                if (idToReplace == ItemId.Empty)
                {
                    throw new InvalidOperationException("No ItemId to replace has been generated.");
                }
            }
        }
        /// <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;
        }
Пример #5
0
 public AssetObjectNodeExtended([NotNull] IAssetObjectNodeInternal node)
 {
     this.node                 = node;
     contents                  = new Dictionary <string, IGraphNode>();
     itemOverrides             = new Dictionary <ItemId, OverrideType>();
     keyOverrides              = new Dictionary <ItemId, OverrideType>();
     disconnectedDeletedIds    = new HashSet <ItemId>();
     collectionItemIdentifiers = null;
     restoringId               = ItemId.Empty;
     PropertyGraph             = null;
     BaseNode                  = null;
     ResettingOverride         = false;
 }
Пример #6
0
        private bool TryGetCollectionItemIds(object instance, out CollectionItemIdentifiers itemIds)
        {
            if (collectionItemIdentifiers != null)
            {
                itemIds = collectionItemIdentifiers;
                return(true);
            }

            var result = CollectionItemIdHelper.TryGetCollectionItemIds(instance, out collectionItemIdentifiers);

            itemIds = collectionItemIdentifiers;
            return(result);
        }
        public static CollectionItemIdentifiers GetCollectionItemIds(object instance)
        {
            var shadow = ShadowObject.GetOrCreate(instance);
            object result;
            if (shadow.TryGetValue(CollectionItemIdKey, out result))
            {
                return (CollectionItemIdentifiers)result;
            }

            var itemIds = new CollectionItemIdentifiers();
            shadow.Add(CollectionItemIdKey, itemIds);
            return itemIds;
        }
        public static bool TryGetCollectionItemIds(object instance, out CollectionItemIdentifiers itemIds)
        {
            var shadow = ShadowObject.Get(instance);
            if (shadow == null)
            {
                itemIds = null;
                return false;
            }

            object result;
            itemIds = shadow.TryGetValue(CollectionItemIdKey, out result) ? (CollectionItemIdentifiers)result : null;
            return result != null;
        }
Пример #9
0
        public static CollectionItemIdentifiers GetCollectionItemIds(object instance)
        {
            var    shadow = ShadowObject.GetOrCreate(instance);
            object result;

            if (shadow.TryGetValue(CollectionItemIdKey, out result))
            {
                return((CollectionItemIdentifiers)result);
            }

            var itemIds = new CollectionItemIdentifiers();

            shadow.Add(CollectionItemIdKey, itemIds);
            return(itemIds);
        }
Пример #10
0
        public static bool TryGetCollectionItemIds(object instance, out CollectionItemIdentifiers itemIds)
        {
            var shadow = ShadowObject.Get(instance);

            if (shadow == null)
            {
                itemIds = null;
                return(false);
            }

            object result;

            itemIds = shadow.TryGetValue(CollectionItemIdKey, out result) ? (CollectionItemIdentifiers)result : null;
            return(result != null);
        }
 /// <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();
             }
         }
     }
 }
Пример #12
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();
                        }
                    }
                }
            }
Пример #13
0
        private void ContentChanged(object sender, MemberNodeChangeEventArgs e)
        {
            // Make sure that we have item ids everywhere we're supposed to.
            AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Member.Retrieve());

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

            var node = (AssetMemberNode)e.Member;

            if (node.IsNonIdentifiableCollectionContent)
            {
                return;
            }

            // Create new ids for collection items
            var baseNode     = (AssetMemberNode)BaseContent;
            var isOverriding = baseNode != null && !PropertyGraph.UpdatingPropertyFromBase;
            var removedId    = ItemId.Empty;

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

            case ContentChangeType.CollectionAdd:
            {
                var collectionDescriptor = e.Member.Descriptor as CollectionDescriptor;
                var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Member.Retrieve());
                // Compute the id we will add for this item
                ItemId itemId;
                if (baseNode != null && PropertyGraph.UpdatingPropertyFromBase)
                {
                    var baseCollection = baseNode.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.Member.Descriptor as CollectionDescriptor;
                if (collectionDescriptor != null)
                {
                    var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Member.Retrieve());
                    removedId = itemIds.DeleteAndShift(e.Index.Int, isOverriding);
                }
                else
                {
                    var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Member.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 != null && !PropertyGraph.UpdatingPropertyFromBase && !ResettingOverride)
            {
                if (e.ChangeType != ContentChangeType.CollectionRemove)
                {
                    if (e.Index == Index.Empty)
                    {
                        OverrideContent(!ResettingOverride);
                    }
                    else
                    {
                        OverrideItem(!ResettingOverride, e.Index);
                    }
                }
                else
                {
                    OverrideDeletedItem(true, removedId);
                }
            }
        }
Пример #14
0
        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);
                }
            }
        }
Пример #15
0
        public void Restore(object restoredItem, ItemId id)
        {
            CollectionItemIdentifiers oldIds = null;
            CollectionItemIdentifiers ids;
            if (!IsNonIdentifiableCollectionContent && TryGetCollectionItemIds(Content.Retrieve(), out ids))
            {
                // Remove the item from deleted ids if it was here.
                ids.UnmarkAsDeleted(id);
                // Get a clone of the CollectionItemIdentifiers before we add back the item.
                oldIds = new CollectionItemIdentifiers();
                ids.CloneInto(oldIds, null);
            }
            // Actually restore the item.
            Content.Add(restoredItem);

            if (TryGetCollectionItemIds(Content.Retrieve(), out ids) && oldIds != null)
            {
                // Find the new id that has been generated by the Add
                var idToReplace = oldIds.FindMissingId(ids);
                if (idToReplace == ItemId.Empty)
                    throw new InvalidOperationException("No ItemId to replace has been generated.");
            }
        }
Пример #16
0
        public bool TryGetCollectionItemIds(object instance, out CollectionItemIdentifiers itemIds)
        {
            if (collectionItemIdentifiers != null)
            {
                itemIds = collectionItemIdentifiers;
                return true;
            }

            var result = CollectionItemIdHelper.TryGetCollectionItemIds(instance, out collectionItemIdentifiers);
            itemIds = collectionItemIdentifiers;
            return result;
        }
        /// <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;
        }