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)); } } }
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); }
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)); } }
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); }
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); } }
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); } }
/// <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); } }
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 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); }
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); }
/// <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(); }
/// <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); } }
/// <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"); } }
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); }
/// <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); }
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); }
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); }
/// <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); }
public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor) { Fixup(collection); base.VisitCollection(collection, descriptor); }
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; }
// 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++; } } } } } }