public void TestCollectionDescriptor()
        {
            var attributeRegistry = new AttributeRegistry();
            var factory           = new TypeDescriptorFactory(attributeRegistry);
            var descriptor        = new CollectionDescriptor(factory, typeof(List <string>), false, new DefaultNamingConvention());

            descriptor.Initialize(new DefaultKeyComparer());

            // No Capacity as a member
            Assert.AreEqual(0, descriptor.Count);
            Assert.True(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(string), descriptor.ElementType);

            descriptor = new CollectionDescriptor(factory, typeof(NonPureCollection), false,
                                                  new DefaultNamingConvention());
            descriptor.Initialize(new DefaultKeyComparer());

            // Has name as a member
            Assert.AreEqual(1, descriptor.Count);
            Assert.False(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(int), descriptor.ElementType);

            descriptor = new CollectionDescriptor(factory, typeof(ArrayList), false, new DefaultNamingConvention());
            descriptor.Initialize(new DefaultKeyComparer());

            // No Capacity
            Assert.AreEqual(0, descriptor.Count);
            Assert.True(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(object), descriptor.ElementType);
        }
            public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
                var assetReference = item as AssetReference;

                // TODO force support for IList in CollectionDescriptor
                if (assetReference != null)
                {
                    var list = (IList)collection;
                    AddLink(assetReference, (guid, location) => list[index] = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location));
                }
                else
                {
                    var assetBase = item as AssetBase;
                    if (assetBase != null)
                    {
                        var list = (IList)collection;
                        AddLink(assetBase, (guid, location) => list[index] = new AssetBase(location, assetBase.Asset));
                    }
                    else if (item is UFile)
                    {
                        var list = (IList)collection;
                        AddLink(item, (guid, location) => list[index] = new UFile(location));
                    }
                    else if (item is UDirectory)
                    {
                        var list = (IList)collection;
                        AddLink(item, (guid, location) => list[index] = new UDirectory(location));
                    }
                }
            }
Beispiel #3
0
        private static bool IsComparableType(bool hasMembers, Type type)
        {
            // A comparable type doesn't have any members, is not a collection or dictionary or array.
            bool isComparableType = !hasMembers && !CollectionDescriptor.IsCollection(type) && !DictionaryDescriptor.IsDictionary(type) && !type.IsArray;

            return(isComparableType);
        }
Beispiel #4
0
            public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
                var assetReference    = item as AssetReference;
                var assetBase         = item as AssetBase;
                var attachedReference = item != null?AttachedReferenceManager.GetAttachedReference(item) : null;

                // TODO force support for IList in CollectionDescriptor
                if (assetReference != null)
                {
                    var list = (IList)collection;
                    AddLink(assetReference, (guid, location) => list[index] = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location));
                }
                else if (assetBase != null)
                {
                    var list = (IList)collection;
                    AddLink(assetBase, (guid, location) => list[index] = new AssetBase(location, assetBase.Asset));
                }
                else if (attachedReference != null)
                {
                    var list = (IList)collection;
                    AddLink(new AttachedContentReference(attachedReference), (guid, location) => list[index] = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(descriptor.ElementType, guid.Value, location) : null);
                }
                else if (item is UFile)
                {
                    var list = (IList)collection;
                    AddLink(item, (guid, location) => list[index] = new UFile(location));
                }
                else if (item is UDirectory)
                {
                    var list = (IList)collection;
                    AddLink(item, (guid, location) => list[index] = new UDirectory(location));
                }
            }
