View Javadoc

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