View Javadoc

    1   /*
    2    *
    3    *   Copyright 2005-2006 The Apache Software Foundation.
    4    *
    5    *  Licensed under the Apache License, Version 2.0 (the "License");
    6    *  you may not use this file except in compliance with the License.
    7    *  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   */
    18  package org.apache.commons.scxml.model;
    19
    20  import java.util.ArrayList;
    21  import java.util.HashMap;
    22  import java.util.Iterator;
    23  import java.util.List;
    24  import java.util.Map;
    25
    26  /***
    27   * The class in this SCXML object model that corresponds to the
    28   * &lt;state&gt; SCXML element.
    29   *
    30   */
    31  public class State extends TransitionTarget {
    32
    33      /***
    34       * The Map containing immediate children of this State, keyed by
    35       * their IDs. Incompatible with the parallel or invoke property.
    36       */
    37      private Map children;
    38
    39      /***
    40       * The Parallel child, which defines a set of parallel substates.
    41       * May occur 0 or 1 times. Incompatible with the state or invoke property.
    42       */
    43      private Parallel parallel;
    44
    45      /***
    46       * The Invoke child, which defines an external process that should
    47       * be invoked, immediately after the onentry executable content,
    48       * and the transitions become candidates after the invoked
    49       * process has completed its execution.
    50       * May occur 0 or 1 times. Incompatible with the state or parallel
    51       * property.
    52       */
    53      private Invoke invoke;
    54
    55      /***
    56       * Boolean property indicating whether this is a final state or not.
    57       * Default value is false . Final states may not have substates or
    58       * outgoing transitions.
    59       */
    60      private boolean isFinal;
    61
    62      /***
    63       * A child which identifies initial state for state machines that
    64       * have substates.
    65       */
    66      private Initial initial;
    67
    68      /***
    69       * A map of outgoing Transitions from this state.
    70       */
    71      private Map transitions;
    72
    73      /***
    74       * List of history states owned by a given state (applies to non-leaf
    75       * states).
    76       */
    77      private List history;
    78
    79      /***
    80       * Applies to composite states only. If one of its final children is
    81       * active, its parent is marked done. This property is reset upon
    82       * re-entry.
    83       */
    84      private boolean done = false;
    85
    86      /***
    87       * Constructor.
    88       */
    89      public State() {
    90          this.children = new HashMap();
    91          this.transitions = new HashMap();
    92          this.history = new ArrayList();
    93      }
    94
    95      /***
    96       * Is this state a &quot;final&quot; state.
    97       *
    98       * @return boolean Returns the isFinal.
    99       */
    100     public final boolean getIsFinal() {
    101         return isFinal;
    102     }
    103
    104     /***
    105      * Set whether this is a &quot;final&quot; state.
    106      *
    107      * @param isFinal
    108      *            The isFinal to set.
    109      */
    110     public final void setIsFinal(final boolean isFinal) {
    111         this.isFinal = isFinal;
    112     }
    113
    114     /***
    115      * Get the Parallel child (may be null).
    116      *
    117      * @return Parallel Returns the parallel.
    118      */
    119     public final Parallel getParallel() {
    120         return parallel;
    121     }
    122
    123     /***
    124      * Set the Parallel child.
    125      *
    126      * @param parallel
    127      *            The parallel to set.
    128      */
    129     public final void setParallel(final Parallel parallel) {
    130         this.parallel = parallel;
    131     }
    132
    133     /***
    134      * Get the Invoke child (may be null).
    135      *
    136      * @return Invoke Returns the invoke.
    137      */
    138     public final Invoke getInvoke() {
    139         return invoke;
    140     }
    141
    142     /***
    143      * Set the Invoke child.
    144      *
    145      * @param invoke
    146      *            The invoke to set.
    147      */
    148     public final void setInvoke(final Invoke invoke) {
    149         this.invoke = invoke;
    150     }
    151
    152     /***
    153      * Get the initial state.
    154      *
    155      * @return Initial Returns the initial state.
    156      */
    157     public final Initial getInitial() {
    158         return initial;
    159     }
    160
    161     /***
    162      * Set the initial state.
    163      *
    164      * @param target
    165      *            The target to set.
    166      */
    167     public final void setInitial(final Initial target) {
    168         this.initial = target;
    169     }
    170
    171     /***
    172      * Get the map of all outgoing transitions from this state.
    173      *
    174      * @return Map Returns the transitions Map.
    175      */
    176     public final Map getTransitions() {
    177         return transitions;
    178     }
    179
    180     /***
    181      * Get the list of all outgoing transitions from this state, that
    182      * will be candidates for being fired on the given event.
    183      *
    184      * @param event The event
    185      * @return List Returns the candidate transitions for given event
    186      */
    187     public final List getTransitionsList(final String event) {
    188         Object candidateTransitions = transitions.get(event);
    189         if (candidateTransitions == null) {
    190             return null;
    191         }
    192         return (List) candidateTransitions;
    193     }
    194
    195     /***
    196      * Add a transition to the map of all outgoing transitions for
    197      * this state.
    198      *
    199      * @param transition
    200      *            The transitions to set.
    201      */
    202     public final void addTransition(final Transition transition) {
    203         String event = transition.getEvent();
    204         if (!transitions.containsKey(event)) {
    205             List eventTransitions = new ArrayList();
    206             eventTransitions.add(transition);
    207             transitions.put(event, eventTransitions);
    208         } else {
    209             ((List) transitions.get(event)).add(transition);
    210         }
    211     }
    212
    213     /***
    214      * Get the map of child states (may be empty).
    215      *
    216      * @return Map Returns the children.
    217      */
    218     public final Map getChildren() {
    219         return children;
    220     }
    221
    222     /***
    223      * Add a child state.
    224      *
    225      * @param state
    226      *            a child state
    227      */
    228     public final void addChild(final State state) {
    229         this.children.put(state.getId(), state);
    230         state.setParent(this);
    231     }
    232
    233     /***
    234      * Get the outgoing transitions for this state as a java.util.List.
    235      *
    236      * @return List Returns the transitions (as a list). TODO - Check in next
    237      *         iteration whether both methods need to be retained.
    238      */
    239     public final List getTransitionsList() {
    240         // Each call creates a new List, this will change once TO-DO is handled
    241         List transitionsList = new ArrayList();
    242         for (Iterator iter = transitions.keySet().iterator();
    243                 iter.hasNext();) {
    244             transitionsList.addAll((List) transitions.get(iter.next()));
    245         }
    246         return transitionsList;
    247     }
    248
    249     /***
    250      * This method is used by XML digester.
    251      *
    252      * @param h
    253      *            History pseudo state
    254      */
    255     public final void addHistory(final History h) {
    256         history.add(h);
    257     }
    258
    259     /***
    260      * Does this state have a history pseudo state.
    261      *
    262      * @return boolean true if a given state contains at least one
    263      *                 history pseudo state
    264      */
    265     public final boolean hasHistory() {
    266         return (!history.isEmpty());
    267     }
    268
    269     /***
    270      * Get the list of history pseudo states for this state.
    271      *
    272      * @return a list of all history pseudo states contained by a given state
    273      *         (can be empty)
    274      * @see #hasHistory()
    275      */
    276     public final List getHistory() {
    277         return history;
    278     }
    279
    280     /***
    281      * Check whether this is a simple (leaf) state (UML terminology).
    282      *
    283      * @return true if this is a simple state, otherwise false
    284      */
    285     public final boolean isSimple() {
    286         if (parallel == null && children.isEmpty()) {
    287             return true;
    288         }
    289         return false;
    290     }
    291
    292     /***
    293      * Check whether this is a composite state (UML terminology).
    294      *
    295      * @return true if this is a composite state, otherwise false
    296      */
    297     public final boolean isComposite() {
    298         if (parallel == null && children.isEmpty()) {
    299             return false;
    300         }
    301         return true;
    302     }
    303
    304     /***
    305      * Checks whether it is a region state (directly nested to parallel - UML
    306      * terminology).
    307      *
    308      * @return true if this is a region state, otherwise false
    309      * @see Parallel
    310      */
    311     public final boolean isRegion() {
    312         if (getParent() instanceof Parallel) {
    313             return true;
    314         }
    315         return false;
    316     }
    317
    318     /***
    319      * Checks whether it is a orthogonal state, that is, it owns a parallel
    320      * (UML terminology).
    321      *
    322      * @return true if this is a orthogonal state, otherwise false
    323      */
    324     public final boolean isOrthogonal() {
    325         if (parallel != null) {
    326             return true;
    327         }
    328         return false;
    329     }
    330
    331     /***
    332      * In case this is a parallel state, check if one its final states
    333      * is active.
    334      *
    335      * @return Returns the done.
    336      */
    337     public final boolean isDone() {
    338         return done;
    339     }
    340
    341     /***
    342      * Update the done property, which is set if this is a parallel state,
    343      * and one its final states is active.
    344      *
    345      * @param done The done to set.
    346      */
    347     public final void setDone(final boolean done) {
    348         this.done = done;
    349     }
    350 }
    351