private protected virtual ReadOnlyNodeStateDictionary BuildChildrenStateTable(ReadOnlyBrowseContext browseContext)
        {
            IReadOnlyNodeState State = browseContext.State;
            ReadOnlyInnerReadOnlyDictionary <string> InnerTable          = State.InnerTable;
            ReadOnlyIndexCollectionReadOnlyList      IndexCollectionList = browseContext.IndexCollectionList;

            ReadOnlyNodeStateDictionary ChildStateTable = CreateChildStateTable();

            foreach (IReadOnlyIndexCollection <IReadOnlyBrowsingChildIndex> NodeIndexCollection in IndexCollectionList)
            {
                // List of indexes for this property (one for placeholder and optional node, several for lists and block lists)
                IReadOnlyList <IReadOnlyBrowsingChildIndex> NodeIndexList = NodeIndexCollection.NodeIndexList;
                string PropertyName = NodeIndexCollection.PropertyName;

                Debug.Assert(InnerTable.ContainsKey(PropertyName));
                IReadOnlyInner <IReadOnlyBrowsingChildIndex> Inner = (IReadOnlyInner <IReadOnlyBrowsingChildIndex>)InnerTable[PropertyName];

                for (int i = 0; i < NodeIndexList.Count; i++)
                {
                    IReadOnlyBrowsingChildIndex ChildIndex = NodeIndexList[i];

                    // If the inner is that of a block list, and the index is for the first node in the block, add block-specific states
                    if (Inner is IReadOnlyBlockListInner <IReadOnlyBrowsingBlockNodeIndex> AsBlockListInner && ChildIndex is IReadOnlyBrowsingNewBlockNodeIndex AsNewBlockIndex)
                    {
                        IReadOnlyBlockState BlockState = AsBlockListInner.InitNewBlock(AsNewBlockIndex);
                        ((IReadOnlyBlockState <IReadOnlyInner <IReadOnlyBrowsingChildIndex> >)BlockState).InitBlockState();
                        Stats.BlockCount++;

                        IReadOnlyBrowsingPatternIndex PatternIndex = BlockState.PatternIndex;
                        IReadOnlyPatternState         PatternState = BlockState.PatternState;
                        AddState(PatternIndex, PatternState);
                        Stats.PlaceholderNodeCount++;

                        IReadOnlyBrowsingSourceIndex SourceIndex = BlockState.SourceIndex;
                        IReadOnlySourceState         SourceState = BlockState.SourceState;
                        AddState(SourceIndex, SourceState);
                        Stats.PlaceholderNodeCount++;

                        ChildIndex = AsNewBlockIndex.ToExistingBlockIndex();
                    }

                    IReadOnlyNodeState ChildState = BuildChildState(Inner, ChildIndex);
                    ChildStateTable.Add(NodeIndexList[i], ChildState);
                }
            }

            return(ChildStateTable);
        }
        /// <summary>
        /// Initializes the block state.
        /// </summary>
        public virtual void InitBlockState()
        {
            PatternIndex = CreateExistingPatternIndex();
            PatternState = CreatePatternState(PatternIndex);
            ReadOnlyInnerReadOnlyDictionary <string> PatternEmptyInnerTable        = CreateInnerTable().ToReadOnly();
            Dictionary <string, ValuePropertyType>   PatternValuePropertyTypeTable = new Dictionary <string, ValuePropertyType>();

            PatternValuePropertyTypeTable.Add(nameof(Pattern.Text), ValuePropertyType.String);
            ((IReadOnlyPatternState <IInner>)PatternState).Init(PatternInner, PatternEmptyInnerTable, PatternValuePropertyTypeTable);

            SourceIndex = CreateExistingSourceIndex();
            SourceState = CreateSourceState(SourceIndex);
            ReadOnlyInnerReadOnlyDictionary <string> SourceEmptyInnerTable        = CreateInnerTable().ToReadOnly();
            Dictionary <string, ValuePropertyType>   SourceValuePropertyTypeTable = new Dictionary <string, ValuePropertyType>();

            SourceValuePropertyTypeTable.Add(nameof(Identifier.Text), ValuePropertyType.String);
            ((IReadOnlySourceState <IInner>)SourceState).Init(SourceInner, SourceEmptyInnerTable, SourceValuePropertyTypeTable);
        }
        private protected virtual void BuildChildrenStates(ReadOnlyBrowseContext browseContext, ReadOnlyNodeStateDictionary childrenStateTable)
        {
            IReadOnlyNodeState State = browseContext.State;
            ReadOnlyInnerReadOnlyDictionary <string> InnerTable          = State.InnerTable;
            ReadOnlyIndexCollectionReadOnlyList      IndexCollectionList = browseContext.IndexCollectionList;

            // Build states for children in the order they have been reported when browsing the parent state
            foreach (IReadOnlyIndexCollection <IReadOnlyBrowsingChildIndex> NodeIndexCollection in IndexCollectionList)
            {
                IReadOnlyList <IReadOnlyBrowsingChildIndex> NodeIndexList = NodeIndexCollection.NodeIndexList;
                string PropertyName = NodeIndexCollection.PropertyName;
                IReadOnlyInner <IReadOnlyBrowsingChildIndex> Inner = (IReadOnlyInner <IReadOnlyBrowsingChildIndex>)InnerTable[PropertyName];

                for (int i = 0; i < NodeIndexList.Count; i++)
                {
                    IReadOnlyBrowsingChildIndex ChildNodeIndex = NodeIndexList[i];
                    IReadOnlyNodeState          ChildState     = childrenStateTable[ChildNodeIndex];

                    BuildStateTable(Inner, browseContext, ChildState.ParentIndex, ChildState);
                }
            }
        }
        private protected virtual void BuildStateTable(IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner, ReadOnlyBrowseContext parentBrowseContext, IReadOnlyIndex nodeIndex, IReadOnlyNodeState state)
        {
            Debug.Assert((parentBrowseContext == null) || (parentBrowseContext != null && parentInner != null));
            Debug.Assert(Contains(nodeIndex));
            Debug.Assert(IndexToState(nodeIndex) == state);

            // Browse the uninitialized state for children
            ReadOnlyBrowseContext BrowseContext = CreateBrowseContext(parentBrowseContext, state);

            BrowseStateChildren(BrowseContext, parentInner);

            // Build inners for each child
            ReadOnlyInnerReadOnlyDictionary <string> InnerTable = BuildInnerTable(BrowseContext);

            // Initialize the state
            InitState(BrowseContext, parentInner, nodeIndex, InnerTable);

            // Build uninitialized states for each child
            ReadOnlyNodeStateDictionary ChildrenStateTable = BuildChildrenStateTable(BrowseContext);

            // Continue to build the table for each of them
            BuildChildrenStates(BrowseContext, ChildrenStateTable);
        }
        private protected virtual void InitState(ReadOnlyBrowseContext browseContext, IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner, IReadOnlyIndex nodeIndex, ReadOnlyInnerReadOnlyDictionary <string> innerTable)
        {
            Debug.Assert(Contains(nodeIndex));
            Debug.Assert(parentInner != null || nodeIndex == RootIndex);

            IReadOnlyNodeState State = browseContext.State;

            Debug.Assert(IndexToState(nodeIndex) == State);
            Debug.Assert(State.ParentInner == null);
            Debug.Assert(State.ParentIndex == nodeIndex);
            Debug.Assert(State.ParentState == null);
            Debug.Assert(State.InnerTable == null);
            Debug.Assert(State.IsEmptyValuePropertyTypeTable || State.ValuePropertyTypeTable.Count == 0);

            ((IReadOnlyNodeState <IReadOnlyInner <IReadOnlyBrowsingChildIndex> >)State).Init(parentInner, innerTable, browseContext.ValuePropertyTypeTable);

            NotifyNodeStateInitialized(State);
        }