##### Coverage Report - org.apache.commons.scxml.SCXMLExecutor

Classes in this File | Line Coverage | Branch Coverage | Complexity
SCXMLExecutor |
67% |
88% |
| 1.4848484848484849;1.485

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;
18 |  |
19 |  |
     import java.io.Serializable;
20 |  |
     import java.util.ArrayList;
21 |  |
     import java.util.Arrays;
22 |  |
     import java.util.HashMap;
23 |  |
     import java.util.Iterator;
24 |  |
     import java.util.List;
25 |  |
     import java.util.Map;
26 |  |
27 |  |
     import org.apache.commons.logging.Log;
28 |  |
     import org.apache.commons.logging.LogFactory;
29 |  |
     import org.apache.commons.scxml.model.Datamodel;
30 |  |
     import org.apache.commons.scxml.model.History;
31 |  |
     import org.apache.commons.scxml.model.ModelException;
32 |  |
     import org.apache.commons.scxml.model.SCXML;
33 |  |
     import org.apache.commons.scxml.model.State;
34 |  |
     import org.apache.commons.scxml.model.Transition;
35 |  |
     import org.apache.commons.scxml.model.TransitionTarget;
36 |  |
     import org.apache.commons.scxml.semantics.SCXMLSemanticsImpl;
37 |  |
38 |  |
     /**
39 |  |
      * <p>The SCXML &quot;engine&quot; that executes SCXML documents. The
40 |  |
      * particular semantics used by this engine for executing the SCXML are
41 |  |
      * encapsulated in the SCXMLSemantics implementation that it uses.</p>
42 |  |
      *
43 |  |
      * <p>The default implementation is
44 |  |
      * <code>org.apache.commons.scxml.semantics.SCXMLSemanticsImpl</code></p>
45 |  |
      *
46 |  |
      * @see SCXMLSemantics
47 |  |
      */
