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 */ 017package org.apache.commons.scxml2.model; 018 019import java.util.ArrayList; 020import java.util.List; 021 022/** 023 * An abstract base class for state elements in SCXML that can be transitioned out from, such as State or Parallel. 024 */ 025public abstract class TransitionalState extends EnterableState { 026 027 /** 028 * A list of outgoing Transitions from this state, by document order. 029 */ 030 private List<Transition> transitions; 031 032 /** 033 * Optional property holding the data model for this state. 034 */ 035 private Datamodel datamodel; 036 037 /** 038 * List of history states owned by a given state (applies to non-leaf 039 * states). 040 */ 041 private List<History> history; 042 043 /** 044 * The Invoke children, each which defines an external process that should 045 * be invoked, immediately after the onentry executable content, 046 * and the transitions become candidates after the invoked 047 * process has completed its execution. 048 * May occur 0 or more times. 049 */ 050 private List<Invoke> invokes; 051 052 /** 053 * The set of EnterableState children contained in this TransitionalState 054 */ 055 private List<EnterableState> children; 056 057 public TransitionalState() { 058 super(); 059 transitions = new ArrayList<Transition>(); 060 history = new ArrayList<History>(); 061 children = new ArrayList<EnterableState>(); 062 invokes = new ArrayList<Invoke>(); 063 } 064 065 /** 066 * Update TransitionTarget descendants their ancestors 067 */ 068 protected void updateDescendantsAncestors() { 069 super.updateDescendantsAncestors(); 070 for (History h : history) { 071 // reset ancestors 072 h.updateDescendantsAncestors(); 073 } 074 for (TransitionTarget child : children) { 075 child.updateDescendantsAncestors(); 076 } 077 } 078 079 /** 080 * Get the TransitionalState (State or Parallel) parent. 081 * 082 * @return Returns the parent. 083 */ 084 @Override 085 public TransitionalState getParent() { 086 return (TransitionalState)super.getParent(); 087 } 088 089 /** 090 * Set the TransitionalState parent 091 * 092 * @param parent The parent to set. 093 */ 094 public final void setParent(final TransitionalState parent) { 095 super.setParent(parent); 096 } 097 098 /** 099 * Get the ancestor of this TransitionalState at specified level 100 * @param level the level of the ancestor to return, zero being top 101 * @return the ancestor at specified level 102 */ 103 @Override 104 public TransitionalState getAncestor(int level) { 105 return (TransitionalState)super.getAncestor(level); 106 } 107 108 /** 109 * Get the list of all outgoing transitions from this state, that 110 * will be candidates for being fired on the given event. 111 * 112 * @param event The event 113 * @return List Returns the candidate transitions for given event 114 */ 115 public final List<Transition> getTransitionsList(final String event) { 116 List<Transition> matchingTransitions = null; // since we returned null upto v0.6 117 for (Transition t : transitions) { 118 if ((event == null && t.getEvent() == null) 119 || (event != null && event.equals(t.getEvent()))) { 120 if (matchingTransitions == null) { 121 matchingTransitions = new ArrayList<Transition>(); 122 } 123 matchingTransitions.add(t); 124 } 125 } 126 return matchingTransitions; 127 } 128 129 /** 130 * Add a transition to the map of all outgoing transitions for 131 * this state. 132 * 133 * @param transition 134 * The transitions to set. 135 */ 136 public final void addTransition(final Transition transition) { 137 transitions.add(transition); 138 transition.setParent(this); 139 } 140 141 /** 142 * Get the outgoing transitions for this state as a java.util.List. 143 * 144 * @return List Returns the transitions list. 145 */ 146 public final List<Transition> getTransitionsList() { 147 return transitions; 148 } 149 150 /** 151 * Get the data model for this transition target. 152 * 153 * @return Returns the data model. 154 */ 155 public final Datamodel getDatamodel() { 156 return datamodel; 157 } 158 159 /** 160 * Set the data model for this transition target. 161 * 162 * @param datamodel The Datamodel to set. 163 */ 164 public final void setDatamodel(final Datamodel datamodel) { 165 this.datamodel = datamodel; 166 } 167 168 /** 169 * @param h History pseudo state 170 * 171 * @since 0.7 172 */ 173 public final void addHistory(final History h) { 174 history.add(h); 175 h.setParent(this); 176 } 177 178 /** 179 * Does this state have a history pseudo state. 180 * 181 * @return boolean true if a given state contains at least one 182 * history pseudo state 183 * 184 * @since 0.7 185 */ 186 public final boolean hasHistory() { 187 return (!history.isEmpty()); 188 } 189 190 /** 191 * Get the list of history pseudo states for this state. 192 * 193 * @return a list of all history pseudo states contained by a given state 194 * (can be empty) 195 * @see #hasHistory() 196 * 197 * @since 0.7 198 */ 199 public final List<History> getHistory() { 200 return history; 201 } 202 203 /** 204 * Get the Invoke children (may be empty). 205 * 206 * @return Invoke Returns the invoke. 207 */ 208 public final List<Invoke> getInvokes() { 209 return invokes; 210 } 211 212 /** 213 * Set the Invoke child. 214 * 215 * @param invoke 216 * The invoke to set. 217 */ 218 public final void addInvoke(final Invoke invoke) { 219 this.invokes.add(invoke); 220 invoke.setParentEnterableState(this); 221 } 222 223 /** 224 * Get the set of child transition targets (may be empty). 225 * 226 * @return Returns the children. 227 * 228 * @since 0.7 229 */ 230 public final List<EnterableState> getChildren() { 231 return children; 232 } 233 234 /** 235 * Add a child. 236 * 237 * @param es A child enterable state. 238 * 239 * @since 0.7 240 */ 241 protected void addChild(final EnterableState es) { 242 children.add(es); 243 es.setParent(this); 244 } 245}