|
3 | 3 | using System.Linq; |
4 | 4 | using System.Text; |
5 | 5 | using Library.Exceptions; |
6 | | -using Library.Callbacks; |
| 6 | +using Library.CallbackInvokers; |
7 | 7 |
|
8 | 8 | namespace Library |
9 | 9 | { |
10 | | - public delegate void StateCallback(string currentState); |
11 | | - public delegate void ArcCallback(string sourceState, string targetState); |
| 10 | + public delegate void StateCallback<TState>(TState currentState); |
| 11 | + public delegate void ArcCallback<TState>(TState sourceState, TState targetState); |
12 | 12 |
|
13 | | - public class StateMachine |
| 13 | + public class StateMachine<TState> |
14 | 14 | { |
15 | | - private Dictionary<string, State> _statesMap; |
16 | | - private string _postedState; |
| 15 | + private IDictionary<TState, StateContainer<TState>> _statesMap; |
17 | 16 |
|
18 | 17 | public bool Transiting; |
19 | | - public State CurrentState { get; private set; } |
20 | | - private State this[string stateName] |
| 18 | + public StateContainer<TState> CurrentState { get; private set; } |
| 19 | + private StateContainer<TState> this[TState state] |
21 | 20 | { |
22 | 21 | get |
23 | 22 | { |
24 | | - if (!_statesMap.ContainsKey(stateName)) |
| 23 | + if (!_statesMap.ContainsKey(state)) |
25 | 24 | { |
26 | 25 | return null; |
27 | 26 | } |
28 | 27 |
|
29 | | - return _statesMap[stateName]; |
| 28 | + return _statesMap[state]; |
30 | 29 | } |
31 | 30 | } |
32 | 31 |
|
33 | 32 |
|
34 | 33 | public StateMachine() |
35 | 34 | { |
36 | | - _statesMap = new Dictionary<string, State>(); |
37 | | - _postedState = string.Empty; |
| 35 | + _statesMap = new Dictionary<TState, StateContainer<TState>>(); |
38 | 36 | Transiting = false; |
39 | 37 |
|
40 | 38 | CurrentState = null; |
41 | 39 | } |
42 | 40 |
|
43 | | - public void AddState(string stateName) |
| 41 | + public void AddState(TState stateName) |
44 | 42 | { |
45 | 43 | if (this[stateName] != null) |
46 | 44 | { |
47 | | - throw new StateMachineException(ErrorCodes.AlreadyPresentState, stateName); |
| 45 | + throw new StateMachineException(ErrorCodes.AlreadyPresentState, stateName.ToString()); |
48 | 46 | } |
49 | 47 |
|
50 | | - State s = new State(stateName); |
| 48 | + StateContainer<TState> s = new StateContainer<TState>(stateName); |
51 | 49 | _statesMap[stateName] = s; |
52 | 50 | } |
53 | 51 |
|
54 | | - public void AddArc(string source, string target) |
| 52 | + public void AddTransition(TState source, TState target) |
55 | 53 | { |
56 | | - State sourceState = this[source]; |
| 54 | + StateContainer<TState> sourceState = this[source]; |
57 | 55 |
|
58 | 56 | if (sourceState == null) |
59 | 57 | { |
60 | | - throw new StateMachineException(ErrorCodes.UnknownState, source); |
| 58 | + throw new StateMachineException(ErrorCodes.UnknownState, source.ToString()); |
61 | 59 | } |
62 | 60 |
|
63 | | - State targetState = this[target]; |
| 61 | + StateContainer<TState> targetState = this[target]; |
64 | 62 |
|
65 | 63 | if (targetState == null) |
66 | 64 | { |
67 | | - throw new StateMachineException(ErrorCodes.UnknownState, target); |
| 65 | + throw new StateMachineException(ErrorCodes.UnknownState, target.ToString()); |
68 | 66 | } |
69 | 67 |
|
70 | 68 | sourceState.AddArc(targetState); |
71 | 69 | } |
72 | 70 |
|
73 | | - public void AddEnterStateCallback(string targetStateName, StateCallback method) |
| 71 | + public void AddEnterStateCallback(TState targetStateName, StateCallback<TState> method) |
74 | 72 | { |
75 | | - State targetState = this[targetStateName]; |
| 73 | + StateContainer<TState> targetState = this[targetStateName]; |
76 | 74 |
|
77 | 75 | if (targetState == null) |
78 | 76 | { |
79 | | - throw new StateMachineException(ErrorCodes.UnknownState, targetStateName); |
| 77 | + throw new StateMachineException(ErrorCodes.UnknownState, targetStateName.ToString()); |
80 | 78 | } |
81 | 79 |
|
82 | 80 | targetState.AddStateCallback(method, true); |
83 | 81 | } |
84 | 82 |
|
85 | | - public void AddExitStateCallback(string targetStateName, StateCallback method) |
| 83 | + public void AddExitStateCallback(TState targetStateName, StateCallback<TState> method) |
86 | 84 | { |
87 | | - State targetState = this[targetStateName]; |
| 85 | + StateContainer<TState> targetState = this[targetStateName]; |
88 | 86 |
|
89 | 87 | if (targetState == null) |
90 | 88 | { |
91 | | - throw new StateMachineException(ErrorCodes.UnknownState, targetStateName); |
| 89 | + throw new StateMachineException(ErrorCodes.UnknownState, targetStateName.ToString()); |
92 | 90 | } |
93 | 91 |
|
94 | 92 | targetState.AddStateCallback(method, false); |
95 | 93 | } |
96 | 94 |
|
97 | | - public void AddTransitionCallback(string source, string target, ArcCallback method) |
| 95 | + public void AddTransitionCallback(TState source, TState target, ArcCallback<TState> method) |
98 | 96 | { |
99 | | - State s = this[source]; |
| 97 | + StateContainer<TState> s = this[source]; |
100 | 98 |
|
101 | 99 | if (s == null) |
102 | 100 | { |
103 | | - throw new StateMachineException(ErrorCodes.UnknownState, source); |
| 101 | + throw new StateMachineException(ErrorCodes.UnknownState, source.ToString()); |
104 | 102 | } |
105 | 103 |
|
106 | 104 | s.AddTransitArcCallback(target, method); |
107 | 105 | } |
108 | 106 |
|
109 | | - public void GoToState(string stateName) |
| 107 | + public void GoToState(TState stateName) |
110 | 108 | { |
111 | | - if (Transiting) |
| 109 | + try |
112 | 110 | { |
113 | | - if (_postedState.Length != 0) |
| 111 | + if (Transiting) |
114 | 112 | { |
115 | | - throw new StateMachineException(ErrorCodes.PostedStateAreadySet, string.Empty); |
| 113 | + return; |
116 | 114 | } |
117 | 115 |
|
118 | | - _postedState = stateName; |
119 | | - return; |
120 | | - } |
121 | | - |
122 | | - try |
123 | | - { |
124 | | - PostedStateRestart: |
125 | 116 | Transiting = true; |
| 117 | + StateContainer<TState> target = this[stateName]; |
126 | 118 |
|
127 | | - State target = this[stateName]; |
| 119 | + if (target == null) |
| 120 | + { |
| 121 | + throw new StateMachineException(ErrorCodes.UnknownState, stateName.ToString()); |
| 122 | + } |
128 | 123 |
|
129 | | - if (target == null) |
130 | | - { |
131 | | - throw new StateMachineException(ErrorCodes.UnknownState, stateName); |
132 | | - } |
| 124 | + if (CurrentState != null) |
| 125 | + { |
| 126 | + Transition<TState> arc = CurrentState[target]; |
133 | 127 |
|
134 | | - if (CurrentState != null) |
| 128 | + if (arc == null) |
135 | 129 | { |
136 | | - Arc arc = CurrentState[target]; |
137 | | - |
138 | | - if (arc == null) |
139 | | - { |
140 | | - throw new StateMachineException(ErrorCodes.InvalidTransition, StateMachineException.MakeArcName(CurrentState.Name, target.Name)); |
141 | | - } |
142 | | - |
143 | | - CurrentState.CallExitCallbacks(); |
144 | | - arc.CallTransitionCallbacks(); |
| 130 | + throw new StateMachineException(ErrorCodes.InvalidTransition, StateMachineException.MakeArcName(CurrentState.Name, target.Name)); |
145 | 131 | } |
146 | 132 |
|
147 | | - CurrentState = target; |
148 | | - target.CallEnterCallbacks(); |
149 | | - Transiting = false; |
| 133 | + CurrentState.CallExitCallbacks(); |
| 134 | + arc.CallTransitionCallbacks(); |
| 135 | + } |
150 | 136 |
|
151 | | - if (_postedState.Length != 0) |
152 | | - { |
153 | | - stateName = _postedState; |
154 | | - _postedState = string.Empty; |
155 | | - goto PostedStateRestart; //tail recursion |
156 | | - } |
| 137 | + CurrentState = target; |
| 138 | + target.CallEnterCallbacks(); |
| 139 | + Transiting = false; |
157 | 140 | } |
158 | 141 | catch |
159 | 142 | { |
|
0 commit comments