/// <summary>
        /// Returns a clone of the node of this state.
        /// </summary>
        /// <returns>The cloned node.</returns>
        public override INode CloneNode()
        {
            INode NewNode = null;

            NodeTreeHelperOptional.GetChildNode(Optional, out bool IsAssigned, out INode ChildNode);
            if (ChildNode != null)
            {
                // Create a clone, initially empty and full of null references.
                NewNode = NodeHelper.CreateEmptyNode(ChildNode.GetType());

                // Clone and assign reference to all nodes, optional or not, list and block lists.
                foreach (KeyValuePair <string, IReadOnlyInner> Entry in InnerTable)
                {
                    string         PropertyName = Entry.Key;
                    IReadOnlyInner Inner        = Entry.Value;
                    ((IReadOnlyInner <IReadOnlyBrowsingChildIndex>)Inner).CloneChildren(NewNode);
                }

                // Copy other properties.
                foreach (KeyValuePair <string, ValuePropertyType> Entry in ValuePropertyTypeTable)
                {
                    string            PropertyName = Entry.Key;
                    ValuePropertyType Type         = Entry.Value;
                    bool IsHandled = false;

                    switch (Type)
                    {
                    case ValuePropertyType.Boolean:
                        NodeTreeHelper.CopyBooleanProperty(Node, NewNode, Entry.Key);
                        IsHandled = true;
                        break;

                    case ValuePropertyType.Enum:
                        NodeTreeHelper.CopyEnumProperty(Node, NewNode, Entry.Key);
                        IsHandled = true;
                        break;

                    case ValuePropertyType.String:
                        NodeTreeHelper.CopyStringProperty(Node, NewNode, Entry.Key);
                        IsHandled = true;
                        break;

                    case ValuePropertyType.Guid:
                        NodeTreeHelper.CopyGuidProperty(Node, NewNode, Entry.Key);
                        IsHandled = true;
                        break;
                    }

                    Debug.Assert(IsHandled);
                }

                // Also copy comments.
                NodeTreeHelper.CopyDocumentation(Node, NewNode, cloneCommentGuid: true);
            }

            return(NewNode);
        }
        /// <inheritdoc/>
        public override void CloneChildren(Node parentNode)
        {
            NodeTreeHelperBlockList.ClearChildBlockList(parentNode, PropertyName);

            // Clone and insert all blocks. This will clone all children recursively.
            for (int BlockIndex = 0; BlockIndex < BlockStateList.Count; BlockIndex++)
            {
                IReadOnlyBlockState BlockState = BlockStateList[BlockIndex];
                ((IReadOnlyBlockState <IReadOnlyInner <IReadOnlyBrowsingChildIndex> >)BlockState).CloneBlock(parentNode, BlockIndex);
            }

            // Copy comments.
            IBlockList BlockList    = NodeTreeHelperBlockList.GetBlockList(Owner.Node, PropertyName);
            IBlockList NewBlockList = NodeTreeHelperBlockList.GetBlockList(parentNode, PropertyName);

            NodeTreeHelper.CopyDocumentation(BlockList, NewBlockList, cloneCommentGuid: true);
        }
        /// <summary>
        /// Creates a clone of the block and assigns it in the provided parent.
        /// </summary>
        /// <param name="parentNode">The node that will contains a reference to the cloned block upon return.</param>
        /// <param name="blockIndex">Position where to insert the block in <paramref name="parentNode"/>.</param>
        public virtual void CloneBlock(Node parentNode, int blockIndex)
        {
            Pattern PatternClone = ClonePattern();

            Debug.Assert(PatternClone != null);

            Identifier SourceClone = CloneSource();

            Debug.Assert(SourceClone != null);

            IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(parentNode, ParentInner.PropertyName, ChildBlock.Replication, PatternClone, SourceClone);

            NodeTreeHelperBlockList.InsertIntoBlockList(parentNode, ParentInner.PropertyName, blockIndex, NewBlock);
            NodeTreeHelper.CopyDocumentation(ChildBlock, NewBlock, cloneCommentGuid: true);

            // Clone children recursively.
            CloneChildren(parentNode, NewBlock);
        }