1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml.model;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 /***
26 * The class in this SCXML object model that corresponds to the
27 * <state> SCXML element.
28 *
29 */
30 public class State extends TransitionTarget {
31
32 /***
33 * Serial version UID.
34 */
35 private static final long serialVersionUID = 1L;
36
37 /***
38 * The Map containing immediate children of this State, keyed by
39 * their IDs. Incompatible with the parallel or invoke property.
40 */
41 private Map children;
42
43 /***
44 * The Parallel child, which defines a set of parallel substates.
45 * May occur 0 or 1 times. Incompatible with the state or invoke property.
46 */
47 private Parallel parallel;
48
49 /***
50 * The Invoke child, which defines an external process that should
51 * be invoked, immediately after the onentry executable content,
52 * and the transitions become candidates after the invoked
53 * process has completed its execution.
54 * May occur 0 or 1 times. Incompatible with the state or parallel
55 * property.
56 */
57 private Invoke invoke;
58
59 /***
60 * Boolean property indicating whether this is a final state or not.
61 * Default value is false . Final states may not have substates or
62 * outgoing transitions.
63 */
64 private boolean isFinal;
65
66 /***
67 * A child which identifies initial state for state machines that
68 * have substates.
69 */
70 private Initial initial;
71
72 /***
73 * A map of outgoing Transitions from this state.
74 */
75 private Map transitions;
76
77 /***
78 * List of history states owned by a given state (applies to non-leaf
79 * states).
80 */
81 private List history;
82
83 /***
84 * Applies to composite states only. If one of its final children is
85 * active, its parent is marked done. This property is reset upon
86 * re-entry.
87 */
88 private boolean done = false;
89
90 /***
91 * Constructor.
92 */
93 public State() {
94 this.children = new HashMap();
95 this.transitions = new HashMap();
96 this.history = new ArrayList();
97 }
98
99 /***
100 * Is this state a "final" state.
101 *
102 * @return boolean Returns the isFinal.
103 */
104 public final boolean getIsFinal() {
105 return isFinal;
106 }
107
108 /***
109 * Set whether this is a "final" state.
110 *
111 * @param isFinal
112 * The isFinal to set.
113 */
114 public final void setIsFinal(final boolean isFinal) {
115 this.isFinal = isFinal;
116 }
117
118 /***
119 * Get the Parallel child (may be null).
120 *
121 * @return Parallel Returns the parallel.
122 */
123 public final Parallel getParallel() {
124 return parallel;
125 }
126
127 /***
128 * Set the Parallel child.
129 *
130 * @param parallel
131 * The parallel to set.
132 */
133 public final void setParallel(final Parallel parallel) {
134 this.parallel = parallel;
135 }
136
137 /***
138 * Get the Invoke child (may be null).
139 *
140 * @return Invoke Returns the invoke.
141 */
142 public final Invoke getInvoke() {
143 return invoke;
144 }
145
146 /***
147 * Set the Invoke child.
148 *
149 * @param invoke
150 * The invoke to set.
151 */
152 public final void setInvoke(final Invoke invoke) {
153 this.invoke = invoke;
154 }
155
156 /***
157 * Get the initial state.
158 *
159 * @return Initial Returns the initial state.
160 */
161 public final Initial getInitial() {
162 return initial;
163 }
164
165 /***
166 * Set the initial state.
167 *
168 * @param target
169 * The target to set.
170 */
171 public final void setInitial(final Initial target) {
172 this.initial = target;
173 }
174
175 /***
176 * Get the map of all outgoing transitions from this state.
177 *
178 * @return Map Returns the transitions Map.
179 */
180 public final Map getTransitions() {
181 return transitions;
182 }
183
184 /***
185 * Get the list of all outgoing transitions from this state, that
186 * will be candidates for being fired on the given event.
187 *
188 * @param event The event
189 * @return List Returns the candidate transitions for given event
190 */
191 public final List getTransitionsList(final String event) {
192 Object candidateTransitions = transitions.get(event);
193 if (candidateTransitions == null) {
194 return null;
195 }
196 return (List) candidateTransitions;
197 }
198
199 /***
200 * Add a transition to the map of all outgoing transitions for
201 * this state.
202 *
203 * @param transition
204 * The transitions to set.
205 */
206 public final void addTransition(final Transition transition) {
207 String event = transition.getEvent();
208 if (!transitions.containsKey(event)) {
209 List eventTransitions = new ArrayList();
210 eventTransitions.add(transition);
211 transitions.put(event, eventTransitions);
212 } else {
213 ((List) transitions.get(event)).add(transition);
214 }
215 }
216
217 /***
218 * Get the map of child states (may be empty).
219 *
220 * @return Map Returns the children.
221 */
222 public final Map getChildren() {
223 return children;
224 }
225
226 /***
227 * Add a child state.
228 *
229 * @param state
230 * a child state
231 */
232 public final void addChild(final State state) {
233 this.children.put(state.getId(), state);
234 state.setParent(this);
235 }
236
237 /***
238 * Get the outgoing transitions for this state as a java.util.List.
239 *
240 * @return List Returns the transitions (as a list). TODO - Check in next
241 * iteration whether both methods need to be retained.
242 */
243 public final List getTransitionsList() {
244
245 List transitionsList = new ArrayList();
246 for (Iterator iter = transitions.keySet().iterator();
247 iter.hasNext();) {
248 transitionsList.addAll((List) transitions.get(iter.next()));
249 }
250 return transitionsList;
251 }
252
253 /***
254 * This method is used by XML digester.
255 *
256 * @param h
257 * History pseudo state
258 */
259 public final void addHistory(final History h) {
260 history.add(h);
261 }
262
263 /***
264 * Does this state have a history pseudo state.
265 *
266 * @return boolean true if a given state contains at least one
267 * history pseudo state
268 */
269 public final boolean hasHistory() {
270 return (!history.isEmpty());
271 }
272
273 /***
274 * Get the list of history pseudo states for this state.
275 *
276 * @return a list of all history pseudo states contained by a given state
277 * (can be empty)
278 * @see #hasHistory()
279 */
280 public final List getHistory() {
281 return history;
282 }
283
284 /***
285 * Check whether this is a simple (leaf) state (UML terminology).
286 *
287 * @return true if this is a simple state, otherwise false
288 */
289 public final boolean isSimple() {
290 if (parallel == null && children.isEmpty()) {
291 return true;
292 }
293 return false;
294 }
295
296 /***
297 * Check whether this is a composite state (UML terminology).
298 *
299 * @return true if this is a composite state, otherwise false
300 */
301 public final boolean isComposite() {
302 if (parallel == null && children.isEmpty()) {
303 return false;
304 }
305 return true;
306 }
307
308 /***
309 * Checks whether it is a region state (directly nested to parallel - UML
310 * terminology).
311 *
312 * @return true if this is a region state, otherwise false
313 * @see Parallel
314 */
315 public final boolean isRegion() {
316 if (getParent() instanceof Parallel) {
317 return true;
318 }
319 return false;
320 }
321
322 /***
323 * Checks whether it is a orthogonal state, that is, it owns a parallel
324 * (UML terminology).
325 *
326 * @return true if this is a orthogonal state, otherwise false
327 */
328 public final boolean isOrthogonal() {
329 if (parallel != null) {
330 return true;
331 }
332 return false;
333 }
334
335 /***
336 * In case this is a parallel state, check if one its final states
337 * is active.
338 *
339 * @return Returns the done.
340 */
341 public final boolean isDone() {
342 return done;
343 }
344
345 /***
346 * Update the done property, which is set if this is a parallel state,
347 * and one its final states is active.
348 *
349 * @param done The done to set.
350 */
351 public final void setDone(final boolean done) {
352 this.done = done;
353 }
354 }
355