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.LinkedHashMap;
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 = 2L;
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 list of outgoing Transitions from this state, by document order.
74       */
75      private List transitions;
76  
77      /***
78       * Applies to composite states only. If one of its final children is
79       * active, its parent is marked done. This property is reset upon
80       * re-entry.
81       *
82       * @deprecated Will be removed in v1.0
83       */
84      private boolean done = false;
85  
86      /***
87       * Constructor.
88       */
89      public State() {
90          this.children = new LinkedHashMap();
91          this.transitions = new ArrayList();
92      }
93  
94      /***
95       * Is this state a "final" state.
96       *
97       * @return boolean Returns the isFinal.
98       * @deprecated Use {@link #isFinal()} instead
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      * @deprecated Use {@link #setFinal(boolean)} instead
110      */
111     public final void setIsFinal(final boolean isFinal) {
112         this.isFinal = isFinal;
113     }
114 
115     /***
116      * Is this state a "final" state.
117      *
118      * @return boolean Returns the isFinal.
119      *
120      * @since 0.7
121      */
122     public final boolean isFinal() {
123         return isFinal;
124     }
125 
126     /***
127      * Set whether this is a "final" state.
128      *
129      * @param isFinal
130      *            The isFinal to set.
131      *
132      * @since 0.7
133      */
134     public final void setFinal(final boolean isFinal) {
135         this.isFinal = isFinal;
136     }
137 
138     /***
139      * Get the Parallel child (may be null).
140      *
141      * @return Parallel Returns the parallel.
142      *
143      * @deprecated <parallel> no longer needs an enclosing
144      *             <state> element.
145      */
146     public final Parallel getParallel() {
147         return parallel;
148     }
149 
150     /***
151      * Set the Parallel child.
152      *
153      * @param parallel
154      *            The parallel to set.
155      *
156      * @deprecated <parallel> no longer needs an enclosing
157      *             <state> element.
158      */
159     public final void setParallel(final Parallel parallel) {
160         this.parallel = parallel;
161     }
162 
163     /***
164      * Get the Invoke child (may be null).
165      *
166      * @return Invoke Returns the invoke.
167      */
168     public final Invoke getInvoke() {
169         return invoke;
170     }
171 
172     /***
173      * Set the Invoke child.
174      *
175      * @param invoke
176      *            The invoke to set.
177      */
178     public final void setInvoke(final Invoke invoke) {
179         this.invoke = invoke;
180     }
181 
182     /***
183      * Get the initial state.
184      *
185      * @return Initial Returns the initial state.
186      */
187     public final Initial getInitial() {
188         return initial;
189     }
190 
191     /***
192      * Set the initial state.
193      *
194      * @param target
195      *            The target to set.
196      */
197     public final void setInitial(final Initial target) {
198         this.initial = target;
199         target.setParent(this);
200     }
201 
202     /***
203      * Get the map of all outgoing transitions from this state.
204      *
205      * @return Map Returns the transitions Map.
206      * @deprecated Use {@link #getTransitionsList()} instead
207      */
208     public final Map getTransitions() {
209         Map transitionsMap = new HashMap();
210         for (int i = 0; i < transitions.size(); i++) {
211             Transition transition = (Transition) transitions.get(i);
212             String event = transition.getEvent();
213             if (!transitionsMap.containsKey(event)) {
214                 List eventTransitions = new ArrayList();
215                 eventTransitions.add(transition);
216                 transitionsMap.put(event, eventTransitions);
217             } else {
218                 ((List) transitionsMap.get(event)).add(transition);
219             }
220         }
221         return transitionsMap;
222     }
223 
224     /***
225      * Get the list of all outgoing transitions from this state, that
226      * will be candidates for being fired on the given event.
227      *
228      * @param event The event
229      * @return List Returns the candidate transitions for given event
230      */
231     public final List getTransitionsList(final String event) {
232         List matchingTransitions = null; // since we returned null upto v0.6
233         for (int i = 0; i < transitions.size(); i++) {
234             Transition t = (Transition) transitions.get(i);
235             if ((event == null && t.getEvent() == null)
236                     || (event != null && event.equals(t.getEvent()))) {
237                 if (matchingTransitions == null) {
238                     matchingTransitions = new ArrayList();
239                 }
240                 matchingTransitions.add(t);
241             }
242         }
243         return matchingTransitions;
244     }
245 
246     /***
247      * Add a transition to the map of all outgoing transitions for
248      * this state.
249      *
250      * @param transition
251      *            The transitions to set.
252      */
253     public final void addTransition(final Transition transition) {
254         transitions.add(transition);
255         transition.setParent(this);
256     }
257 
258     /***
259      * Get the map of child states (may be empty).
260      *
261      * @return Map Returns the children.
262      */
263     public final Map getChildren() {
264         return children;
265     }
266 
267     /***
268      * Add a child state.
269      *
270      * @param state
271      *            a child state
272      *
273      * @deprecated Use {@link #addChild(TransitionTarget)} instead.
274      */
275     public final void addChild(final State state) {
276         this.children.put(state.getId(), state);
277         state.setParent(this);
278     }
279 
280     /***
281      * Add a child transition target.
282      *
283      * @param tt
284      *            a child transition target
285      *
286      * @since 0.7
287      */
288     public final void addChild(final TransitionTarget tt) {
289         this.children.put(tt.getId(), tt);
290         tt.setParent(this);
291     }
292 
293     /***
294      * Get the outgoing transitions for this state as a java.util.List.
295      *
296      * @return List Returns the transitions list.
297      */
298     public final List getTransitionsList() {
299         return transitions;
300     }
301 
302     /***
303      * Check whether this is a simple (leaf) state (UML terminology).
304      *
305      * @return true if this is a simple state, otherwise false
306      */
307     public final boolean isSimple() {
308         if (parallel == null && children.isEmpty()) {
309             return true;
310         }
311         return false;
312     }
313 
314     /***
315      * Check whether this is a composite state (UML terminology).
316      *
317      * @return true if this is a composite state, otherwise false
318      */
319     public final boolean isComposite() {
320         if (parallel == null && children.isEmpty()) {
321             return false;
322         }
323         return true;
324     }
325 
326     /***
327      * Checks whether it is a region state (directly nested to parallel - UML
328      * terminology).
329      *
330      * @return true if this is a region state, otherwise false
331      * @see Parallel
332      */
333     public final boolean isRegion() {
334         if (getParent() instanceof Parallel) {
335             return true;
336         }
337         return false;
338     }
339 
340     /***
341      * Checks whether it is a orthogonal state, that is, it owns a parallel
342      * (UML terminology).
343      *
344      * @return true if this is a orthogonal state, otherwise false
345      * @deprecated &lt;parallel&gt; now represents an orthogonal state, rather
346      *             than denoting that the enclosing state is orthogonal, as
347      *             it did in previous SCXML WDs.
348      */
349     public final boolean isOrthogonal() {
350         if (parallel != null) {
351             return true;
352         }
353         return false;
354     }
355 
356     /***
357      * In case this is a parallel state, check if one its final states
358      * is active.
359      *
360      * @return Returns the done.
361      * @deprecated Will be removed in v1.0, in favor of
362      *             <code>SCInstance#isDone(TransitionTarget)</code>
363      */
364     public final boolean isDone() {
365         return done;
366     }
367 
368     /***
369      * Update the done property, which is set if this is a parallel state,
370      * and one its final states is active.
371      *
372      * @param done The done to set.
373      * @deprecated Will be removed in v1.0, in favor of
374      *             <code>SCInstance#setDone(TransitionTarget)</code>
375      */
376     public final void setDone(final boolean done) {
377         this.done = done;
378     }
379 }
380