View Javadoc

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