48 |  |
     public class SCXMLExecutor implements Serializable {
49 |  |
50 |  |
         /**
51 |  |
          * Serial version UID.
52 |  |
          */
53 |  |
         private static final long serialVersionUID = 1L;
54 |  |
55 |  |
         /**
56 |  |
          * The Logger for the SCXMLExecutor.
57 |  |
          */
58 | 54 |
         private Log log = LogFactory.getLog(SCXMLExecutor.class);
59 |  |
60 |  |
         /**
61 |  |
          * The stateMachine being executed.
62 |  |
          */
63 |  |
         private SCXML stateMachine;
64 |  |
65 |  |
         /**
66 |  |
          * The current status of the stateMachine.
67 |  |
          */
68 |  |
         private Status currentStatus;
69 |  |
70 |  |
         /**
71 |  |
          * The event dispatcher to interface with external documents etc.
72 |  |
          */
73 |  |
         private EventDispatcher eventdispatcher;
74 |  |
75 |  |
         /**
76 |  |
          * The environment specific error reporter.
77 |  |
          */
78 | 48 |
         private ErrorReporter errorReporter = null;
79 |  |
80 |  |
         /**
81 |  |
          * Run-to-completion.
82 |  |
          */
83 | 48 |
         private boolean superStep = true;
84 |  |
85 |  |
         /**
86 |  |
          *  Interpretation semantics.
87 |  |
          */
88 |  |
         private SCXMLSemantics semantics;
89 |  |
90 |  |
         /**
91 |  |
          * The SCInstance.
92 |  |
          */
93 |  |
         private SCInstance scInstance;
94 |  |
95 |  |
         /**
96 |  |
          * The worker method.
97 |  |
          * Re-evaluates current status whenever any events are triggered.
98 |  |
          *
99 |  |
          * @param evts
100 |  |
          *            an array of external events which triggered during the last
101 |  |
          *            time quantum
102 |  |
          * @throws ModelException in case there is a fatal SCXML object
103 |  |
          *            model problem.
104 |  |
          */
105 |  |
         public synchronized void triggerEvents(final TriggerEvent[] evts)
106 |  |
                 throws ModelException {
107 |  |
             // Set event data, saving old values
108 | 151 |
             Object[] oldData = setEventData(evts);
109 |  |
110 |  |
             // Forward events (external only) to any existing invokes,
111 |  |
             // and finalize processing
112 | 151 |
             semantics.processInvokes(evts, errorReporter, scInstance);
113 |  |
114 | 151 |
             List evs = new ArrayList(Arrays.asList(evts));
115 | 151 |
             Step step = null;
116 |  |
117 |  |
             do {
118 |  |
                 // CreateStep
119 | 266 |
                 step = new Step(evs, currentStatus);
120 |  |
                 // EnumerateReachableTransitions
121 | 266 |
                 semantics.enumerateReachableTransitions(stateMachine, step,
122 |  |
                     errorReporter);
123 |  |
                 // FilterTransitionSet
124 | 266 |
                 semantics.filterTransitionsSet(step, eventdispatcher,
125 |  |
                     errorReporter, scInstance);
126 |  |
                 // FollowTransitions
127 | 266 |
                 semantics.followTransitions(step, errorReporter, scInstance);
128 |  |
                 // UpdateHistoryStates
129 | 266 |
                 semantics.updateHistoryStates(step, errorReporter, scInstance);
130 |  |
                 // ExecuteActions
131 | 266 |
                 semantics.executeActions(step, stateMachine, eventdispatcher,
132 |  |
                     errorReporter, scInstance);
133 |  |
                 // AssignCurrentStatus
134 | 266 |
                 updateStatus(step);
135 |  |
                 // ***Cleanup external events if superStep
136 | 266 |
                 if (superStep) {
137 | 266 |
                     evs.clear();
138 |  |
                 }
139 | 266 |
             } while (superStep && currentStatus.getEvents().size() > 0);
140 |  |
141 |  |
             // InitiateInvokes only after state machine has stabilized
142 | 151 |
             semantics.initiateInvokes(step, errorReporter, scInstance);
143 |  |
144 |  |
             // Restore event data
145 | 151 |
             restoreEventData(oldData);
146 | 151 |
             logState();
147 | 151 |
         }
148 |  |
149 |  |
         /**
150 |  |
          * Convenience method when only one event needs to be triggered.
151 |  |
          *
152 |  |
          * @param evt
153 |  |
          *            the external events which triggered during the last
154 |  |
          *            time quantum
155 |  |
          * @throws ModelException in case there is a fatal SCXML object
156 |  |
          *            model problem.
157 |  |
          */
158 |  |
         public void triggerEvent(final TriggerEvent evt)
159 |  |
                 throws ModelException {
160 | 0 |
             triggerEvents(new TriggerEvent[] {evt});
161 | 0 |
         }
162 |  |
163 |  |
         /**
164 |  |
          * Constructor.
165 |  |
          *
166 |  |
          * @param expEvaluator The expression evaluator
167 |  |
          * @param evtDisp The event dispatcher
168 |  |
          * @param errRep The error reporter
169 |  |
          */
170 |  |
         public SCXMLExecutor(final Evaluator expEvaluator,
171 |  |
                 final EventDispatcher evtDisp, final ErrorReporter errRep) {
172 | 48 |
             this(expEvaluator, evtDisp, errRep, null);
173 | 48 |
         }
174 |  |
175 |  |
         /**
176 |  |
          * Convenience constructor.
177 |  |
          */
178 |  |
         public SCXMLExecutor() {
179 | 0 |
             this(null, null, null, null);
180 | 0 |
         }
181 |  |
182 |  |
         /**
183 |  |
          * Constructor.
184 |  |
          *
185 |  |
          * @param expEvaluator The expression evaluator
186 |  |
          * @param evtDisp The event dispatcher
187 |  |
          * @param errRep The error reporter
188 |  |
          * @param semantics The SCXML semantics
189 |  |
          */
190 |  |
         public SCXMLExecutor(final Evaluator expEvaluator,
191 |  |
                 final EventDispatcher evtDisp, final ErrorReporter errRep,
192 | 48 |
                 final SCXMLSemantics semantics) {
193 | 48 |
             this.eventdispatcher = evtDisp;
194 | 48 |
             this.errorReporter = errRep;
195 | 48 |
             this.currentStatus = new Status();
196 | 48 |
             this.stateMachine = null;
197 | 48 |
             if (semantics == null) {
198 |  |
                 // Use default semantics, if none provided
199 | 48 |
                 this.semantics = new SCXMLSemanticsImpl();
200 |  |
             } else {
201 | 0 |
                 this.semantics = semantics;
202 |  |
             }
203 | 48 |
             this.scInstance = new SCInstance(this);
204 | 48 |
             this.scInstance.setEvaluator(expEvaluator);
205 | 48 |
         }
206 |  |
207 |  |
         /**
208 |  |
          * Clear all state and begin from &quot;initialstate&quot; indicated
209 |  |
          * on root SCXML element.
210 |  |
          *
211 |  |
          * @throws ModelException in case there is a fatal SCXML object
212 |  |
          *         model problem.
213 |  |
          */
214 |  |
         public synchronized void reset() throws ModelException {
215 |  |
             // Reset all variable contexts
216 | 50 |
             Context rootCtx = scInstance.getRootContext();
217 |  |
             // Clone root datamodel
218 | 50 |
             if (stateMachine == null) {
219 | 0 |
                 log.error(ERR_NO_STATE_MACHINE);
220 | 0 |
                 throw new ModelException(ERR_NO_STATE_MACHINE);
221 |  |
             } else {
222 | 50 |
                 Datamodel rootdm = stateMachine.getDatamodel();
223 | 50 |
                 SCXMLHelper.cloneDatamodel(rootdm, rootCtx,
224 |  |
                     scInstance.getEvaluator(), log);
225 |  |
             }
226 |  |
             // all states and parallels, only states have variable contexts
227 | 50 |
             for (Iterator i = stateMachine.getTargets().values().iterator();
228 | 294 |
                     i.hasNext();) {
229 | 244 |
                 TransitionTarget tt = (TransitionTarget) i.next();
230 | 244 |
                 if (tt instanceof State) {
231 | 234 |
                     Context context = scInstance.lookupContext(tt);
232 | 234 |
                     if (context != null) {
233 | 11 |
                         context.reset();
234 | 11 |
                         Datamodel dm = tt.getDatamodel();
235 | 11 |
                         if (dm != null) {
236 | 0 |
                             SCXMLHelper.cloneDatamodel(dm, context,
237 |  |
                                 scInstance.getEvaluator(), log);
238 |  |
                         }
239 |  |
                     }
240 | 10 |
                 } else if (tt instanceof History) {
241 | 7 |
                     scInstance.reset((History) tt);
242 |  |
                 }
243 |  |
             }
244 |  |
             // CreateEmptyStatus
245 | 50 |
             currentStatus = new Status();
246 | 50 |
             Step step = new Step(null, currentStatus);
247 |  |
             // DetermineInitialStates
248 | 50 |
             semantics.determineInitialStates(stateMachine,
249 |  |
                     step.getAfterStatus().getStates(),
250 |  |
                     step.getEntryList(), errorReporter, scInstance);
251 |  |
             // ExecuteActions
252 | 50 |
             semantics.executeActions(step, stateMachine, eventdispatcher,
253 |  |
                     errorReporter, scInstance);
254 |  |
             // AssignCurrentStatus
255 | 50 |
             updateStatus(step);
256 |  |
             // Execute Immediate Transitions
257 | 50 |
             if (superStep && currentStatus.getEvents().size() > 0) {
258 | 50 |
                 this.triggerEvents(new TriggerEvent[0]);
259 |  |
             } else {
260 |  |
                 // InitiateInvokes only after state machine has stabilized
261 | 0 |
                 semantics.initiateInvokes(step, errorReporter, scInstance);
262 | 0 |
                 logState();
263 |  |
             }
264 | 50 |
         }
265 |  |
266 |  |
         /**
267 |  |
          * Get the current status.
268 |  |
          *
269 |  |
          * @return The current Status
270 |  |
          */
271 |  |
         public synchronized Status getCurrentStatus() {
272 | 152 |
             return currentStatus;
273 |  |
         }
274 |  |
275 |  |
         /**
276 |  |
          * Set the expression evaluator.
277 |  |
          *
278 |  |
          * @param evaluator The evaluator to set.
279 |  |
          */
280 |  |
         public void setEvaluator(final Evaluator evaluator) {
281 | 0 |
             this.scInstance.setEvaluator(evaluator);
282 | 0 |
         }
283 |  |
284 |  |
         /**
285 |  |
          * Get the expression evaluator in use.
286 |  |
          *
287 |  |
          * @return Evaluator The evaluator in use.
288 |  |
          */
289 |  |
         public Evaluator getEvaluator() {
290 | 0 |
             return scInstance.getEvaluator();
291 |  |
         }
292 |  |
293 |  |
         /**
294 |  |
          * Set the root context for this execution.
295 |  |
          *
296 |  |
          * @param rootContext The Context that ties to the host environment.
297 |  |
          */
298 |  |
         public void setRootContext(final Context rootContext) {
299 | 48 |
             this.scInstance.setRootContext(rootContext);
300 | 48 |
         }
301 |  |
302 |  |
         /**
303 |  |
          * Get the root context for this execution.
304 |  |
          *
305 |  |
          * @return Context The root context.
306 |  |
          */
307 |  |
         public Context getRootContext() {
308 | 4 |
             return scInstance.getRootContext();
309 |  |
         }
310 |  |
311 |  |
         /**
312 |  |
          * Get the state machine that is being executed.
313 |  |
          *
314 |  |
          * @return Returns the stateMachine.
315 |  |
          */
316 |  |
         public SCXML getStateMachine() {
317 | 2 |
             return stateMachine;
318 |  |
         }
319 |  |
320 |  |
         /**
321 |  |
          * Set the state machine to be executed.
322 |  |
          *
323 |  |
          * @param stateMachine The stateMachine to set.
324 |  |
          */
325 |  |
         public void setStateMachine(final SCXML stateMachine) {
326 |  |
             // NormalizeStateMachine
327 | 48 |
             SCXML sm = semantics.normalizeStateMachine(stateMachine,
328 |  |
                     errorReporter);
329 |  |
             // StoreStateMachine
330 | 48 |
             this.stateMachine = sm;
331 | 48 |
         }
332 |  |
333 |  |
         /**
334 |  |
          * Initiate state machine execution.
335 |  |
          *
336 |  |
          * @throws ModelException in case there is a fatal SCXML object
337 |  |
          *  model problem.
338 |  |
          */
339 |  |
         public void go() throws ModelException {
340 |  |
             // same as reset
341 | 48 |
             this.reset();
342 | 48 |
         }
343 |  |
344 |  |
         /**
345 |  |
          * Get the environment specific error reporter.
346 |  |
          *
347 |  |
          * @return Returns the errorReporter.
348 |  |
          */
349 |  |
         public ErrorReporter getErrorReporter() {
350 | 0 |
             return errorReporter;
351 |  |
         }
352 |  |
353 |  |
         /**
354 |  |
          * Set the environment specific error reporter.
355 |  |
          *
356 |  |
          * @param errorReporter The errorReporter to set.
357 |  |
          */
358 |  |
         public void setErrorReporter(final ErrorReporter errorReporter) {
359 | 0 |
             this.errorReporter = errorReporter;
360 | 0 |
         }
361 |  |
362 |  |
         /**
363 |  |
          * Get the event dispatcher.
364 |  |
          *
365 |  |
          * @return Returns the eventdispatcher.
366 |  |
          */
367 |  |
         public EventDispatcher getEventdispatcher() {
368 | 0 |
             return eventdispatcher;
369 |  |
         }
370 |  |
371 |  |
         /**
372 |  |
          * Set the event dispatcher.
373 |  |
          *
374 |  |
          * @param eventdispatcher The eventdispatcher to set.
375 |  |
          */
376 |  |
         public void setEventdispatcher(final EventDispatcher eventdispatcher) {
377 | 0 |
             this.eventdispatcher = eventdispatcher;
378 | 0 |
         }
379 |  |
380 |  |
         /**
381 |  |
          * Use &quot;super-step&quot;, default is <code>true</code>
382 |  |
          * (that is, run-to-completion is default).
383 |  |
          *
384 |  |
          * @return Returns the superStep property.
385 |  |
          * @see #setSuperStep(boolean)
386 |  |
          */
387 |  |
         public boolean isSuperStep() {
388 | 0 |
             return superStep;
389 |  |
         }
390 |  |
391 |  |
         /**
392 |  |
          * Set the super step.
393 |  |
          *
394 |  |
          * @param superStep
395 |  |
          * if true, the internal derived events are also processed
396 |  |
          *    (run-to-completion);
397 |  |
          * if false, the internal derived events are stored in the
398 |  |
          * CurrentStatus property and processed within the next
399 |  |
          * triggerEvents() invocation, also the immediate (empty event) transitions
400 |  |
          * are deferred until the next step
401 |  |
           */
402 |  |
         public void setSuperStep(final boolean superStep) {
403 | 46 |
             this.superStep = superStep;
404 | 46 |
         }
405 |  |
406 |  |
         /**
407 |  |
          * Add a listener to the document root.
408 |  |
          *
409 |  |
          * @param scxml The document root to attach listener to.
410 |  |
          * @param listener The SCXMLListener.
411 |  |
          */
412 |  |
         public void addListener(final SCXML scxml, final SCXMLListener listener) {
413 | 47 |
             Object observable = scxml;
414 | 47 |
             scInstance.getNotificationRegistry().addListener(observable, listener);
415 | 47 |
         }
416 |  |
417 |  |
         /**
418 |  |
          * Remove this listener from the document root.
419 |  |
          *
420 |  |
          * @param scxml The document root.
421 |  |
          * @param listener The SCXMLListener to be removed.
422 |  |
          */
423 |  |
         public void removeListener(final SCXML scxml,
424 |  |
                 final SCXMLListener listener) {
425 | 0 |
             Object observable = scxml;
426 | 0 |
             scInstance.getNotificationRegistry().removeListener(observable,
427 |  |
                 listener);
428 | 0 |
         }
429 |  |
430 |  |
         /**
431 |  |
          * Add a listener to this transition target.
432 |  |
          *
433 |  |
          * @param transitionTarget The <code>TransitionTarget</code> to
434 |  |
          *                         attach listener to.
435 |  |
          * @param listener The SCXMLListener.
436 |  |
          */
437 |  |
         public void addListener(final TransitionTarget transitionTarget,
438 |  |
                 final SCXMLListener listener) {
439 | 0 |
             Object observable = transitionTarget;
440 | 0 |
             scInstance.getNotificationRegistry().addListener(observable, listener);
441 | 0 |
         }
442 |  |
443 |  |
         /**
444 |  |
          * Remove this listener for this transition target.
445 |  |
          *
446 |  |
          * @param transitionTarget The <code>TransitionTarget</code>.
447 |  |
          * @param listener The SCXMLListener to be removed.
448 |  |
          */
449 |  |
         public void removeListener(final TransitionTarget transitionTarget,
450 |  |
                 final SCXMLListener listener) {
451 | 0 |
             Object observable = transitionTarget;
452 | 0 |
             scInstance.getNotificationRegistry().removeListener(observable,
453 |  |
                 listener);
454 | 0 |
         }
455 |  |
456 |  |
         /**
457 |  |
          * Add a listener to this transition.
458 |  |
          *
459 |  |
          * @param transition The <code>Transition</code> to attach listener to.
460 |  |
          * @param listener The SCXMLListener.
461 |  |
          */
462 |  |
         public void addListener(final Transition transition,
463 |  |
                 final SCXMLListener listener) {
464 | 0 |
             Object observable = transition;
465 | 0 |
             scInstance.getNotificationRegistry().addListener(observable, listener);
466 | 0 |
         }
467 |  |
468 |  |
         /**
469 |  |
          * Remove this listener for this transition.
470 |  |
          *
471 |  |
          * @param transition The <code>Transition</code>.
472 |  |
          * @param listener The SCXMLListener to be removed.
473 |  |
          */
474 |  |
         public void removeListener(final Transition transition,
475 |  |
                 final SCXMLListener listener) {
476 | 0 |
             Object observable = transition;
477 | 0 |
             scInstance.getNotificationRegistry().removeListener(observable,
478 |  |
                 listener);
479 | 0 |
         }
480 |  |
481 |  |
         /**
482 |  |
          * Register an <code>Invoker</code> for this target type.
483 |  |
          *
484 |  |
          * @param targettype The target type (specified by "targettype"
485 |  |
          *                   attribute of &lt;invoke&gt; tag).
486 |  |
          * @param invokerClass The <code>Invoker</code> <code>Class</code>.
487 |  |
          */
488 |  |
         public void registerInvokerClass(final String targettype,
489 |  |
                 final Class invokerClass) {
490 | 1 |
             scInstance.registerInvokerClass(targettype, invokerClass);
491 | 1 |
         }
492 |  |
493 |  |
         /**
494 |  |
          * Remove the <code>Invoker</code> registered for this target
495 |  |
          * type (if there is one registered).
496 |  |
          *
497 |  |
          * @param targettype The target type (specified by "targettype"
498 |  |
          *                   attribute of &lt;invoke&gt; tag).
499 |  |
          */
500 |  |
         public void unregisterInvokerClass(final String targettype) {
501 | 0 |
             scInstance.unregisterInvokerClass(targettype);
502 | 0 |
         }
503 |  |
504 |  |
         /**
505 |  |
          * Get the state chart instance for this executor.
506 |  |
          *
507 |  |
          * @return The SCInstance for this executor.
508 |  |
          */
509 |  |
         SCInstance getSCInstance() {
510 | 2 |
             return scInstance;
511 |  |
         }
512 |  |
513 |  |
         /**
514 |  |
          * Log the current set of active states.
515 |  |
          */
516 |  |
         private void logState() {
517 | 151 |
             if (log.isInfoEnabled()) {
518 | 0 |
                 Iterator si = currentStatus.getStates().iterator();
519 | 0 |
                 StringBuffer sb = new StringBuffer("Current States: [");
520 | 0 |
                 while (si.hasNext()) {
521 | 0 |
                     State s = (State) si.next();
522 | 0 |
                     sb.append(s.getId());
523 | 0 |
                     if (si.hasNext()) {
524 | 0 |
                         sb.append(", ");
525 |  |
                     }
526 |  |
                 }
527 | 0 |
                 sb.append(']');
528 | 0 |
                 log.info(sb.toString());
529 |  |
             }
530 | 151 |
         }
531 |  |
532 |  |
         /**
533 |  |
          * @param step The most recent Step
534 |  |
          */
535 |  |
         private void updateStatus(final Step step) {
536 | 316 |
             currentStatus = step.getAfterStatus();
537 | 316 |
             scInstance.getRootContext().setLocal("_ALL_STATES",
538 |  |
                 SCXMLHelper.getAncestorClosure(currentStatus.getStates(), null));
539 | 316 |
         }
540 |  |
541 |  |
         /**
542 |  |
          * @param evts The events being triggered.
543 |  |
          * @return Object[] Previous values.
544 |  |
          */
545 |  |
         private Object[] setEventData(final TriggerEvent[] evts) {
546 | 151 |
             Context rootCtx = scInstance.getRootContext();
547 | 151 |
             Object[] oldData = {rootCtx.get(EVENT_DATA),
548 |  |
                 rootCtx.get(EVENT_DATA_MAP)};
549 | 151 |
             Object eventData = null;
550 | 151 |
             Map payloadMap = new HashMap();
551 | 151 |
             int len = evts.length;
552 | 253 |
             for (int i = 0; i < len; i++) {
553 | 102 |
                 TriggerEvent te = evts[i];
554 | 102 |
                 payloadMap.put(te.getName(), te.getPayload());
555 |  |
             }
556 | 151 |
             if (len == 1) {
557 |  |
                 // we have only one event
558 | 100 |
                 eventData = evts[0].getPayload();
559 |  |
             }
560 | 151 |
             rootCtx.setLocal(EVENT_DATA, eventData);
561 | 151 |
             rootCtx.setLocal(EVENT_DATA_MAP, payloadMap);
562 | 151 |
             return oldData;
563 |  |
         }
564 |  |
565 |  |
         /**
566 |  |
          * @param oldData The old values to restore to.
567 |  |
          */
568 |  |
         private void restoreEventData(final Object[] oldData) {
569 | 151 |
             scInstance.getRootContext().setLocal(EVENT_DATA, oldData[0]);
570 | 151 |
             scInstance.getRootContext().setLocal(EVENT_DATA_MAP, oldData[1]);
571 | 151 |
         }
572 |  |
573 |  |
         /**
574 |  |
          * The special variable for storing single event data / payload.
575 |  |
          */
576 |  |
         private static final String EVENT_DATA = "_eventdata";
577 |  |
578 |  |
         /**
579 |  |
          * The special variable for storing event data / payload,
580 |  |
          * when multiple events are triggered, keyed by event name.
581 |  |
          */
582 |  |
         private static final String EVENT_DATA_MAP = "_eventdatamap";
583 |  |
584 |  |
         /**
585 |  |
          * SCXMLExecutor put into motion without setting a model (state machine).
586 |  |
          */
587 |  |
         private static final String ERR_NO_STATE_MACHINE =
588 |  |
             "SCXMLExecutor: State machine not set";
589 |  |
590 |  |
     }
591 |  |