Beispiel #5
0
        public void TestCollectionDescriptor()
        {
            var attributeRegistry = new AttributeRegistry();
            var descriptor        = new CollectionDescriptor(attributeRegistry, typeof(List <string>), false);

            descriptor.Initialize();

            // No Capacity as a member
            Assert.AreEqual(0, descriptor.Count);
            Assert.True(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(string), descriptor.ElementType);

            descriptor = new CollectionDescriptor(attributeRegistry, typeof(NonPureCollection), false);
            descriptor.Initialize();

            // Has name as a member
            Assert.AreEqual(1, descriptor.Count);
            Assert.False(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(int), descriptor.ElementType);

            descriptor = new CollectionDescriptor(attributeRegistry, typeof(ArrayList), false);
            descriptor.Initialize();

            // No Capacity
            Assert.AreEqual(0, descriptor.Count);
            Assert.True(descriptor.IsPureCollection);
            Assert.AreEqual(typeof(object), descriptor.ElementType);
        }
 /// <inheritdoc/>
 public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
 {
     // Don't visit items unless they are primitive or enumerable (collections within collections)
     if (IsPrimitiveType(descriptor.ElementType, false) || IsEnumerable(descriptor.ElementType))
     {
         base.VisitCollection(collection, descriptor);
     }
 }
            public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                if (ProcessObject(item, descriptor.ElementType))
                {
                    return;
                }

                base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
            }
Beispiel #8
0
        private static IEnumerable EnumerateCollection([NotNull] object collection, [NotNull] CollectionDescriptor collectionDescriptor)
        {
            var count = collectionDescriptor.GetCollectionCount(collection);

            for (var i = 0; i < count; i++)
            {
                yield return(collectionDescriptor.GetValue(collection, i));
            }
        }
 /// <inheritdoc/>
 public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
 {
     if (CurrentPath.Match(MemberPath))
     {
         VisitAssetMember(item, itemDescriptor);
     }
     else
     {
         base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
     }
 }
Beispiel #10
0
        public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
        {
            var node = stackItems.Peek();
            // TODO modify DataVisitorBase to allow only IList?
            var newNode = new DataVisitListItem(index, item, itemDescriptor);

            AddItem(node, newNode);

            stackItems.Push(newNode);
            base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
            stackItems.Pop();
        }
 /// <inheritdoc/>
 public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
 {
     if (!descriptor.HasIndexerAccessors)
     {
         return; // HashSet or some other set, skip this (don't crash loading the project though, geez!)
     }
     // Don't visit items unless they are primitive or enumerable (collections within collections)
     if (IsCollection(descriptor.ElementType))
     {
         base.VisitCollection(collection, descriptor);
     }
 }
Beispiel #12
0
        /// <inheritdoc/>
        public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
        {
            if (!descriptor.HasIndexerAccessors)
            {
                throw new NotSupportedException("Collections that do not have indexer accessors are not supported in Quantum.");
            }

            // Don't visit items unless they are primitive or enumerable (collections within collections)
            if (IsCollection(descriptor.ElementType))
            {
                base.VisitCollection(collection, descriptor);
            }
        }
Beispiel #13
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);
 }
Beispiel #14
0
        public DemoAdapter(DocumentClient client, string databaseName, string collectionName)
        {
            this.client         = client ?? throw new ArgumentNullException(nameof(client));
            this.databaseName   = databaseName ?? throw new ArgumentNullException(nameof(databaseName));
            this.collectionName = collectionName ?? throw new ArgumentNullException(nameof(collectionName));

            this.monitor = new CosmosDbPerformanceMonitor();

            var collectionUri = UriFactory.CreateDocumentCollectionUri(this.databaseName, this.collectionName);
            var descriptor    = new CollectionDescriptor(this.monitor, client, collectionUri);

            this.Authors   = new AuthorEntityClient(descriptor);
            this.BlogPosts = new BlogPostEntityClient(descriptor);
        }
