View Javadoc

1   /*
2    * Copyright (C) 2006  Tom Gibara
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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  //TODO consider adding method that identifies if engine is in a terminal state
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 }