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.scxml2.model;
18
19 import java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.HashMap;
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 * <scxml> root element, and serves as the "document
28 * root".
29 *
30 */
31 public class SCXML implements Serializable, Observable,
32 NamespacePrefixesHolder {
33
34 /**
35 * Serial version UID.
36 */
37 private static final long serialVersionUID = 2L;
38
39 /**
40 * The SCXML XMLNS.
41 */
42 @SuppressWarnings("unused")
43 public static final String XMLNS = "http://www.w3.org/2005/07/scxml";
44
45 /**
46 * Reserved prefix for auto generated TransitionTarget id values
47 */
48 public static final String GENERATED_TT_ID_PREFIX = "_generated_tt_id_";
49
50 /**
51 * The predefined observableId with value 0 (zero) for this SCXML state machine
52 */
53 private static final Integer SCXML_OBSERVABLE_ID = 0;
54
55 /**
56 * The xmlns attribute on the root <smxml> element.
57 * This must match XMLNS above.
58 */
59 private String xmlns;
60
61 /**
62 * The SCXML version of this document.
63 */
64 private String version;
65
66 /**
67 * The initial Transition for the SCXML executor.
68 */
69 private SimpleTransition initialTransition;
70
71 /**
72 * The initial transition target ID
73 */
74 private String initial;
75
76 /**
77 * The name for this state machine.
78 */
79 private String name;
80
81 /**
82 * The profile in use.
83 */
84 private String profile;
85
86 /**
87 * The exmode for this document.
88 */
89 private String exmode;
90
91
92 /**
93 * The datamodel name as specified as "datamodel" attribute on this document
94 */
95 private String datamodelName;
96
97 /**
98 * Optional property holding the data model for this SCXML document.
99 * This gets merged with the root context and potentially hides any
100 * (namesake) variables in the root context.
101 */
102 private Datamodel datamodel;
103
104 /**
105 * Optional property holding the initial script for this SCXML document.
106 */
107 private Script globalScript;
108
109 /**
110 * The immediate child targets of this SCXML document root.
111 */
112 private List<EnterableState> children;
113
114 /**
115 * A global map of all States and Parallels associated with this
116 * state machine, keyed by their id.
117 */
118 private Map<String, TransitionTarget> targets;
119
120 /**
121 * The XML namespaces defined on the SCXML document root node,
122 * preserved primarily for serialization.
123 */
124 private Map<String, String> namespaces;
125
126 /**
127 * The next auto-generated transition target unique id value
128 * @see #generateTransitionTargetId()
129 */
130 private long ttNextId;
131
132 /**
133 * Constructor.
134 */
135 public SCXML() {
136 this.children = new ArrayList<EnterableState>();
137 this.targets = new HashMap<String, TransitionTarget>();
138 }
139
140 /**
141 * {@inheritDoc}
142 */
143 public final Integer getObservableId() {
144 return SCXML_OBSERVABLE_ID;
145 }
146
147 /**
148 * Simple unique TransitionTarget id value generation
149 * @return a unique TransitionTarget id for this SCXML instance
150 */
151 public final String generateTransitionTargetId() {
152 return GENERATED_TT_ID_PREFIX +ttNextId++;
153 }
154
155 public final Script getGlobalScript() {
156 return globalScript;
157 }
158
159 public final void setGlobalScript(Script script) {
160 this.globalScript = script;
161 }
162
163 /**
164 * Get the initial Transition.
165 *
166 * @return Returns the initial transition for this state machine.
167 *
168 * @since 2.0
169 */
170 public final SimpleTransition getInitialTransition() {
171 return initialTransition;
172 }
173
174 /**
175 * Set the initial Transition.
176 * <p>Note: the initial transition can/may not have executable content!</p>
177 *
178 * @param initialTransition The initial transition to set.
179 *
180 * @since 2.0
181 */
182 public final void setInitialTransition(final SimpleTransition initialTransition) {
183 this.initialTransition = initialTransition;
184 }
185
186 /**
187 * Get the data model placed at document root.
188 *
189 * @return Returns the data model.
190 */
191 public final Datamodel getDatamodel() {
192 return datamodel;
193 }
194
195 /**
196 * Set the data model at document root.
197 *
198 * @param datamodel The Datamodel to set.
199 */
200 public final void setDatamodel(final Datamodel datamodel) {
201 this.datamodel = datamodel;
202 }
203
204 /**
205 * Get the immediate child targets of the SCXML root.
206 *
207 * @return List Returns list of the child targets.
208 *
209 * @since 0.7
210 */
211 public final List<EnterableState> getChildren() {
212 return children;
213 }
214
215 /**
216 * Get the first immediate child of the SCXML root. Return null if there's no child.
217 *
218 * @return Returns the first immediate child of the SCXML root. Return null if there's no child.
219 *
220 * @since 2.0
221 */
222 public final EnterableState getFirstChild() {
223 if (!children.isEmpty()) {
224 return children.get(0);
225 }
226 return null;
227 }
228
229 /**
230 * Add an immediate child of the SCXML root.
231 *
232 * @param es The child to be added.
233 *
234 * @since 0.7
235 */
236 public final void addChild(final EnterableState es) {
237 children.add(es);
238 }
239
240 /**
241 * Get the targets map, which is a Map of all States and Parallels
242 * associated with this state machine, keyed by their id.
243 *
244 * @return Map Returns the targets.
245 */
246 public final Map<String, TransitionTarget> getTargets() {
247 return targets;
248 }
249
250 /**
251 * Add a target to this SCXML document.
252 *
253 * @param target The target to be added to the targets Map.
254 */
255 public final void addTarget(final TransitionTarget target) {
256 targets.put(target.getId(), target);
257 }
258
259 /**
260 * Get the SCXML document version.
261 *
262 * @return Returns the version.
263 */
264 public final String getVersion() {
265 return version;
266 }
267
268 /**
269 * Set the SCXML document version.
270 *
271 * @param version The version to set.
272 */
273 public final void setVersion(final String version) {
274 this.version = version;
275 }
276
277 /**
278 * Get the xmlns of this SCXML document.
279 *
280 * @return Returns the xmlns.
281 */
282 public final String getXmlns() {
283 return xmlns;
284 }
285
286 /**
287 * Set the xmlns of this SCXML document.
288 *
289 * @param xmlns The xmlns to set.
290 */
291 public final void setXmlns(final String xmlns) {
292 this.xmlns = xmlns;
293 }
294
295 /**
296 * Get the namespace definitions specified on the SCXML element.
297 * May be <code>null</code>.
298 *
299 * @return The namespace definitions specified on the SCXML element,
300 * may be <code>null</code>.
301 */
302 public final Map<String, String> getNamespaces() {
303 return namespaces;
304 }
305
306 /**
307 * Set the namespace definitions specified on the SCXML element.
308 *
309 * @param namespaces The namespace definitions specified on the
310 * SCXML element.
311 */
312 public final void setNamespaces(final Map<String, String> namespaces) {
313 this.namespaces = namespaces;
314 }
315
316 /**
317 * Get the the initial transition target.
318 *
319 * @return String Returns the initial transition target ID
320 * @see #getInitialTransition()
321 */
322 public final String getInitial() {
323 return initial;
324 }
325
326 /**
327 * Set the initial transition target.
328 *
329 * @param initial The initial transition target
330 * @see #setInitialTransition(SimpleTransition)
331 */
332 public final void setInitial(final String initial) {
333 this.initial = initial;
334 }
335
336 /**
337 * Get the name for this state machine.
338 *
339 * @return The name for this state machine.
340 */
341 public String getName() {
342 return name;
343 }
344
345 /**
346 * Set the name for this state machine.
347 *
348 * @param name The name for this state machine.
349 */
350 public void setName(String name) {
351 this.name = name;
352 }
353
354 /**
355 * Get the profile in use for this state machine.
356 *
357 * @return The profile in use.
358 */
359 public String getProfile() {
360 return profile;
361 }
362
363 /**
364 * Set the profile in use for this state machine.
365 *
366 * @param profile The profile to be used.
367 */
368 public void setProfile(String profile) {
369 this.profile = profile;
370 }
371
372 /**
373 * Get the exmode in use for this state machine.
374 *
375 * @return The exmode in use.
376 */
377 public String getExmode() {
378 return exmode;
379 }
380
381 /**
382 * Set the exmode to be used for this state machine.
383 *
384 * @param exmode The exmode to be used.
385 */
386 public void setExmode(String exmode) {
387 this.exmode = exmode;
388 }
389
390 /**
391 * Get the datamodel name as specified as attribute on this document
392 * @return The datamodel name of this document
393 */
394 public String getDatamodelName() {
395 return datamodelName;
396 }
397
398 /**
399 * Sets the datamodel name as specified as attribute on this document
400 * @param datamodelName The datamodel name
401 */
402 public void setDatamodelName(final String datamodelName) {
403 this.datamodelName = datamodelName;
404 }
405 }
406