Beispiel #15
0
            public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
                var assetReference    = item as AssetReference;
                var attachedReference = AttachedReferenceManager.GetAttachedReference(item);

                // We cannot set links if we do not have indexer accessor
                if (!descriptor.HasIndexerAccessors)
                {
                    return;
                }

                if (assetReference != null)
                {
                    AddLink(assetReference, (guid, location) =>
                    {
                        var link = AssetReference.New(guid ?? assetReference.Id, location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (attachedReference != null)
                {
                    AddLink(attachedReference, (guid, location) =>
                    {
                        var link = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null;
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (item is UFile)
                {
                    AddLink(item, (guid, location) =>
                    {
                        var link = new UFile(location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (item is UDirectory)
                {
                    AddLink(item, (guid, location) =>
                    {
                        var link = new UDirectory(location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
            }
        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);
        }
Beispiel #17
0
        /// <summary>
        /// Database migration
        /// </summary>
        private void Migrate()
        {
            var properties = this._context.GetType().GetProperties();

            var collectionProperties = properties.Where(x => Attribute.IsDefined(x, typeof(CollectionDescriptor))).ToList();

            foreach (var collectionProperty in collectionProperties)
            {
                CollectionDescriptor descriptor = collectionProperty.GetCustomAttributes(typeof(CollectionDescriptor), false).FirstOrDefault() as CollectionDescriptor;

                Type entityType = Type.GetType(collectionProperty.PropertyType.GenericTypeArguments[0].FullName + "," + collectionProperty.Module.Assembly.FullName);

                this.MigrateCollection(collectionProperty.Name, entityType, descriptor);
            }

            this._context.CreateIndexes();
        }
Beispiel #18
0
        /// <inheritdoc/>
        public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
        {
            var containerNode = GetContextNode();

            var count         = descriptor.GetCollectionCount(collection);
            var referenceInfo = GetReferenceInfo(descriptor.Type, collection);

            if (referenceInfo != null && referenceInfo.EnumerableCount != count)
            {
                throw new QuantumConsistencyException("A node with an EnumerableReference containing [{0}] items", referenceInfo.EnumerableCount.ToStringSafe(), "A node with an EnumerableReference containing [{0}] items", count.ToStringSafe(), containerNode);
            }

            if (IsPrimitiveType(descriptor.ElementType, false) || IsEnumerable(descriptor.ElementType))
            {
                base.VisitCollection(collection, descriptor);
            }
        }
Beispiel #19
0
        /// <summary>
        /// Initialize the tests.
        /// </summary>
        public virtual void Initialize()
        {
            TypeFactory = new TypeDescriptorFactory();
            var myClassDesc  = TypeFactory.Find(typeof(MyClass));
            var myStructDesc = TypeFactory.Find(typeof(MyStruct));

            ListClassDesc = (CollectionDescriptor)TypeFactory.Find(typeof(List <MyClass>));
            MapClassDesc  = (DictionaryDescriptor)TypeFactory.Find(typeof(Dictionary <string, MyClass>));

            MemberValue  = (IMemberDescriptor)myClassDesc.Members.FirstOrDefault(member => member.Name == "Value");
            MemberSub    = (IMemberDescriptor)myClassDesc.Members.FirstOrDefault(member => member.Name == "Sub");
            MemberStruct = (IMemberDescriptor)myClassDesc.Members.FirstOrDefault(member => member.Name == "Struct");
            MemberSubs   = (IMemberDescriptor)myClassDesc.Members.FirstOrDefault(member => member.Name == "Subs");
            MemberMaps   = (IMemberDescriptor)myClassDesc.Members.FirstOrDefault(member => member.Name == "Maps");
            MemberX      = (IMemberDescriptor)myStructDesc.Members.FirstOrDefault(member => member.Name == "X");
            MemberClass  = (IMemberDescriptor)myStructDesc.Members.FirstOrDefault(member => member.Name == "Class");
        }
        protected async void DoPaste(INodePresenter nodePresenter, bool replace)
        {
            var text = SafeClipboard.GetText();

            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            var assetNodePresenter = (IAssetNodePresenter)nodePresenter;
            var asset            = assetNodePresenter.Asset;
            var copyPasteService = asset.ServiceProvider.Get <ICopyPasteService>();
            var result           = copyPasteService.DeserializeCopiedData(text, asset.Asset, (nodePresenter as ItemNodePresenter)?.OwnerCollection.Type ?? nodePresenter.Type);

            if (result.Items.Count == 0)
            {
                return;
            }

            var nodeAccessor = nodePresenter.GetNodeAccessor();
            var targetNode   = nodeAccessor.Node;

            // If the node presenter is a virtual node without node, we cannot paste.
            if (targetNode == null)
            {
                return;
            }

            var actionService = asset.UndoRedoService;

            using (var transaction = actionService.CreateTransaction())
            {
                // FIXME: for now we only handle one result item
                var item = result.Items[0];
                if (item.Data is ICollection && !CollectionDescriptor.IsCollection(targetNode.Type))
                {
                    return; // cannot paste a collection to a non-collection content
                }
                var propertyContainer = new PropertyContainer {
                    { AssetPropertyPasteProcessor.IsReplaceKey, replace }
                };
                await(item.Processor?.Paste(item, asset.PropertyGraph, ref nodeAccessor, ref propertyContainer) ?? Task.CompletedTask);
                actionService.SetName(transaction, replace ? "Replace property": "Paste property");
            }
        }
Beispiel #21
0
        private Diff3Node DiffNodeWithUniformType(DataVisitNode baseNode, DataVisitNode asset1Node, DataVisitNode asset2Node)
        {
            var baseNodeDesc   = GetNodeDescription(baseNode);
            var asset1NodeDesc = GetNodeDescription(asset1Node);
            var asset2NodeDesc = GetNodeDescription(asset2Node);

            var node = baseNode ?? asset1Node ?? asset2Node;
            var type = baseNodeDesc.Type ?? asset1NodeDesc.Type ?? asset2NodeDesc.Type;

            var diff3 = new Diff3Node(baseNode, asset1Node, asset2Node)
            {
                InstanceType = type
            };

            if (type == null)
            {
                // All nodes are null. This should only happen as part of a temporary diff in DiffNode()
                diff3.ChangeType = Diff3ChangeType.None;
            }
            else if (IsComparableType(node.HasMembers, type))
            {
                DiffValue(diff3, ref baseNodeDesc, ref asset1NodeDesc, ref asset2NodeDesc);
            }
            else
            {
                DiffMembers(diff3, baseNode, asset1Node, asset2Node);

                if (DictionaryDescriptor.IsDictionary(type))
                {
                    DiffDictionary(diff3, baseNode, asset1Node, asset2Node);
                }
                else if (CollectionDescriptor.IsCollection(type))
                {
                    DiffCollection(diff3, baseNode, asset1Node, asset2Node);
                }
                else if (type.IsArray)
                {
                    DiffArray(diff3, baseNode, asset1Node, asset2Node);
                }
            }

            return(diff3);
        }
Beispiel #22
0
        /// <summary>
        /// Migrate collection
        /// </summary>
        /// <param name="name"></param>
        /// <param name="collectionPropertyType"></param>
        /// <param name="descriptor"></param>
        private void MigrateCollection(string name, Type collectionPropertyType, CollectionDescriptor descriptor)
        {
            if (!this.CollectionExists(name))
            {
                this._database.CreateCollection(name, new CreateCollectionOptions
                {
                    MaxDocuments     = descriptor.MaxDocuments > 0 ? descriptor.MaxDocuments : (long?)null,
                    Capped           = descriptor.Capped,
                    MaxSize          = descriptor.MaxSize > 0 ? descriptor.MaxSize : (long?)null,
                    ValidationAction = descriptor.ValidationAction,
                    ValidationLevel  = descriptor.ValidationLevel
                });
            }

            var typedCollection = typeof(MongoDatabase)
                                  .GetMethod("GetCollectionByName", BindingFlags.NonPublic | BindingFlags.Instance)
                                  .MakeGenericMethod(new Type[] { collectionPropertyType })
                                  .Invoke(this, new object[] { name });

            this._context.GetType().GetProperty(name).SetValue(this._context, typedCollection);
        }
Beispiel #23
0
        private Diff3Node DiffNodeWithUniformType(DataVisitNode baseNode, DataVisitNode asset1Node, DataVisitNode asset2Node)
        {
            var baseNodeDesc   = GetNodeDescription(baseNode);
            var asset1NodeDesc = GetNodeDescription(asset1Node);
            var asset2NodeDesc = GetNodeDescription(asset2Node);

            var node = baseNode ?? asset1Node ?? asset2Node;
            var type = baseNodeDesc.Type ?? asset1NodeDesc.Type ?? asset2NodeDesc.Type;

            var diff3 = new Diff3Node(baseNode, asset1Node, asset2Node)
            {
                InstanceType = type
            };

            if (IsComparableType(node.HasMembers, type))
            {
                DiffValue(diff3, ref baseNodeDesc, ref asset1NodeDesc, ref asset2NodeDesc);
            }
            else
            {
                DiffMembers(diff3, baseNode, asset1Node, asset2Node);

                if (DictionaryDescriptor.IsDictionary(type))
                {
                    DiffDictionary(diff3, baseNode, asset1Node, asset2Node);
                }
                else if (CollectionDescriptor.IsCollection(type))
                {
                    DiffCollection(diff3, baseNode, asset1Node, asset2Node);
                }
                else if (type.IsArray)
                {
                    DiffArray(diff3, baseNode, asset1Node, asset2Node);
                }
            }

            return(diff3);
        }
Beispiel #24
0
        private static bool ConvertForCollection(CollectionDescriptor collectionDescriptor, [NotNull] ref object data)
        {
            if (CollectionDescriptor.IsCollection(data.GetType()))
            {
                if (!TryConvertCollectionData(data, collectionDescriptor, out data))
                {
                    return(false);
                }
            }
            else
            {
                object convertedData;
                if (!TypeConverterHelper.TryConvert(data, collectionDescriptor.ElementType, out convertedData))
                {
                    return(false);
                }

                var convertedCollection = Activator.CreateInstance(collectionDescriptor.Type, true);
                collectionDescriptor.Add(convertedCollection, convertedData);
                data = convertedCollection;
            }
            return(true);
        }
Beispiel #25
0
        /// <summary>
        /// Tries to convert the <paramref name="sourceCollection"/> to the type described by <paramref name="collectionDescriptor"/>.
        /// </summary>
        /// <param name="sourceCollection"></param>
        /// <param name="collectionDescriptor"></param>
        /// <param name="convertedCollection"></param>
        /// <returns><c>true</c> if the <paramref name="sourceCollection"/> could be converted to the type described by <paramref name="collectionDescriptor"/>; otherwise, <c>false</c>.</returns>
        private static bool TryConvertCollectionData([NotNull] object sourceCollection, [NotNull] CollectionDescriptor collectionDescriptor, out object convertedCollection)
        {
            try
            {
                var sourceCollectionType = sourceCollection.GetType();
                // Already same type
                if (collectionDescriptor.Type == sourceCollectionType)
                {
                    convertedCollection = sourceCollection;
                    return(true);
                }

                convertedCollection = Activator.CreateInstance(collectionDescriptor.Type, true);
                var sourceCollectionDescriptor = (CollectionDescriptor)TypeDescriptorFactory.Default.Find(sourceCollectionType);
                foreach (var item in EnumerateCollection(sourceCollection, sourceCollectionDescriptor))
                {
                    object obj;
                    if (!TypeConverterHelper.TryConvert(item, collectionDescriptor.ElementType, out obj))
                    {
                        // (optimistic) try to convert the remaining items
                        continue;
                    }
                    collectionDescriptor.Add(convertedCollection, obj);
                }
                return(collectionDescriptor.GetCollectionCount(convertedCollection) > 0);
            }
            catch (InvalidCastException) { }
            catch (InvalidOperationException) { }
            catch (FormatException) { }
            catch (NotSupportedException) { }
            catch (Exception ex) when(ex.InnerException is InvalidCastException)
            {
            }
            catch (Exception ex) when(ex.InnerException is InvalidOperationException)
            {
            }
            catch (Exception ex) when(ex.InnerException is FormatException)
            {
            }
            catch (Exception ex) when(ex.InnerException is NotSupportedException)
            {
            }

            // Incompatible type and no conversion available
            convertedCollection = null;
            return(false);
        }
Beispiel #26
0
 public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)
 {
     Fixup(collection);
     base.VisitCollection(collection, descriptor);
 }
Beispiel #27
0
 private static bool HasCollectionReference(Type type)
 {
     return type.IsArray || CollectionDescriptor.IsCollection(type) || DictionaryDescriptor.IsDictionary(type);
 }
        protected override void ReadAddCollectionItem(ref ObjectContext objectContext, Type elementType, CollectionDescriptor collectionDescriptor, object thisObject, int index)
        {
            var scriptCollection = (EntityComponentCollection)objectContext.Instance;

            EntityComponent value   = null;
            bool            needAdd = true; // If we could get existing value, no need add to collection

            if (index < scriptCollection.Count)
            {
                value   = scriptCollection[index];
                needAdd = false;
            }

            value = (EntityComponent)ReadCollectionItem(ref objectContext, value, elementType);
            if (needAdd)
            {
                scriptCollection.Add(value);
            }
        }
 /// <summary>
 ///		Initializes a new instance of the <see cref="ApplyMaxLengthAttribute" /> class.
 /// </summary>
 /// <param name="descriptor">Describe a collection should be mutated.</param>
 protected ApplyMaxLengthAttribute(CollectionDescriptor descriptor)
 {
     _descriptor = descriptor;
 }
Beispiel #30
0
        // TODO: replace targetNode & index arguments by a NodeAccessor
        private void Paste([NotNull] IPasteItem pasteResultItem, IGraphNode targetNode, NodeIndex index, bool replace)
        {
            if (pasteResultItem?.Data == null)
            {
                throw new ArgumentNullException(nameof(pasteResultItem));
            }
            if (targetNode == null)
            {
                throw new ArgumentNullException(nameof(targetNode));
            }

            var copiedData           = pasteResultItem.Data;
            var copiedDataType       = copiedData.GetType();
            var copiedDataDescriptor = TypeDescriptorFactory.Default.Find(copiedDataType);
            var memberNode           = targetNode as IMemberNode;

            // We're pasting in a node that is not a collection (nor a dictionary), let's just do a member update
            if (!CollectionDescriptor.IsCollection(targetNode.Type))
            {
                if (CanUpdateMember(memberNode, copiedData))
                {
                    UpdateMember(memberNode, copiedData);
                }
                return;
            }

            // Check if target collection/dictionary is null.
            if (memberNode != null && memberNode.Target == null)
            {
                // Check if the type has a public constructor with no arguments
                if (targetNode.Type.GetConstructor(Type.EmptyTypes) != null)
                {
                    // Instantiate a new collection (based on node type)
                    memberNode.Update(Activator.CreateInstance(targetNode.Type));
                }
            }

            var collectionNode = memberNode != null ? memberNode.Target : (IObjectNode)targetNode;

            // The collection/dictionary is null and we couldn't construct it, let's stop here
            if (collectionNode == null)
            {
                return;
            }

            // We're pasting in a dictionary. In this case the only accepted input is a (compatible) dictionary
            if (copiedDataDescriptor.Category == DescriptorCategory.Dictionary && DictionaryDescriptor.IsDictionary(targetNode.Type))
            {
                var copiedDataDictionaryDescriptor = (DictionaryDescriptor)copiedDataDescriptor;
                var existingKeys = collectionNode.Indices.ToList();
                if (replace)
                {
                    var keys = ((DictionaryDescriptor)collectionNode.Descriptor).GetKeys(collectionNode.Retrieve()).Cast <object>().ToList();
                    if (index.IsEmpty)
                    {
                        // If this operation is a replace of the whole dictionary, let's first clear it
                        foreach (var key in keys)
                        {
                            var itemIndex = new NodeIndex(key);
                            if (CanRemoveItem(collectionNode, itemIndex))
                            {
                                var itemToRemove = targetNode.Retrieve(itemIndex);
                                collectionNode.Remove(itemToRemove, itemIndex);
                            }
                        }
                    }
                    else
                    {
                        // Otherwise, just remove the corresponding item
                        if (CanRemoveItem(collectionNode, index))
                        {
                            var itemToRemove = targetNode.Retrieve(index);
                            collectionNode.Remove(itemToRemove, index);
                        }
                    }
                }
                foreach (var kv in copiedDataDictionaryDescriptor.GetEnumerator(copiedData))
                {
                    var itemIndex = new NodeIndex(kv.Key);
                    if (existingKeys.Contains(itemIndex))
                    {
                        // Replace if the key already exists
                        if (CanReplaceItem(collectionNode, itemIndex, kv.Value))
                        {
                            ReplaceItem(collectionNode, itemIndex, kv.Value);
                        }
                    }
                    else
                    {
                        // Add if the key does not exist
                        if (CanInsertItem(collectionNode, itemIndex, kv.Value))
                        {
                            InsertItem(collectionNode, itemIndex, kv.Value);
                        }
                    }
                }
            }
            else if (targetNode.Descriptor.Category == DescriptorCategory.Collection)
            {
                var targetCollectionDescriptor = (CollectionDescriptor)targetNode.Descriptor;
                if (replace)
                {
                    // No index, we're replacing the whole collection
                    if (index.IsEmpty)
                    {
                        // First clear the collection
                        var count = targetCollectionDescriptor.GetCollectionCount(targetNode.Retrieve());
                        for (var j = count - 1; j >= 0; j--)
                        {
                            var itemIndex = new NodeIndex(j);
                            if (CanRemoveItem(collectionNode, itemIndex))
                            {
                                var itemToRemove = targetNode.Retrieve(itemIndex);
                                collectionNode.Remove(itemToRemove, itemIndex);
                            }
                        }

                        // Then add the new items
                        var i = 0;
                        foreach (var item in EnumerateItems(copiedData, copiedDataDescriptor))
                        {
                            var itemIndex = new NodeIndex(i);
                            if (CanInsertItem(collectionNode, itemIndex, item))
                            {
                                InsertItem(collectionNode, itemIndex, item);
                                i++;
                            }
                        }
                    }
                    else
                    {
                        // We're replacing a single item with a given index...
                        var  startIndex        = index.Int;
                        var  i                 = 0;
                        bool firstItemReplaced = false;
                        foreach (var item in EnumerateItems(copiedData, copiedDataDescriptor))
                        {
                            var itemIndex = new NodeIndex(startIndex + i);
                            if (!firstItemReplaced)
                            {
                                // We replace the first item.
                                if (CanReplaceItem(collectionNode, itemIndex, item))
                                {
                                    ReplaceItem(collectionNode, itemIndex, item);
                                    firstItemReplaced = true;
                                    i++;
                                }
                            }
                            else if (CanInsertItem(collectionNode, itemIndex, item))
                            {
                                // We insert the following items that have no pre-existing counter-part.
                                InsertItem(collectionNode, itemIndex, item);
                                i++;
                            }
                        }
                    }
                }
                else
                {
                    // No index, we're replacing the whole collection
                    if (index.IsEmpty)
                    {
                        // Add the new items
                        var i = targetCollectionDescriptor.GetCollectionCount(targetNode.Retrieve());
                        foreach (var item in EnumerateItems(copiedData, copiedDataDescriptor))
                        {
                            var itemIndex = new NodeIndex(i);
                            if (CanInsertItem(collectionNode, itemIndex, item))
                            {
                                InsertItem(collectionNode, itemIndex, item);
                                i++;
                            }
                        }
                    }
                    else
                    {
                        // Handling non-replacing paste
                        var i = index.Int;
                        foreach (var item in EnumerateItems(copiedData, copiedDataDescriptor))
                        {
                            // We're pasting a collection into the collection, let's add all items at the given index if provided or at the end of the collection.
                            var itemIndex = new NodeIndex(i);
                            if (CanInsertItem(collectionNode, itemIndex, item))
                            {
                                InsertItem(collectionNode, itemIndex, item);
                                i++;
                            }
                        }
                    }
                }
            }
        }