示例#1
0
        public GraphNodePath Clone(IGraphNode newRoot)
        {
            var clone = new GraphNodePath(newRoot, Math.Max(path.Count, DefaultCapacity));

            clone.path.AddRange(path);
            return(clone);
        }
 /// <summary>
 /// Visits a hierarchy of node, starting by the given root node.
 /// </summary>
 /// <param name="node">The root node of the visit</param>
 /// <param name="memberNode">The member content containing the node to visit, if relevant. This is used to properly check if the root node should be visited.</param>
 /// <param name="initialPath">The initial path of the root node, if this visit occurs in the context of a sub-hierarchy. Can be null.</param>
 public virtual void Visit([NotNull] IGraphNode node, [CanBeNull] MemberNode memberNode = null, [CanBeNull] GraphNodePath initialPath = null)
 {
     if (node == null)
     {
         throw new ArgumentNullException(nameof(node));
     }
     CurrentPath = initialPath ?? new GraphNodePath(node);
     RootNode    = node;
     VisitNode(node);
     RootNode = null;
 }
示例#3
0
        public static GraphNodePath From(IGraphNode root, [NotNull] MemberPath memberPath, out NodeIndex index)
        {
            if (memberPath == null)
            {
                throw new ArgumentNullException(nameof(memberPath));
            }

            var result = new GraphNodePath(root);

            index = NodeIndex.Empty;
            var memberPathItems = memberPath.Decompose();

            for (int i = 0; i < memberPathItems.Count; i++)
            {
                var  memberPathItem = memberPathItems[i];
                bool lastItem       = i == memberPathItems.Count - 1;
                if (memberPathItem.MemberDescriptor != null)
                {
                    result.PushMember(memberPathItem.MemberDescriptor.Name);
                }
                else if (memberPathItem.GetIndex() != null)
                {
                    var localIndex = new NodeIndex(memberPathItem.GetIndex());

                    if (lastItem)
                    {
                        // If last item, we directly return the index rather than add it to the path
                        index = localIndex;
                    }
                    else
                    {
                        result.PushIndex(localIndex);
                    }
                }

                // Don't apply Target on last item
                if (!lastItem)
                {
                    // If this is a reference, add a target element to the path
                    var node            = result.GetNode();
                    var objectReference = (node as IMemberNode)?.TargetReference;
                    if (objectReference?.TargetNode != null)
                    {
                        result.PushTarget();
                    }
                }
            }

            return(result);
        }
示例#4
0
        public GraphNodePath GetParent()
        {
            if (IsEmpty)
            {
                return(null);
            }

            var result = new GraphNodePath(RootNode, path.Count - 1);

            for (var i = 0; i < path.Count - 1; ++i)
            {
                result.path.Add(path[i]);
            }
            return(result);
        }
示例#5
0
        private void ContentFinalizeChange(object sender, [NotNull] INodeChangeEventArgs e)
        {
            var visitor = CreateVisitor();

            visitor.Visiting += (node, path) => RegisterNode(node);
            switch (e.ChangeType)
            {
            case ContentChangeType.ValueChange:
            case ContentChangeType.CollectionUpdate:
                // The changed node itself is still valid, we don't want to re-register it
                visitor.SkipRootNode = true;
                visitor.Visit(e.Node);
                // TODO: In case of CollectionUpdate we could probably visit only the target node of the corresponding index
                break;

            case ContentChangeType.CollectionAdd:
                if (e.Node.IsReference && e.NewValue != null)
                {
                    var        objectNode = (IObjectNode)e.Node;
                    IGraphNode addedNode;
                    NodeIndex  index;
                    var        arg = (ItemChangeEventArgs)e;
                    if (!arg.Index.IsEmpty)
                    {
                        index     = arg.Index;
                        addedNode = objectNode.ItemReferences[arg.Index].TargetNode;
                    }
                    else
                    {
                        // TODO: review this
                        var reference = objectNode.ItemReferences.First(x => x.TargetNode.Retrieve() == e.NewValue);
                        index     = reference.Index;
                        addedNode = reference.TargetNode;
                    }

                    if (addedNode != null && visitor.ShouldVisitTargetItem(objectNode, index))
                    {
                        var path = new GraphNodePath(e.Node);
                        path.PushIndex(index);
                        visitor.Visit(addedNode, e.Node as MemberNode, path);
                    }
                }
                break;
            }
        }
示例#6
0
        /// <inheritdoc/>
        public bool Equals(GraphNodePath other)
        {
            if (ReferenceEquals(null, other))
            {
                return(false);
            }
            if (ReferenceEquals(this, other))
            {
                return(true);
            }
            if (!Equals(RootNode, other.RootNode) || path.Count != other.path.Count)
            {
                return(false);
            }

            for (var i = 0; i < path.Count; ++i)
            {
                if (!path[i].EqualsInPath(other.path[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
示例#7
0
 public GraphNodePathEnumerator(GraphNodePath path)
 {
     this.path = path;
 }