コード例 #1
0
 protected virtual void OnMerge(MergeableNode <T> existingNode, MergeableNode <T> node)
 {
     // Process children.
     if (node.Children != null && node.Children.Count > 0)
     {
         EnsureChildren(existingNode);
         Merge(existingNode.Children, node.Children);
     }
 }
コード例 #2
0
        private static void EnsureChildren(MergeableNode <T> node)
        {
            Debug.Assert(node != null);

            if (node.Children == null)
            {
                node.Children = new MergeableNodeCollection <T>();
            }
        }
コード例 #3
0
        public MergeableNode <T> GetRoot()
        {
            MergeableNode <T> node = this;

            while (node.Parent != null)
            {
                node = node.Parent;
            }

            return(node);
        }
コード例 #4
0
        protected virtual void OnInsert(MergeableNodeCollection <T> existingNodes, MergeableNode <T> node, int index)
        {
            if (!CloneNodesOnMerge)
            {
                // Moving nodes - destroying the input collection:
                node.Parent?.Children?.Remove(node);   // First detach node from parent.
                existingNodes.Insert(index, node);
            }
            else
            {
                // Copying nodes - leaving the input collection intact.
                var copy = new MergeableNode <T>(node.Content);

                existingNodes.Insert(index, copy);

                // Process children
                if (node.Children != null && node.Children.Count > 0)
                {
                    EnsureChildren(copy);
                    Merge(copy.Children, node.Children);
                }
            }
        }
コード例 #5
0
        //--------------------------------------------------------------
        #region Traversal Methods
        //--------------------------------------------------------------

        /// <summary>
        /// Gets the children of the specified node.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns>The children of <paramref name="node"/>.</returns>
        private static IEnumerable <MergeableNode <T> > GetChildren(MergeableNode <T> node)
        {
            return(node.Children ?? Enumerable.Empty <MergeableNode <T> >());
        }
コード例 #6
0
 protected override void SetParent(MergeableNode <T> child, MergeableNode <T> parent)
 {
     child.Parent = parent;
 }
コード例 #7
0
 protected override MergeableNode <T> GetParent(MergeableNode <T> child)
 {
     return(child.Parent);
 }
コード例 #8
0
        private void Merge(MergeableNodeCollection <T> targetNodes, MergeableNode <T> node)
        {
            if (node == null)
            {
                return;
            }

            if (node.Content == null)
            {
                throw new NotSupportedException("Cannot merge nodes. MergeableNode must not be empty (Content != null).");
            }

            if (node.MergePoints == null)
            {
                return;
            }

            foreach (var mergePoint in node.MergePoints)
            {
                string targetName     = mergePoint.Target;
                var    mergeOperation = mergePoint.Operation;

                if (mergeOperation == MergeOperation.Ignore)
                {
                    return;   // Ignore this node.
                }
                // Check whether node with the same action name already exists.
                int  indexOfExistingNode = FindTargetNode(targetNodes, node.Content.Name);
                bool nodeExists          = (indexOfExistingNode >= 0);

                int  indexOfTarget = -1;
                bool targetFound   = false;

                // Find target node.
                // (MergeOperation.Append and MergeOperation.Prepend do not need a target node.)
                if (!nodeExists && mergeOperation != MergeOperation.Append && mergeOperation != MergeOperation.Prepend)
                {
                    indexOfTarget = FindTargetNode(targetNodes, targetName);
                    targetFound   = (indexOfTarget >= 0);

                    if (!targetFound)
                    {
                        continue;       // Target not found. Try next merge point.
                    }
                }

                switch (mergeOperation)
                {
                case MergeOperation.Ignore:
                    // Do nothing.
                    Debug.Fail("We should never get here, cause all MergeOperation.Ignore are handled above.");
                    break;

                case MergeOperation.Match:
                    // Do not add this node, but merge children
                    Debug.Assert(nodeExists || targetFound, "Sanity check.");

                    if (nodeExists)
                    {
                        if (node.Children != null && node.Children.Count > 0)
                        {
                            var targetNode = targetNodes[indexOfExistingNode];
                            EnsureChildren(targetNode);
                            Merge(targetNode.Children, node.Children);
                        }
                    }
                    else
                    {
                        if (node.Children != null && node.Children.Count > 0)
                        {
                            var targetNode = targetNodes[indexOfTarget];
                            EnsureChildren(targetNode);
                            Merge(targetNode.Children, node.Children);
                        }
                    }
                    break;

                case MergeOperation.Prepend:
                    // Merge node with existing node, or prepend at the beginning.
                    if (nodeExists)
                    {
                        OnMerge(targetNodes[indexOfExistingNode], node);
                    }
                    else
                    {
                        OnInsert(targetNodes, node, 0);
                    }
                    break;

                case MergeOperation.Append:
                    // Merge node with existing node, or append at the end.
                    if (nodeExists)
                    {
                        OnMerge(targetNodes[indexOfExistingNode], node);
                    }
                    else
                    {
                        OnInsert(targetNodes, node, targetNodes.Count);
                    }
                    break;

                case MergeOperation.InsertBefore:
                    // Merge node with existing, or insert before merge point.
                    Debug.Assert(nodeExists || targetFound, "Sanity check.");
                    if (nodeExists)
                    {
                        OnMerge(targetNodes[indexOfExistingNode], node);
                    }
                    else
                    {
                        OnInsert(targetNodes, node, indexOfTarget);
                    }
                    break;

                case MergeOperation.InsertAfter:
                    // Merge node with existing or insert after merge point.
                    Debug.Assert(nodeExists || targetFound, "Sanity check.");
                    if (nodeExists)
                    {
                        OnMerge(targetNodes[indexOfExistingNode], node);
                    }
                    else
                    {
                        OnInsert(targetNodes, node, indexOfTarget + 1);
                    }
                    break;

                case MergeOperation.Replace:
                    // Replace existing node (or node at merge point).
                    Debug.Assert(nodeExists || targetFound, "Sanity check.");
                    if (nodeExists)
                    {
                        targetNodes.RemoveAt(indexOfExistingNode);
                        OnInsert(targetNodes, node, indexOfExistingNode);
                    }
                    else
                    {
                        targetNodes.RemoveAt(indexOfTarget);
                        OnInsert(targetNodes, node, indexOfTarget);
                    }
                    break;

                case MergeOperation.Remove:
                    // Remove existing node (or node at merge point)
                    Debug.Assert(nodeExists || targetFound, "Sanity check.");
                    if (nodeExists)
                    {
                        targetNodes.RemoveAt(indexOfExistingNode);
                    }
                    else
                    {
                        targetNodes.RemoveAt(indexOfTarget);
                    }
                    break;
                }
            }
        }