001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.scxml.model;
018    
019    import java.util.LinkedHashMap;
020    import java.util.Map;
021    
022    /**
023     * The class in this SCXML object model that corresponds to the
024     * <state> SCXML element.
025     *
026     */
027    public class State extends TransitionTarget {
028    
029        /**
030         * Serial version UID.
031         */
032        private static final long serialVersionUID = 2L;
033    
034        /**
035         * The Map containing immediate children of this State, keyed by
036         * their IDs. Incompatible with the parallel or invoke property.
037         */
038        private Map children;
039    
040        /**
041         * The Parallel child, which defines a set of parallel substates.
042         * May occur 0 or 1 times. Incompatible with the state or invoke property.
043         */
044        private Parallel parallel;
045    
046        /**
047         * The Invoke child, which defines an external process that should
048         * be invoked, immediately after the onentry executable content,
049         * and the transitions become candidates after the invoked
050         * process has completed its execution.
051         * May occur 0 or 1 times. Incompatible with the state or parallel
052         * property.
053         */
054        private Invoke invoke;
055    
056        /**
057         * Boolean property indicating whether this is a final state or not.
058         * Default value is false . Final states may not have substates or
059         * outgoing transitions.
060         */
061        private boolean isFinal;
062    
063        /**
064         * A child which identifies initial state for state machines that
065         * have substates.
066         */
067        private Initial initial;
068    
069        /**
070         * Applies to composite states only. If one of its final children is
071         * active, its parent is marked done. This property is reset upon
072         * re-entry.
073         *
074         * @deprecated Will be removed in v1.0
075         */
076        private boolean done = false;
077    
078        /**
079         * Constructor.
080         */
081        public State() {
082            this.children = new LinkedHashMap();
083        }
084    
085        /**
086         * Is this state a "final" state.
087         *
088         * @return boolean Returns the isFinal.
089         * @deprecated Use {@link #isFinal()} instead
090         */
091        public final boolean getIsFinal() {
092            return isFinal;
093        }
094    
095        /**
096         * Set whether this is a "final" state.
097         *
098         * @param isFinal
099         *            The isFinal to set.
100         * @deprecated Use {@link #setFinal(boolean)} instead
101         */
102        public final void setIsFinal(final boolean isFinal) {
103            this.isFinal = isFinal;
104        }
105    
106        /**
107         * Is this state a "final" state.
108         *
109         * @return boolean Returns the isFinal.
110         *
111         * @since 0.7
112         */
113        public final boolean isFinal() {
114            return isFinal;
115        }
116    
117        /**
118         * Set whether this is a "final" state.
119         *
120         * @param isFinal
121         *            The isFinal to set.
122         *
123         * @since 0.7
124         */
125        public final void setFinal(final boolean isFinal) {
126            this.isFinal = isFinal;
127        }
128    
129        /**
130         * Get the Parallel child (may be null).
131         *
132         * @return Parallel Returns the parallel.
133         *
134         * @deprecated <parallel> no longer needs an enclosing
135         *             <state> element.
136         */
137        public final Parallel getParallel() {
138            return parallel;
139        }
140    
141        /**
142         * Set the Parallel child.
143         *
144         * @param parallel
145         *            The parallel to set.
146         *
147         * @deprecated <parallel> no longer needs an enclosing
148         *             <state> element.
149         */
150        public final void setParallel(final Parallel parallel) {
151            this.parallel = parallel;
152        }
153    
154        /**
155         * Get the Invoke child (may be null).
156         *
157         * @return Invoke Returns the invoke.
158         */
159        public final Invoke getInvoke() {
160            return invoke;
161        }
162    
163        /**
164         * Set the Invoke child.
165         *
166         * @param invoke
167         *            The invoke to set.
168         */
169        public final void setInvoke(final Invoke invoke) {
170            this.invoke = invoke;
171        }
172    
173        /**
174         * Get the initial state.
175         *
176         * @return Initial Returns the initial state.
177         */
178        public final Initial getInitial() {
179            return initial;
180        }
181    
182        /**
183         * Set the initial state.
184         *
185         * @param target
186         *            The target to set.
187         */
188        public final void setInitial(final Initial target) {
189            this.initial = target;
190            target.setParent(this);
191        }
192    
193        /**
194         * Get the initial state's ID.
195         *
196         * @return The initial state's string ID.
197         */
198        public final String getFirst() {
199            if (initial != null) {
200                return initial.getTransition().getNext();
201            }
202            return null;
203        }
204    
205        /**
206         * Set the initial state by its ID string.
207         *
208         * @param target
209         *            The initial target's ID to set.
210         */
211        public final void setFirst(final String target) {
212            Transition t = new Transition();
213            t.setNext(target);
214            Initial ini = new Initial();
215            ini.setTransition(t);
216            ini.setParent(this);
217            this.initial = ini;
218        }
219    
220        /**
221         * Get the map of child states (may be empty).
222         *
223         * @return Map Returns the children.
224         */
225        public final Map getChildren() {
226            return children;
227        }
228    
229        /**
230         * Add a child state.
231         *
232         * @param state
233         *            a child state
234         *
235         * @deprecated Use {@link #addChild(TransitionTarget)} instead.
236         */
237        public final void addChild(final State state) {
238            this.children.put(state.getId(), state);
239            state.setParent(this);
240        }
241    
242        /**
243         * Add a child transition target.
244         *
245         * @param tt
246         *            a child transition target
247         *
248         * @since 0.7
249         */
250        public final void addChild(final TransitionTarget tt) {
251            this.children.put(tt.getId(), tt);
252            tt.setParent(this);
253        }
254    
255        /**
256         * Check whether this is a simple (leaf) state (UML terminology).
257         *
258         * @return true if this is a simple state, otherwise false
259         */
260        public final boolean isSimple() {
261            if (parallel == null && children.isEmpty()) {
262                return true;
263            }
264            return false;
265        }
266    
267        /**
268         * Check whether this is a composite state (UML terminology).
269         *
270         * @return true if this is a composite state, otherwise false
271         */
272        public final boolean isComposite() {
273            if (parallel == null && children.isEmpty()) {
274                return false;
275            }
276            return true;
277        }
278    
279        /**
280         * Checks whether it is a region state (directly nested to parallel - UML
281         * terminology).
282         *
283         * @return true if this is a region state, otherwise false
284         * @see Parallel
285         */
286        public final boolean isRegion() {
287            if (getParent() instanceof Parallel) {
288                return true;
289            }
290            return false;
291        }
292    
293        /**
294         * Checks whether it is a orthogonal state, that is, it owns a parallel
295         * (UML terminology).
296         *
297         * @return true if this is a orthogonal state, otherwise false
298         * @deprecated <parallel> now represents an orthogonal state, rather
299         *             than denoting that the enclosing state is orthogonal, as
300         *             it did in previous SCXML WDs.
301         */
302        public final boolean isOrthogonal() {
303            if (parallel != null) {
304                return true;
305            }
306            return false;
307        }
308    
309        /**
310         * In case this is a parallel state, check if one its final states
311         * is active.
312         *
313         * @return Returns the done.
314         * @deprecated Will be removed in v1.0, in favor of
315         *             <code>SCInstance#isDone(TransitionTarget)</code>
316         */
317        public final boolean isDone() {
318            return done;
319        }
320    
321        /**
322         * Update the done property, which is set if this is a parallel state,
323         * and one its final states is active.
324         *
325         * @param done The done to set.
326         * @deprecated Will be removed in v1.0, in favor of
327         *             <code>SCInstance#setDone(TransitionTarget)</code>
328         */
329        public final void setDone(final boolean done) {
330            this.done = done;
331        }
332    }
333