    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.ArrayList;
    021    import java.util.HashMap;
    022    import java.util.List;
    023    import java.util.Map;
    024
    025    /**
    026     * An abstract base class for elements in SCXML that can serve as a
    027     * <target> for a <transition>, such as State or Parallel.
    028     *
    029     */
    030    public abstract class TransitionTarget implements Serializable {
    031
    032        /**
    033         * Identifier for this transition target. Other parts of the SCXML
    034         * document may refer to this <state> using this ID.
    035         */
    036        private String id;
    037
    038        /**
    039         * Optional property holding executable content to be run upon
    040         * entering this transition target.
    041         */
    042        private OnEntry onEntry;
    043
    044        /**
    045         * Optional property holding executable content to be run upon
    046         * exiting this transition target.
    047         */
    048        private OnExit onExit;
    049
    050        /**
    051         * Optional property holding the data model for this transition target.
    052         */
    053        private Datamodel datamodel;
    054
    055        /**
    056         * The parent of this transition target (may be null, if the parent
    057         * is the SCXML document root).
    058         */
    059        private TransitionTarget parent;
    060
    061        /**
    062         * A list of outgoing Transitions from this target, by document order.
    063         */
    064        private List transitions;
    065
    066        /**
    067         * List of history states owned by a given state (applies to non-leaf
    068         * states).
    069         */
    070        private List history;
    071
    072        /**
    073         * Constructor.
    074         */
    075        public TransitionTarget() {
    076            super();
    077            onEntry = new OnEntry(); //empty defaults
    078            onEntry.setParent(this);
    079            onExit = new OnExit();   //empty defaults
    080            onExit.setParent(this);
    081            parent = null;
    082            transitions = new ArrayList();
    083            history = new ArrayList();
    084        }
    085
    086        /**
    087         * Get the identifier for this transition target (may be null).
    088         *
    089         * @return Returns the id.
    090         */
    091        public final String getId() {
    092            return id;
    093        }
    094
    095        /**
    096         * Set the identifier for this transition target.
    097         *
    098         * @param id The id to set.
    099         */
    100        public final void setId(final String id) {
    101            this.id = id;
    102        }
    103
    104        /**
    105         * Get the onentry property.
    106         *
    107         * @return Returns the onEntry.
    108         */
    109        public final OnEntry getOnEntry() {
    110            return onEntry;
    111        }
    112
    113        /**
    114         * Set the onentry property.
    115         *
    116         * @param onEntry The onEntry to set.
    117         */
    118        public final void setOnEntry(final OnEntry onEntry) {
    119            this.onEntry = onEntry;
    120            this.onEntry.setParent(this);
    121        }
    122
    123        /**
    124         * Get the onexit property.
    125         *
    126         * @return Returns the onExit.
    127         */
    128        public final OnExit getOnExit() {
    129            return onExit;
    130        }
    131
    132        /**
    133         * Set the onexit property.
    134         *
    135         * @param onExit The onExit to set.
    136         */
    137        public final void setOnExit(final OnExit onExit) {
    138            this.onExit = onExit;
    139            this.onExit.setParent(this);
    140        }
    141
    142        /**
    143         * Get the data model for this transition target.
    144         *
    145         * @return Returns the data model.
    146         */
    147        public final Datamodel getDatamodel() {
    148            return datamodel;
    149        }
    150
    151        /**
    152         * Set the data model for this transition target.
    153         *
    154         * @param datamodel The Datamodel to set.
    155         */
    156        public final void setDatamodel(final Datamodel datamodel) {
    157            this.datamodel = datamodel;
    158        }
    159
    160        /**
    161         * Get the parent TransitionTarget.
    162         *
    163         * @return Returns the parent state
    164         * (null if parent is <scxml> element)
    165         */
    166        public final TransitionTarget getParent() {
    167            return parent;
    168        }
    169
    170        /**
    171         * Set the parent TransitionTarget.
    172         *
    173         * @param parent The parent state to set
    174         */
    175        public final void setParent(final TransitionTarget parent) {
    176            this.parent = parent;
    177        }
    178
    179        /**
    180         * Get the parent State.
    181         *
    182         * @return The parent State
    183         * @deprecated Will be removed in v1.0
    184         */
    185        public final State getParentState() {
    186            TransitionTarget tt = this.getParent();
    187            if (tt == null) {
    188                return null;
    189            } else {
    190                if (tt instanceof State) {
    191                    return (State) tt;
    192                } else { //tt is Parallel
    193                    return tt.getParentState();
    194                }
    195            }
    196        }
    197
    198        /**
    199         * Get the map of all outgoing transitions from this state.
    200         *
    201         * @return Map Returns the transitions Map.
    202         * @deprecated Use {@link #getTransitionsList()} instead
    203         */
    204        public final Map getTransitions() {
    205            Map transitionsMap = new HashMap();
    206            for (int i = 0; i < transitions.size(); i++) {
    207                Transition transition = (Transition) transitions.get(i);
    208                String event = transition.getEvent();
    209                if (!transitionsMap.containsKey(event)) {
    210                    List eventTransitions = new ArrayList();
    211                    eventTransitions.add(transition);
    212                    transitionsMap.put(event, eventTransitions);
    213                } else {
    214                    ((List) transitionsMap.get(event)).add(transition);
    215                }
    216            }
    217            return transitionsMap;
    218        }
    219
    220        /**
    221         * Get the list of all outgoing transitions from this target, that
    222         * will be candidates for being fired on the given event.
    223         *
    224         * @param event The event
    225         * @return List Returns the candidate transitions for given event
    226         */
    227        public final List getTransitionsList(final String event) {
    228            List matchingTransitions = null; // TODO v1.0 we returned null <= v0.6
    229            for (int i = 0; i < transitions.size(); i++) {
    230                Transition t = (Transition) transitions.get(i);
    231                if ((event == null && t.getEvent() == null)
    232                        || (event != null && event.equals(t.getEvent()))) {
    233                    if (matchingTransitions == null) {
    234                        matchingTransitions = new ArrayList();
    235                    }
    236                    matchingTransitions.add(t);
    237                }
    238            }
    239            return matchingTransitions;
    240        }
    241
    242        /**
    243         * Add a transition to the map of all outgoing transitions for
    244         * this transition target.
    245         *
    246         * @param transition
    247         *            The transitions to set.
    248         */
    249        public final void addTransition(final Transition transition) {
    250            transitions.add(transition);
    251            transition.setParent(this);
    252        }
    253
    254        /**
    255         * Get the outgoing transitions for this target as a java.util.List.
    256         *
    257         * @return List Returns the transitions list.
    258         */
    259        public final List getTransitionsList() {
    260            return transitions;
    261        }
    262
    263        /**
    264         * This method is used by XML digester.
    265         *
    266         * @param h
    267         *            History pseudo state
    268         *
    269         * @since 0.7
    270         */
    271        public final void addHistory(final History h) {
    272            history.add(h);
    273            h.setParent(this);
    274        }
    275
    276        /**
    277         * Does this state have a history pseudo state.
    278         *
    279         * @return boolean true if a given state contains at least one
    280         *                 history pseudo state
    281         *
    282         * @since 0.7
    283         */
    284        public final boolean hasHistory() {
    285            return (!history.isEmpty());
    286        }
    287
    288        /**
    289         * Get the list of history pseudo states for this state.
    290         *
    291         * @return a list of all history pseudo states contained by a given state
    292         *         (can be empty)
    293         * @see #hasHistory()
    294         *
    295         * @since 0.7
    296         */
    297        public final List getHistory() {
    298            return history;
    299        }
    300
    301    }
    302