1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.tomgibara.pronto.state;
20
21 import java.util.Set;
22
23 /**
24 * State Engines manage transitions across a pre-defined graph of allowed states
25 * and state transitions. Work that is to be done as part of a transition is
26 * performed by a <code>StateActivator</code> assigned to the engine. When an
27 * engine is first created (or after the failure of a transition due to a
28 * unchecked exception being thrown by the engine's associated activator), the
29 * engine is in an indeterminate state and the setState method must be called
30 * before any transmissions may be made. Instances of this class are entirely
31 * safe for concurrent access.
32 *
33 * @param <S>
34 * the type of states in the engine's state graph
35 * @param <L>
36 * the type of labels on the engine's state graph
37 * @param <P>
38 * the type of transition parameterisation of the state activator
39 *
40 * @author Tom Gibara
41 */
42
43
44 public interface StateEngine<S, L, P> {
45
46 /**
47 * Sets the policy under which the state engine will operate. Supplying a
48 * null value causes an instance of <code>DefaultStatePolicy</code> to be
49 * used.
50 *
51 * @param policy
52 * the engine's policy, may be null
53 */
54
55 void setPolicy(StateEnginePolicy policy);
56
57 /**
58 * The policy under which the engine is operating.
59 *
60 * @return the engine's policy, never null
61 */
62
63 StateEnginePolicy getPolicy();
64
65 /**
66 * The graph of an engine constrains the states which it may enter and the
67 * transitions it may make.
68 *
69 * @return the state graph which this engine operates over, never null
70 */
71
72 StateGraph<S, L> getGraph();
73
74 /**
75 * Returns a set of the states which are currently permitted in a call to
76 * <code>setState</code>. Initially, this will be every state in the
77 * engine's state graph. After a state has been set, only the current state
78 * will be returned unless a transition failure has occured due to an
79 * unchecked exception in which case the possible states are the initial and
80 * final states of the transition which failed.
81 *
82 * @return an immutable set of states which may be empty, never null
83 */
84
85 Set<S> getPossibleStates();
86
87 /**
88 * The state that this engine is currently in. If the engine is in an
89 * indeterminate state (due to the failure of a transition, or because no
90 * state has yet been set), this method returns null.
91 *
92 * @return the current state or null
93 */
94
95 S getState();
96
97 /**
98 * Puts the engine into a specified state. This method does not trigger any
99 * transitions but attempts to set the state of the engine directly. This
100 * method may fail with a ProntoStateException if the state is impossible,
101 * or if the state change is vetoed, or if an unexpected exception occured
102 * during the state change. Setting the state to the current state has no
103 * effect.
104 *
105 * Depending on the engine's current policy, exceptions raised by listeners
106 * in response to the transitioning may be thrown from this method.
107 *
108 * @param state
109 * the state into which the engine should be put
110 * @throws ProntoStateException
111 * if the state change is impossible, vetoed or failed
112 */
113
114 void setState(S state) throws ProntoStateException;
115
116 /**
117 * This method is called to instruct the engine to make one (or possibly
118 * more) state transitions. Before this method is called, the engine must be
119 * in a determinate state.
120 *
121 * The target state and transition label supplied to this method are
122 * combined with the current engine state in an attempt to identify a
123 * uniquely matching transition. If no such transition exists (or is not
124 * unique) an exception is raised, otherwise a transition is attempted.
125 *
126 * Either one or both of the specified label and state may be null.
127 * Naturally, if both are null then there must be a single exit transition
128 * from the current state or an exception is raised.
129 *
130 * In the event that a transition fails due to an unchecked exception being
131 * thrown by the engine's state activator, the engine enters an
132 * indeterminate state in which <code>getState()</code> will return null.
133 *
134 * Depending on the engine's current policy, exceptions raised by listeners
135 * in response to the transitioning may be thrown from this method. Such
136 * exceptions will not cause the engine to enter an indeterminate state.
137 *
138 * @param state
139 * the state to transition to, may be null
140 * @param label
141 * a constraint on the transition, may be null
142 * @param parameter
143 * passed through to the activator on transition, may be null if
144 * the activator permits it
145 * @throws ProntoStateException
146 * if the transition fails for any reason including: the engine
147 * being in an indetermintate state, the activator vetoing the
148 * transition, the activator failing with a unchecked exception,
149 * the lack of a matching transition, the presence of more than
150 * one matching transition
151 * @throws IllegalArgumentException
152 * if the method is called with null state and null label
153 */
154 void transition(S state, L label, P parameter) throws ProntoStateException, IllegalArgumentException;
155
156 /**
157 * This method is called to instruct the engine to make a sequence of state
158 * transitions. Before this method is called, the engine must be in a
159 * determinate state. This method may be used in several ways depending on
160 * the combination of parameters supplied.
161 *
162 * If the method is called with a non-null state, a single sequence of
163 * transitions from the current state into the specified state is sought.
164 * Otherwise the method will attempt to identify a unique terminal state
165 * (given the engine's current state and any specified label) and transition
166 * into that state.
167 *
168 * If the method is called with a label then only transitions with matching
169 * labels will be traversed to attain the specified state.
170 *
171 * The type parameter constrains the sequences of transitions that this
172 * method is permitted to consider for transition into the target state. If
173 * there is more than one possible sequence of transitions between the
174 * initial and target states and exception is raised.
175 *
176 * In the event that a transition fails due to an unchecked exception being
177 * thrown by the engine's state activator, the engine enters an
178 * indeterminate state in which <code>getState()</code> will return null.
179 *
180 * Depending on the engine's current policy, exceptions raised by listeners
181 * in response to the transitioning may be thrown from this method. Such
182 * exceptions will not cause the engine to enter an indeterminate state.
183 *
184 * @param state
185 * the state to transition to, may be null
186 * @param label
187 * a constraint on each transition, may be null
188 * @param type
189 * a constraint on the sequence of transitions
190 * @param parameters
191 * may supply a parameter for each transition, may be null in
192 * which case a null parameter will be supplied for every
193 * transition
194 * @throws ProntoStateException
195 * if the transition fails for any reason including: the engine
196 * being in an indetermintate state, the activator vetoing the
197 * transition, the activator failing with a unchecked exception,
198 * the lack of a matching sequence of transition, the presence
199 * of more than one matching sequence of transitions.
200 * @throws IllegalArgumentException
201 * if the method is called with null state and null label
202 */
203 void pathTransition(S state, L label, PathType type, StateTransitionParameters<S, L, P> parameters)
204 throws ProntoStateException, IllegalArgumentException;
205
206 /**
207 * Adds a state listener to this engine. A given state listener instance can
208 * only be added once. The state listener will be notified after each
209 * successful change of state. Event dispatch is currently done on the
210 * state-changing thread but this is currently subject to change. Unchecked
211 * exceptions raised by listeners will not invalidate the engine state.
212 *
213 * @param listener
214 * the state listener to be added
215 *
216 * @return true if the listener was added, false if it is already registered
217 * as a listener
218 */
219
220 boolean addStateListener(StateListener<S, L> listener);
221
222 /**
223 * Removes a previously added state listener from this engine.
224 *
225 * @param listener
226 * the listener to be removed
227 * @return true if the listener was removed, false if the object was not a
228 * registered listener
229 */
230
231 boolean removeStateListener(StateListener<S, L> listener);
232
233 }