    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 "stay" transitions.
    144         *  Returns parent (the source node) for "self" 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 "stay" transitions.
    161         * Contains parent (the source node) for "self" 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 "stay" and "self"
    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 "stay" and "self"
    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