1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml.invoke;
18
19 import java.io.IOException;
20 import java.io.Serializable;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 import org.apache.commons.scxml.Context;
25 import org.apache.commons.scxml.Evaluator;
26 import org.apache.commons.scxml.SCInstance;
27 import org.apache.commons.scxml.SCXMLExecutor;
28 import org.apache.commons.scxml.TriggerEvent;
29 import org.apache.commons.scxml.env.SimpleDispatcher;
30 import org.apache.commons.scxml.env.SimpleErrorHandler;
31 import org.apache.commons.scxml.env.SimpleErrorReporter;
32 import org.apache.commons.scxml.env.SimpleSCXMLListener;
33 import org.apache.commons.scxml.io.SCXMLDigester;
34 import org.apache.commons.scxml.model.ModelException;
35 import org.apache.commons.scxml.model.SCXML;
36 import org.xml.sax.SAXException;
37
38 /***
39 * A simple {@link Invoker} for SCXML documents. Invoked SCXML document
40 * may not contain external namespace elements, further invokes etc.
41 */
42 public class SimpleSCXMLInvoker implements Invoker, Serializable {
43
44 /*** Serial version UID. */
45 private static final long serialVersionUID = 1L;
46 /*** Parent state ID. */
47 private String parentStateId;
48 /*** Event prefix, all events sent to the parent executor must begin
49 * with this prefix. */
50 private String eventPrefix;
51 /*** Invoking document's SCInstance. */
52 private SCInstance parentSCInstance;
53 /*** The invoked state machine executor. */
54 private SCXMLExecutor executor;
55 /*** Cancellation status. */
56 private boolean cancelled;
57
58
59 /*** Prefix for all events sent to the parent state machine. */
60 private static String invokePrefix = ".invoke.";
61 /*** Suffix for invoke done event. */
62 private static String invokeDone = "done";
63 /*** Suffix for invoke cancel response event. */
64 private static String invokeCancelResponse = "cancel.response";
65
66 /***
67 * {@inheritDoc}.
68 */
69 public void setParentStateId(final String parentStateId) {
70 this.parentStateId = parentStateId;
71 this.eventPrefix = parentStateId + invokePrefix;
72 this.cancelled = false;
73 }
74
75 /***
76 * {@inheritDoc}.
77 */
78 public void setSCInstance(final SCInstance scInstance) {
79 this.parentSCInstance = scInstance;
80 }
81
82 /***
83 * {@inheritDoc}.
84 */
85 public void invoke(final String source, final Map params)
86 throws InvokerException {
87 SCXML scxml = null;
88 try {
89 scxml = SCXMLDigester.digest(source,
90 new SimpleErrorHandler(), null);
91 } catch (ModelException me) {
92 throw new InvokerException(me.getMessage(), me.getCause());
93 } catch (IOException ioe) {
94 throw new InvokerException(ioe.getMessage(), ioe.getCause());
95 } catch (SAXException se) {
96 throw new InvokerException(se.getMessage(), se.getCause());
97 }
98 Evaluator eval = parentSCInstance.getEvaluator();
99 executor = new SCXMLExecutor(eval,
100 new SimpleDispatcher(), new SimpleErrorReporter());
101 Context rootCtx = eval.newContext(null);
102 for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
103 Map.Entry entry = (Map.Entry) iter.next();
104 rootCtx.setLocal((String) entry.getKey(), entry.getValue());
105 }
106 executor.setRootContext(rootCtx);
107 executor.setStateMachine(scxml);
108 executor.addListener(scxml, new SimpleSCXMLListener());
109 try {
110 executor.go();
111 } catch (ModelException me) {
112 throw new InvokerException(me.getMessage(), me.getCause());
113 }
114 }
115
116 /***
117 * {@inheritDoc}.
118 */
119 public void parentEvents(final TriggerEvent[] evts)
120 throws InvokerException {
121 if (cancelled) {
122 return;
123 }
124 boolean doneBefore = executor.getCurrentStatus().isFinal();
125 try {
126 executor.triggerEvents(evts);
127 } catch (ModelException me) {
128 throw new InvokerException(me.getMessage(), me.getCause());
129 }
130 if (!doneBefore && executor.getCurrentStatus().isFinal()) {
131 TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
132 TriggerEvent.SIGNAL_EVENT);
133 new AsyncTrigger(parentSCInstance.getExecutor(), te);
134 }
135 }
136
137 /***
138 * {@inheritDoc}.
139 */
140 public void cancel()
141 throws InvokerException {
142 cancelled = true;
143 TriggerEvent te = new TriggerEvent(eventPrefix
144 + invokeCancelResponse, TriggerEvent.SIGNAL_EVENT);
145 new AsyncTrigger(parentSCInstance.getExecutor(), te);
146 }
147
148 }
149