Exemple #1
0
        public override void UpdateNode(INodePresenter node)
        {
            if (DictionaryDescriptor.IsDictionary(node.Type))
            {
                if (node.Type.IsGenericType)
                {
                    var genericArguments = node.Type.GetGenericArguments();
                    node.AttachedProperties.Add(DictionaryNodeKeyType, genericArguments[0]);
                }
                else
                {
                    foreach (var typeInterface in node.Type.GetInterfaces())
                    {
                        if (!typeInterface.IsGenericType || typeInterface.GetGenericTypeDefinition() != typeof(IDictionary <,>))
                        {
                            continue;
                        }

                        var genericArguments = typeInterface.GetGenericArguments();
                        node.AttachedProperties.Add(DictionaryNodeKeyType, genericArguments[0]);
                        break;
                    }
                }
            }
        }
Exemple #2
0
        private static bool ConvertForDictionary(DictionaryDescriptor dictionaryDescriptor, ref object data)
        {
            object convertedDictionary;

            if (DictionaryDescriptor.IsDictionary(data.GetType()))
            {
                if (!TryConvertDictionaryData(data, dictionaryDescriptor, out convertedDictionary))
                {
                    return(false);
                }
            }
            else
            {
                var dataType = data.GetType();
                var key      = dataType.GetMember("Key").OfType <PropertyInfo>().FirstOrDefault()?.GetValue(data);
                if (key == null || !TypeConverterHelper.TryConvert(key, dictionaryDescriptor.KeyType, out key))
                {
                    return(false);
                }

                var value = dataType.GetMember("Value").OfType <PropertyInfo>().FirstOrDefault()?.GetValue(data);
                if (value == null || !TypeConverterHelper.TryConvert(value, dictionaryDescriptor.ValueType, out value))
                {
                    return(false);
                }

                convertedDictionary = Activator.CreateInstance(dictionaryDescriptor.Type, true);
                dictionaryDescriptor.SetValue(convertedDictionary, key, value);
            }
            data = convertedDictionary;
            return(true);
        }
Exemple #3
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);
        }
Exemple #4
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);
        }
Exemple #5
0
 private static bool HasCollectionReference(Type type)
 {
     return type.IsArray || CollectionDescriptor.IsCollection(type) || DictionaryDescriptor.IsDictionary(type);
 }
Exemple #6
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);
        }
Exemple #7
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++;
                            }
                        }
                    }
                }
            }
        }
Exemple #8
0
        private bool IsComparableType(bool hasMembers, Type type)
        {
            // A comparable type doesn't have any members, is not a collection or dictionary or array.
            bool isComparableType = ((UseOverrideMode && type.IsValueType) || !hasMembers) && !CollectionDescriptor.IsCollection(type) && !DictionaryDescriptor.IsDictionary(type) && !type.IsArray;

            return(isComparableType);
        }
Exemple #9
0
        private Diff3Node DiffNode(DataVisitNode baseNode, DataVisitNode asset1Node, DataVisitNode asset2Node)
        {
            var diff3 = new Diff3Node(baseNode, asset1Node, asset2Node);

            var baseNodeDesc   = GetNodeDescription(baseNode);
            var asset1NodeDesc = GetNodeDescription(asset1Node);
            var asset2NodeDesc = GetNodeDescription(asset2Node);

            bool hasMembers = false;

            Type type     = null;
            Type nodeType = null;

            if (baseNodeDesc.Type != null)
            {
                type       = baseNodeDesc.Type;
                hasMembers = baseNode.HasMembers;
                nodeType   = baseNode.GetType();
            }

            if (asset1NodeDesc.Type != null)
            {
                if (type == null)
                {
                    type       = asset1NodeDesc.Type;
                    hasMembers = asset1Node.HasMembers;
                    nodeType   = asset1Node.GetType();
                }
                else
                {
                    if (nodeType != asset1Node.GetType())
                    {
                        diff3.ChangeType = Diff3ChangeType.InvalidNodeType;
                        return(diff3);
                    }

                    if (type != asset1NodeDesc.Type)
                    {
                        diff3.ChangeType = Diff3ChangeType.ConflictType;
                        return(diff3);
                    }
                }
            }

            if (asset2NodeDesc.Type != null)
            {
                if (type == null)
                {
                    type       = asset2NodeDesc.Type;
                    hasMembers = asset2Node.HasMembers;
                }
                else
                {
                    if (nodeType != asset2Node.GetType())
                    {
                        diff3.ChangeType = Diff3ChangeType.InvalidNodeType;
                        return(diff3);
                    }

                    if (type != asset2NodeDesc.Type)
                    {
                        diff3.ChangeType = Diff3ChangeType.ConflictType;
                        return(diff3);
                    }
                }
            }

            if (type == null)
            {
                return(diff3);
            }

            diff3.InstanceType = 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;

            if (isComparableType)
            {
                DiffValue(diff3, ref baseNodeDesc, ref asset1NodeDesc, ref asset2NodeDesc);
                return(diff3);
            }

            // Diff members
            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);
        }
Exemple #10
0
 private static bool HasCollectionReference(Type type)
 {
     return(type.IsArray || ListDescriptor.IsList(type) || DictionaryDescriptor.IsDictionary(type) || SetDescriptor.IsSet(type) || OldCollectionDescriptor.IsCollection(type));
 }