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