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