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.io.Serializable;
020    import java.util.HashMap;
021    import java.util.LinkedHashMap;
022    import java.util.Map;
023    
024    import org.apache.commons.scxml.SCXMLHelper;
025    
026    /**
027     * The class in this SCXML object model that corresponds to the
028     * <scxml> root element, and serves as the "document
029     * root".
030     *
031     */
032    public class SCXML implements Serializable, NamespacePrefixesHolder {
033    
034        /**
035         * Serial version UID.
036         */
037        private static final long serialVersionUID = 2L;
038    
039        /**
040         * The SCXML XMLNS.
041         */
042        public static final String XMLNS = "http://www.w3.org/2005/07/scxml";
043    
044        /**
045         * The xmlns attribute on the root <smxml> element.
046         * This must match XMLNS above.
047         */
048        private String xmlns;
049    
050        /**
051         * The SCXML version of this document.
052         */
053        private String version;
054    
055        /**
056         * The initial TransitionTarget for the SCXML executor.
057         */
058        private TransitionTarget initialTarget;
059    
060        /**
061         * The initial transition target ID (used by XML Digester only).
062         */
063        private String initial;
064    
065        /**
066         * Optional property holding the data model for this SCXML document.
067         * This gets merged with the root context and potentially hides any
068         * (namesake) variables in the root context.
069         */
070        private Datamodel datamodel;
071    
072        /**
073         * The immediate child targets of this SCXML document root.
074         */
075        private Map children;
076    
077        /**
078         * A global map of all States and Parallels associated with this
079         * state machine, keyed by their id.
080         */
081        private Map targets;
082    
083        /**
084         * The XML namespaces defined on the SCXML document root node,
085         * preserved primarily for serialization.
086         */
087        private Map namespaces;
088    
089        /**
090         * Indicates whether the legacy parser
091         * ({@link org.apache.commons.scxml.io.SCXMLDigester}) was used.
092         */
093        private boolean legacy = false;
094    
095        /**
096         * Constructor.
097         */
098        public SCXML() {
099            this.children = new LinkedHashMap();
100            this.targets = new HashMap();
101        }
102    
103        /**
104         * Get the initial State.
105         *
106         * @return State Returns the initialstate.
107         *
108         * @deprecated Use getInitialTarget() instead. Returns <code>null</code>
109         *             if the initial target is a Parallel.
110         */
111        public final State getInitialState() {
112            if (initialTarget != null && initialTarget instanceof State) {
113                return (State) initialTarget;
114            }
115            return null;
116        }
117    
118        /**
119         * Set the initial State.
120         *
121         * @param initialState The initialstate to set.
122         *
123         * @deprecated Use setInitialTarget(TransitionTarget) instead.
124         */
125        public final void setInitialState(final State initialState) {
126            this.initialTarget = initialState;
127        }
128    
129        /**
130         * Get the initial TransitionTarget.
131         *
132         * @return Returns the initial target for this state machine.
133         *
134         * @since 0.7
135         */
136        public final TransitionTarget getInitialTarget() {
137            return initialTarget;
138        }
139    
140        /**
141         * Set the initial TransitionTarget.
142         *
143         * @param initialTarget The initial target to set.
144         *
145         * @since 0.7
146         */
147        public final void setInitialTarget(final TransitionTarget initialTarget) {
148            this.initialTarget = initialTarget;
149        }
150    
151        /**
152         * Get the data model placed at document root.
153         *
154         * @return Returns the data model.
155         */
156        public final Datamodel getDatamodel() {
157            return datamodel;
158        }
159    
160        /**
161         * Set the data model at document root.
162         *
163         * @param datamodel The Datamodel to set.
164         */
165        public final void setDatamodel(final Datamodel datamodel) {
166            this.datamodel = datamodel;
167        }
168    
169        /**
170         * Get the children states.
171         *
172         * @return Map Returns map of the child states.
173         *
174         * @deprecated Use getChildren() instead.
175         */
176        public final Map getStates() {
177            return children;
178        }
179    
180        /**
181         * Add a child state.
182         *
183         * @param state The state to be added to the states Map.
184         *
185         * @deprecated Use addChild(TransitionTarget) instead.
186         */
187        public final void addState(final State state) {
188            children.put(state.getId(), state);
189        }
190    
191        /**
192         * Get the immediate child targets of the SCXML root.
193         *
194         * @return Map Returns map of the child targets.
195         *
196         * @since 0.7
197         */
198        public final Map getChildren() {
199            return children;
200        }
201    
202        /**
203         * Add an immediate child target of the SCXML root.
204         *
205         * @param tt The transition target to be added to the states Map.
206         *
207         * @since 0.7
208         */
209        public final void addChild(final TransitionTarget tt) {
210            children.put(tt.getId(), tt);
211        }
212    
213        /**
214         * Get the targets map, which is a Map of all States and Parallels
215         * associated with this state machine, keyed by their id.
216         *
217         * @return Map Returns the targets.
218         */
219        public final Map getTargets() {
220            return targets;
221        }
222    
223        /**
224         * Add a target to this SCXML document.
225         *
226         * @param target The target to be added to the targets Map.
227         */
228        public final void addTarget(final TransitionTarget target) {
229            String id = target.getId();
230            if (!SCXMLHelper.isStringEmpty(id)) {
231                // Target is not anonymous, so makes sense to map it
232                targets.put(id, target);
233            }
234        }
235    
236        /**
237         * Get the SCXML document version.
238         *
239         * @return Returns the version.
240         */
241        public final String getVersion() {
242            return version;
243        }
244    
245        /**
246         * Set the SCXML document version.
247         *
248         * @param version The version to set.
249         */
250        public final void setVersion(final String version) {
251            this.version = version;
252        }
253    
254        /**
255         * Get the xmlns of this SCXML document.
256         *
257         * @return Returns the xmlns.
258         */
259        public final String getXmlns() {
260            return xmlns;
261        }
262    
263        /**
264         * Set the xmlns of this SCXML document.
265         *
266         * @param xmlns The xmlns to set.
267         */
268        public final void setXmlns(final String xmlns) {
269            this.xmlns = xmlns;
270        }
271    
272        /**
273         * Get the namespace definitions specified on the SCXML element.
274         * May be <code>null</code>.
275         *
276         * @return The namespace definitions specified on the SCXML element,
277         *         may be <code>null</code>.
278         */
279        public final Map getNamespaces() {
280            return namespaces;
281        }
282    
283        /**
284         * Set the namespace definitions specified on the SCXML element.
285         *
286         * @param namespaces The namespace definitions specified on the
287         *                   SCXML element.
288         */
289        public final void setNamespaces(final Map namespaces) {
290            this.namespaces = namespaces;
291        }
292    
293        /**
294         * Get the ID of the initial state.
295         *
296         * @return String Returns the initial state ID (used by XML Digester only).
297         * @see #getInitialTarget()
298         * @deprecated Use {@link #getInitial()} instead.
299         */
300        public final String getInitialstate() {
301            return initial;
302        }
303    
304        /**
305         * Set the ID of the initial state.
306         *
307         * @param initialstate The initial state ID (used by XML Digester only).
308         * @see #setInitialTarget(TransitionTarget)
309         * @deprecated Use {@link #setInitial(String)} instead.
310         */
311        public final void setInitialstate(final String initialstate) {
312            this.initial = initialstate;
313        }
314    
315        /**
316         * Get the ID of the initial transition target.
317         *
318         * @return String Returns the initial transition target ID
319         *     (used by XML Digester only).
320         * @see #getInitialTarget()
321         */
322        public final String getInitial() {
323            return initial;
324        }
325    
326        /**
327         * Set the ID of the initial transition target.
328         *
329         * @param initial The initial transition target ID
330         *     (used by XML Digester only).
331         * @see #setInitialTarget(TransitionTarget)
332         */
333        public final void setInitial(final String initial) {
334            this.initial = initial;
335        }
336    
337        /**
338         * Whether the legacy parser was used.
339         *
340         * @return True, if legacy parser was used.
341         *
342         * @since 0.9
343         * @deprecated Will be removed in v1.0
344         */
345        public final boolean isLegacy() {
346            return legacy;
347        }
348    
349        /**
350         * Set whether the legacy parser was used.
351         *
352         * @param legacy True, if legacy parser was used.
353         *
354         * @since 0.9
355         * @deprecated Will be removed in v1.0
356         */
357        public final void setLegacy(final boolean legacy) {
358            this.legacy = legacy;
359        }
360    
361    }
362