private protected virtual IReadOnlyInner BuildInner(IReadOnlyNodeState parentState, IReadOnlyIndexCollection nodeIndexCollection) { IReadOnlyInner Result = null; switch (nodeIndexCollection) { case IReadOnlyIndexCollection <IReadOnlyBrowsingPlaceholderNodeIndex> AsPlaceholderNodeIndexCollection: Result = (IReadOnlyPlaceholderInner)CreatePlaceholderInner(parentState, AsPlaceholderNodeIndexCollection); break; case IReadOnlyIndexCollection <IReadOnlyBrowsingOptionalNodeIndex> AsOptionalNodeIndexCollection: Result = (IReadOnlyOptionalInner)CreateOptionalInner(parentState, AsOptionalNodeIndexCollection); break; case IReadOnlyIndexCollection <IReadOnlyBrowsingListNodeIndex> AsListNodeIndexCollection: Stats.ListCount++; Result = (IReadOnlyListInner)CreateListInner(parentState, AsListNodeIndexCollection); break; case IReadOnlyIndexCollection <IReadOnlyBrowsingBlockNodeIndex> AsBlockNodeIndexCollection: Stats.BlockListCount++; IReadOnlyBlockListInner Inner = (IReadOnlyBlockListInner)CreateBlockListInner(parentState, AsBlockNodeIndexCollection); NotifyBlockListInnerCreated(Inner as IReadOnlyBlockListInner); Result = Inner; break; } Debug.Assert(Result != null); return(Result); }
private protected virtual ReadOnlyInnerReadOnlyDictionary <string> BuildInnerTable(ReadOnlyBrowseContext browseContext) { IReadOnlyNodeState State = browseContext.State; Debug.Assert(State.InnerTable == null); ReadOnlyIndexCollectionReadOnlyList IndexCollectionList = browseContext.IndexCollectionList; ReadOnlyInnerDictionary <string> InnerTable = CreateInnerTable(); foreach (IReadOnlyIndexCollection NodeIndexCollection in IndexCollectionList) { string PropertyName = NodeIndexCollection.PropertyName; Debug.Assert(!InnerTable.ContainsKey(PropertyName)); IReadOnlyInner Inner = BuildInner(State, NodeIndexCollection); InnerTable.Add(PropertyName, Inner); } if (InnerTable.Count > 0) { DebugObjects.AddReference(InnerTable); } return(InnerTable.ToReadOnly()); }
/// <summary> /// Initializes a newly created state. /// </summary> /// <param name="parentInner">Inner containing this state.</param> /// <param name="innerTable">Table for all inners in this state.</param> /// <param name="valuePropertyTable">Table of children that are not nodes.</param> public virtual void Init(IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner, IReadOnlyInnerReadOnlyDictionary <string> innerTable, IReadOnlyDictionary <string, ValuePropertyType> valuePropertyTable) { Debug.Assert(innerTable != null); Debug.Assert(valuePropertyTable != null); Debug.Assert(!IsInitialized); Debug.Assert(ParentInner == null); Debug.Assert(InnerTable == null); Debug.Assert(ValuePropertyTypeTable == null); InitParentInner(parentInner); if (parentInner != null) // The root node doesn't have a parent inner. { InitParentState(ParentInner.Owner); } InitInnerTable(innerTable); Dictionary <string, ValuePropertyType> Table = new Dictionary <string, ValuePropertyType>(); foreach (KeyValuePair <string, ValuePropertyType> Entry in valuePropertyTable) { Table.Add(Entry.Key, Entry.Value); } ValuePropertyTypeTable = Table; IsInitialized = true; CheckInvariant(); }
bool IDictionary <TKey, IReadOnlyInner> .TryGetValue(TKey key, out IReadOnlyInner value) { bool Result = TryGetValue(key, out IFrameInner Value); value = Value; return(Result); }
/// <summary> /// Browse the optional node in the node tree. /// </summary> /// <param name="browseContext">The context used to browse the node tree.</param> /// <param name="parentInner">The inner containing this state as a child.</param> public override void BrowseChildren(ReadOnlyBrowseContext browseContext, IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner) { NodeTreeHelperOptional.GetChildNode(Optional, out bool IsAssigned, out Node ChildNode); if (ChildNode != null) { BrowseChildrenOfNode(browseContext, ChildNode); } }
/// <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); }
/// <summary> /// Detach a view to the state. /// </summary> /// <param name="view">The attaching view.</param> /// <param name="callbackSet">The set of callbacks to no longer call when enumerating existing states.</param> public virtual void Detach(IReadOnlyControllerView view, IReadOnlyAttachCallbackSet callbackSet) { foreach (KeyValuePair <string, IReadOnlyInner> Entry in InnerTable) { IReadOnlyInner Inner = Entry.Value; ((IReadOnlyInner <IReadOnlyBrowsingChildIndex>)Inner).Detach(view, callbackSet); } callbackSet.OnNodeStateDetached(this); }
private protected override void CheckInvariant() { InvariantAssert(IsInitialized); foreach (KeyValuePair <string, IReadOnlyInner> Entry in InnerTable) { IReadOnlyInner Inner = Entry.Value; InvariantAssert((Inner is IReadOnlyBlockListInner) || (Inner is IReadOnlyListInner) || (Inner is IReadOnlyOptionalInner) || (Inner is IReadOnlyPlaceholderInner)); InvariantAssert(Inner.Owner == this); } }
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); }
private protected virtual IReadOnlyInner <IReadOnlyBrowsingChildIndex> GetInner(Node parentNode, string propertyName) { IReadOnlyInner <IReadOnlyBrowsingChildIndex> Result = null; foreach (KeyValuePair <IReadOnlyIndex, IReadOnlyNodeState> Entry in StateTable) { IReadOnlyNodeState State = Entry.Value; if (State.Node == parentNode) { Result = State.PropertyToInner(propertyName) as IReadOnlyInner <IReadOnlyBrowsingChildIndex>; break; } } Debug.Assert(Result != null); return(Result); }
private void AddChildInner(IReadOnlyNodeStateList stateList, IReadOnlyInner inner) { bool IsHandled = false; switch (inner) { case IReadOnlyPlaceholderInner AsPlaceholderInner: AddChildStates(stateList, AsPlaceholderInner.ChildState); IsHandled = true; break; case IReadOnlyOptionalInner AsOptionalInner: if (AsOptionalInner.IsAssigned) { AddChildStates(stateList, AsOptionalInner.ChildState); } IsHandled = true; break; case IReadOnlyListInner AsListInner: foreach (IReadOnlyNodeState ChildState in AsListInner.StateList) { AddChildStates(stateList, ChildState); } IsHandled = true; break; case IReadOnlyBlockListInner AsBlockListInner: foreach (IReadOnlyBlockState Block in AsBlockListInner.BlockStateList) { stateList.Add(Block.PatternState); stateList.Add(Block.SourceState); foreach (IReadOnlyNodeState ChildState in Block.StateList) { AddChildStates(stateList, ChildState); } } IsHandled = true; break; } Debug.Assert(IsHandled); }
/// <summary> /// Gets the inner corresponding to a property in a node. /// </summary> /// <param name="propertyName">Property name.</param> public virtual IReadOnlyInner <IReadOnlyBrowsingChildIndex> PropertyToInner(string propertyName) { Debug.Assert(!string.IsNullOrEmpty(propertyName)); IReadOnlyInner <IReadOnlyBrowsingChildIndex> Result = null; switch (propertyName) { case nameof(IBlock.ReplicationPattern): Result = PatternInner; break; case nameof(IBlock.SourceIdentifier): Result = SourceInner; break; } Debug.Assert(Result != null); return(Result); }
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 IReadOnlyNodeState BuildChildState(IReadOnlyInner <IReadOnlyBrowsingChildIndex> inner, IReadOnlyBrowsingChildIndex nodeIndex) { IReadOnlyNodeState ChildState = inner.InitChildState(nodeIndex); AddState(nodeIndex, ChildState); // For debugging: count nodes according to their type if (inner is IReadOnlyOptionalInner <IReadOnlyBrowsingOptionalNodeIndex> AsOptionalInner) { Stats.OptionalNodeCount++; if (AsOptionalInner.IsAssigned) { Stats.AssignedOptionalNodeCount++; } } else { Stats.PlaceholderNodeCount++; } return(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); }
void IDictionary <TKey, IReadOnlyInner> .Add(TKey key, IReadOnlyInner value) { Add(key, (IFrameInner)value); }
/// <summary> /// Find children in the node tree. /// </summary> /// <param name="browseContext">The context used to browse the node tree.</param> /// <param name="parentInner">The inner containing this state as a child.</param> public virtual void BrowseChildren(IReadOnlyBrowseContext browseContext, IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner) { BrowseChildrenOfNode(browseContext, Node); }
private protected virtual void InitParentInner(IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner) { Debug.Assert(ParentInner == null); ParentInner = (IReadOnlyInner)parentInner; }
void IDictionary <TKey, IReadOnlyInner> .Add(TKey key, IReadOnlyInner value) { Add(key, (IWriteableInner)value); }
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); }
private protected virtual void BrowseStateChildren(ReadOnlyBrowseContext browseContext, IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner) { Debug.Assert(browseContext.IndexCollectionList.Count == 0); IReadOnlyNodeState State = browseContext.State; ((IReadOnlyNodeState <IReadOnlyInner <IReadOnlyBrowsingChildIndex> >)State).BrowseChildren(browseContext, parentInner); CheckContextConsistency(browseContext); }