State Configurations |
Explains what a StateConfiguration is and where it is used.
Describing the active state of a plain state machine is simple: A reference to a single state is sufficient. Source and target states of transitions in a plain state machine can simply be addressed through references to single states. Also the active state in a hierarchical state machine is sufficiently defined through the ultimate leaf simple state, regardless of nesting depth. Transitions starting or ending at a composite state can be described through the reference to the composite state.
Things start to become more complex with orthogonal sub-states:
Defining the active state in the presence of orthogonal sub-regions requires references to multiple states in case the state machine is in the orthogonal sub-states. The same applies for transition source and target states. While it would be possible to handle active states and transition source and target states as a simple array of state references, it turns out that this is computationally inefficient when questions have to be answered like these:
Is a set of states really valid, which means are the referenced states really in separate orthogonal sub-regions?
What is the common region between the source and target of a transition, i.e. the tree node up to which exit actions and from which entry actions have to be executed in case the transition is executed?
Is the active state identical to (or is it a sub-state of) a particular transition's source state? The answer of this question is needed to identify the reached transitions, and it is particular complex to answer in case of a partially defined source state of a join transition.
This is where the StaMa.StateConfiguration type helps. StateConfiguration instances are used to keep the active state of a StateMachine and for the SourceState and TargetState properties of Transitions.
For the client code there is usually no need to explicitly create StateConfiguration instances, as the StateMachineTemplate.Transition statement accepts arrays of state names for defining the source and target states of fork and join Transitions. For special cases StateConfiguration instances can be created through the StateMachineTemplate.CreateStateConfiguration method, if needed.
The StateConfiguration for the active state property is managed internally.
In order to get a human readable format for tracing or debugging, the StateConfiguration.ToString method returns the referenced state name or state names concatenated into a single String. See StateConfiguration.ToString for details of the format.
The built-in StateConfiguration.ToString method traverses the state machine structure and collects all state names in a String with some structure formatting characters like '(', ')', ',' and '*' by utilizing the StateConfiguration.PassThrough method.
The following code shows how to implement an individual formatting method.
public static class StateConfigurationUtils { public static string Format(StateConfiguration stateConfiguration) { StateConfigurationWriter writer = new StateConfigurationWriter(); stateConfiguration.PassThrough(writer); return writer.ToString(); } private class StateConfigurationWriter : IStateConfigurationVisitor { System.Text.StringBuilder text = new System.Text.StringBuilder(256); public override string ToString() { return text.ToString(); } public void State(State state) { text.Append(state.Name); } public void StateAny() { text.Append("*"); } public void BeginSubStates() { text.Append("("); } public void EndSubStates() { text.Append(")"); } public void NextSubState() { text.Append(","); } } }