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