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.ArrayList;
020    import java.util.List;
021    import java.util.Map;
022    
023    /**
024     * The class in this SCXML object model that corresponds to the
025     * <transition> SCXML element. Transition rules are triggered
026     * by "events" and conditionalized via
027     * "guard-conditions".
028     *
029     */
030    public class Transition extends Executable
031            implements NamespacePrefixesHolder {
032    
033        /**
034         * Serial version UID.
035         */
036        private static final long serialVersionUID = 2L;
037    
038        /**
039         * Property that specifies the trigger for this transition.
040         */
041        private String event;
042    
043        /**
044         * Optional guard condition.
045         */
046        private String cond;
047    
048        /**
049         * Optional property that specifies the new state(s) or parallel
050         * element to transition to. May be specified by reference or in-line.
051         * If multiple state(s) are specified, they must belong to the regions
052         * of the same parallel.
053         */
054        private List targets;
055    
056        /**
057         * The transition target ID (used by XML Digester only).
058         */
059        private String next;
060    
061        /**
062         * The path(s) for this transition, one per target, in the same order
063         * as <code>targets</code>.
064         * @see Path
065         */
066        private List paths;
067    
068        /**
069         * The current XML namespaces in the SCXML document for this action node,
070         * preserved for deferred XPath evaluation.
071         */
072        private Map namespaces;
073    
074        /**
075         * Constructor.
076         */
077        public Transition() {
078            super();
079            this.targets = new ArrayList();
080            this.paths = new ArrayList();
081        }
082    
083        /**
084         * Get the guard condition (may be null).
085         *
086         * @return Returns the cond.
087         */
088        public final String getCond() {
089            return cond;
090        }
091    
092        /**
093         * Set the guard condition.
094         *
095         * @param cond The cond to set.
096         */
097        public final void setCond(final String cond) {
098            this.cond = cond;
099        }
100    
101        /**
102         * Get the event that will trigger this transition (pending
103         * evaluation of the guard condition in favor).
104         *
105         * @return Returns the event.
106         */
107        public final String getEvent() {
108            return event;
109        }
110    
111        /**
112         * Set the event that will trigger this transition (pending
113         * evaluation of the guard condition in favor).
114         *
115         * @param event The event to set.
116         */
117        public final void setEvent(final String event) {
118            this.event = event;
119        }
120    
121        /**
122         * Get the XML namespaces at this action node in the SCXML document.
123         *
124         * @return Returns the map of namespaces.
125         */
126        public final Map getNamespaces() {
127            return namespaces;
128        }
129    
130        /**
131         * Set the XML namespaces at this action node in the SCXML document.
132         *
133         * @param namespaces The document namespaces.
134         */
135        public final void setNamespaces(final Map namespaces) {
136            this.namespaces = namespaces;
137        }
138    
139        /**
140         * Get the transition target (may be null).
141         *
142         * @return Returns the target as specified in SCXML markup.
143         * <p>Remarks: Is <code>null</code> for &quot;stay&quot; transitions.
144         *  Returns parent (the source node) for &quot;self&quot; transitions.</p>
145         *
146         * @deprecated A transition may have multiple targets,
147         *             use getTargets() instead.
148         */
149        public final TransitionTarget getTarget() {
150            if (targets.size() > 0) {
151                return (TransitionTarget) targets.get(0);
152            }
153            return null;
154        }
155    
156        /**
157         * Get the list of transition targets (may be an empty list).
158         *
159         * @return Returns the target(s) as specified in SCXML markup.
160         * <p>Remarks: Is <code>empty</code> for &quot;stay&quot; transitions.
161         * Contains parent (the source node) for &quot;self&quot; transitions.</p>
162         *
163         * @since 0.7
164         */
165        public final List getTargets() {
166            return targets;
167        }
168    
169        /**
170         * Get the runtime transition target, which always resolves to
171         * a TransitionTarget instance.
172         *
173         * @return Returns the actual target of a transition at runtime.
174         * <p>Remarks: For both the &quot;stay&quot; and &quot;self&quot;
175         * transitions it returns parent (the source node). This method should
176         * never return <code>null</code>.</p>
177         *
178         * @deprecated A transition may have multiple targets,
179         *             use getRuntimeTargets() instead.
180         */
181        public final TransitionTarget getRuntimeTarget() {
182            return (TransitionTarget) getRuntimeTargets().get(0);
183        }
184    
185        /**
186         * Get the list of runtime transition target, which always contains
187         * atleast one TransitionTarget instance.
188         *
189         * @return Returns the actual targets of a transition at runtime.
190         * <p>Remarks: For both the &quot;stay&quot; and &quot;self&quot;
191         * transitions it returns parent (the source node). This method should
192         * never return an empty list or <code>null</code>.</p>
193         *
194         * @since 0.7
195         */
196        public final List getRuntimeTargets() {
197            if (targets.size() == 0) {
198                List runtimeTargets = new ArrayList();
199                runtimeTargets.add(getParent());
200                return runtimeTargets;
201            }
202            return targets;
203        }
204    
205        /**
206         * Set the transition target.
207         *
208         * @param target The target to set.
209         * @deprecated Use setTargets(List) instead.
210         */
211        public final void setTarget(final TransitionTarget target) {
212            this.targets.add(0, target);
213        }
214    
215        /**
216         * Get the ID of the transition target (may be null, if, for example,
217         * the target is specified inline).
218         *
219         * @return String Returns the transition target ID
220         *                (used by SCXML Digester only).
221         * @see #getTargets()
222         */
223        public final String getNext() {
224            return next;
225        }
226    
227        /**
228         * Set the transition target by specifying its ID.
229         *
230         * @param next The the transition target ID (used by SCXML Digester only).
231         */
232        public final void setNext(final String next) {
233            this.next = next;
234        }
235    
236        /**
237         * Get the path of this transiton.
238         *
239         * @see Path
240         * @return Path returns the transition path
241         * @deprecated Use getPaths() instead.
242         */
243        public final Path getPath() {
244            return (Path) getPaths().get(0);
245        }
246    
247        /**
248         * Get the path(s) of this transiton.
249         *
250         * @see Path
251         * @return List returns the list of transition path(s)
252         *
253         * @since 0.7
254         */
255        public final List getPaths() {
256            if (paths.size() == 0) {
257                if (targets.size() > 0) {
258                    for (int i = 0; i < targets.size(); i++) {
259                        paths.add(i, new Path(getParent(),
260                            (TransitionTarget) targets.get(i)));
261                    }
262                } else {
263                    paths.add(new Path(getParent(), null));
264                }
265            }
266            return paths;
267        }
268    }
269