View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  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  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         // Each call creates a new List, this will change once TO-DO is handled
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