View Javadoc

    1   /*
    2    *
    3    *   Copyright 2005 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.Iterator;
    22  import java.util.LinkedList;
    23  import java.util.List;
    24
    25  import org.apache.commons.scxml.SCXMLHelper;
    26
    27  /***
    28   * A helper class for this SCXML implementation that represents the
    29   * path taken to transition from one TransitionTarget to another in
    30   * the SCXML document.
    31   *
    32   * The Path consists of the &quot;up segment&quot; that traces up to
    33   * the least common ancestor and a &quot;down segment&quot; that traces
    34   * down to the target of the Transition.
    35   *
    36   */
    37  public class Path {
    38
    39      /***
    40       * The list of TransitionTargets in the &quot;up segment&quot;.
    41       */
    42      private List upSeg = new ArrayList();
    43
    44      /***
    45       * The list of TransitionTargets in the &quot;down segment&quot;.
    46       */
    47      private List downSeg = new ArrayList();
    48
    49      /***
    50       * &quot;Lowest&quot; state which is not being exited nor entered by
    51       * the transition.
    52       */
    53      private State scope = null;
    54
    55      /***
    56       * Whether the path crosses region border(s).
    57       */
    58      private boolean crossRegion = false;
    59
    60      /***
    61       * Constructor.
    62       *
    63       * @param source The source TransitionTarget
    64       * @param target The target TransitionTarget
    65       */
    66      Path(final TransitionTarget source, final TransitionTarget target) {
    67          if (target == null) {
    68              //a local "stay" transition
    69              scope = (State) source;
    70              //all segments remain empty
    71          } else {
    72              TransitionTarget tt = SCXMLHelper.getLCA(source, target);
    73              if (tt != null) {
    74                  if (tt instanceof State) {
    75                      scope = (State) tt;
    76                  } else {
    77                      scope = tt.getParentState();
    78                  }
    79                  if (scope == source || scope == target) {
    80                      scope = scope.getParentState();
    81                  }
    82              }
    83              tt = source;
    84              while (tt != scope) {
    85                  upSeg.add(tt);
    86                  if (tt instanceof State) {
    87                      State st = (State) tt;
    88                      if (st.isRegion()) {
    89                          crossRegion = true;
    90                      }
    91                  }
    92                  tt = tt.getParent();
    93              }
    94              tt = target;
    95              while (tt != scope) {
    96                  downSeg.add(0, tt);
    97                  if (tt instanceof State) {
    98                      State st = (State) tt;
    99                      if (st.isRegion()) {
    100                         crossRegion = true;
    101                     }
    102                 }
    103                 tt = tt.getParent();
    104             }
    105         }
    106     }
    107
    108     /***
    109      * Does this &quot;path&quot; cross regions.
    110      *
    111      * @return true when the path crosses a region border(s)
    112      * @see State#isRegion()
    113      */
    114     public final boolean isCrossRegion() {
    115         return crossRegion;
    116     }
    117
    118     /***
    119      * Get the list of regions exited.
    120      *
    121      * @return List a list of exited regions sorted bottom-up;
    122      *         no order defined for siblings
    123      * @see State#isRegion()
    124      */
    125     public final List getRegionsExited() {
    126         LinkedList ll = new LinkedList();
    127         for (Iterator i = upSeg.iterator(); i.hasNext();) {
    128             Object o = i.next();
    129             if (o instanceof State) {
    130                 State st = (State) o;
    131                 if (st.isRegion()) {
    132                     ll.add(st);
    133                 }
    134             }
    135         }
    136         return ll;
    137     }
    138
    139     /***
    140      * Get the list of regions entered.
    141      *
    142      * @return List a list of entered regions sorted top-down; no order
    143      *         defined for siblings
    144      * @see State#isRegion()
    145      */
    146     public final List getRegionsEntered() {
    147         LinkedList ll = new LinkedList();
    148         for (Iterator i = downSeg.iterator(); i.hasNext();) {
    149             Object o = i.next();
    150             if (o instanceof State) {
    151                 State st = (State) o;
    152                 if (st.isRegion()) {
    153                     ll.add(st);
    154                 }
    155             }
    156         }
    157         return ll;
    158     }
    159
    160     /***
    161      * Get the farthest state from root which is not being exited
    162      * nor entered by the transition (null if scope is document root).
    163      *
    164      * @return State scope of the transition path, null means global transition
    165      *         (SCXML document level) Scope is the least state which is not
    166      *         being exited nor entered by the transition.
    167      */
    168     public final State getScope() {
    169         return scope;
    170     }
    171
    172     /***
    173      * Get the upward segment.
    174      *
    175      * @return List upward segment of the path up to the scope
    176      */
    177     public final List getUpwardSegment() {
    178         return upSeg;
    179     }
    180
    181     /***
    182      * Get the downward segment.
    183      *
    184      * @return List downward segment from the scope to the target
    185      */
    186     public final List getDownwardSegment() {
    187         return downSeg;
    188     }
    189 }
    190