Beispiel #1
0
        /// <summary>
        /// Visits the <see cref="ReferenceEnumerable"/> contained in the given node, if any.
        /// </summary>
        /// <param name="node">The node being visited.</param>
        protected virtual void VisitItemTargets([NotNull] IObjectNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            var enumerableReference = node.ItemReferences;

            if (enumerableReference != null)
            {
                foreach (var reference in enumerableReference)
                {
                    if (reference.TargetNode == null)
                    {
                        continue;
                    }

                    if (ShouldVisitTargetItem(node, reference.Index))
                    {
                        CurrentPath.PushIndex(reference.Index);
                        VisitReference(node, reference);
                        CurrentPath.Pop();
                    }
                }
            }
        }
Beispiel #2
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);
        }
Beispiel #3
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;
                    Index      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;
            }
        }