1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.scxml.model;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.StringTokenizer;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.scxml.Context;
29 import org.apache.commons.scxml.ErrorReporter;
30 import org.apache.commons.scxml.Evaluator;
31 import org.apache.commons.scxml.EventDispatcher;
32 import org.apache.commons.scxml.SCInstance;
33 import org.apache.commons.scxml.SCXMLExpressionException;
34 import org.apache.commons.scxml.SCXMLHelper;
35 import org.apache.commons.scxml.TriggerEvent;
36
37 /***
38 * The class in this SCXML object model that corresponds to the
39 * <send> SCXML element.
40 *
41 */
42 public class Send extends Action implements ExternalContent {
43
44 /***
45 * The default targettype.
46 */
47 private static final String TARGETTYPE_SCXML = "scxml";
48
49 /***
50 * The spec mandated derived event when target cannot be reached
51 * for TARGETTYPE_SCXML.
52 */
53 private static final String EVENT_ERR_SEND_TARGETUNAVAILABLE =
54 "error.send.targetunavailable";
55
56 /***
57 * The ID of the send message.
58 */
59 private String sendid;
60
61 /***
62 * An expression returning the target location of the event.
63 */
64 private String target;
65
66 /***
67 * The type of the Event I/O Processor that the event.
68 * should be dispatched to
69 */
70 private String targettype;
71
72 /***
73 * The event is dispatched after the delay interval elapses.
74 */
75 private String delay;
76
77 /***
78 * The data containing information which may be used by the
79 * implementing platform to configure the event processor.
80 */
81 private String hints;
82
83 /***
84 * The namelist to the sent.
85 */
86 private String namelist;
87
88 /***
89 * The list of external nodes associated with this <send> element.
90 */
91 private List externalNodes;
92
93 /***
94 * The type of event being generated.
95 */
96 private String event;
97
98 /***
99 * OutputFormat used to serialize external nodes.
100 *
101 private static final OutputFormat format;
102 static {
103 format = new OutputFormat();
104 format.setOmitXMLDeclaration(true);
105 }
106 */
107
108 /***
109 * Constructor.
110 */
111 public Send() {
112 super();
113 this.externalNodes = new ArrayList();
114 this.targettype = TARGETTYPE_SCXML;
115 }
116
117 /***
118 * Get the delay.
119 *
120 * @return Returns the delay.
121 */
122 public final String getDelay() {
123 return delay;
124 }
125
126 /***
127 * Set the delay.
128 *
129 * @param delay The delay to set.
130 */
131 public final void setDelay(final String delay) {
132 this.delay = delay;
133 }
134
135 /***
136 * Get the list of external namespaced child nodes.
137 *
138 * @return List Returns the list of externalnodes.
139 */
140 public final List getExternalNodes() {
141 return externalNodes;
142 }
143
144 /***
145 * Set the list of external namespaced child nodes.
146 *
147 * @param externalNodes The externalnode to set.
148 */
149 public final void setExternalNodes(final List externalNodes) {
150 this.externalNodes = externalNodes;
151 }
152
153 /***
154 * Get the hints for this <send> element.
155 *
156 * @return String Returns the hints.
157 */
158 public final String getHints() {
159 return hints;
160 }
161
162 /***
163 * Set the hints for this <send> element.
164 *
165 * @param hints The hints to set.
166 */
167 public final void setHints(final String hints) {
168 this.hints = hints;
169 }
170
171 /***
172 * Get the namelist.
173 *
174 * @return String Returns the namelist.
175 */
176 public final String getNamelist() {
177 return namelist;
178 }
179
180 /***
181 * Set the namelist.
182 *
183 * @param namelist The namelist to set.
184 */
185 public final void setNamelist(final String namelist) {
186 this.namelist = namelist;
187 }
188
189 /***
190 * Get the identifier for this <send> element.
191 *
192 * @return String Returns the sendid.
193 */
194 public final String getSendid() {
195 return sendid;
196 }
197
198 /***
199 * Set the identifier for this <send> element.
200 *
201 * @param sendid The sendid to set.
202 */
203 public final void setSendid(final String sendid) {
204 this.sendid = sendid;
205 }
206
207 /***
208 * Get the target for this <send> element.
209 *
210 * @return String Returns the target.
211 */
212 public final String getTarget() {
213 return target;
214 }
215
216 /***
217 * Set the target for this <send> element.
218 *
219 * @param target The target to set.
220 */
221 public final void setTarget(final String target) {
222 this.target = target;
223 }
224
225 /***
226 * Get the target type for this <send> element.
227 *
228 * @return String Returns the targettype.
229 */
230 public final String getTargettype() {
231 return targettype;
232 }
233
234 /***
235 * Set the target type for this <send> element.
236 *
237 * @param targettype The targettype to set.
238 */
239 public final void setTargettype(final String targettype) {
240 this.targettype = targettype;
241 }
242
243 /***
244 * Get the event to send.
245 *
246 * @param event The event to set.
247 */
248 public final void setEvent(final String event) {
249 this.event = event;
250 }
251
252 /***
253 * Set the event to send.
254 *
255 * @return String Returns the event.
256 */
257 public final String getEvent() {
258 return event;
259 }
260
261 /***
262 * {@inheritDoc}
263 */
264 public void execute(final EventDispatcher evtDispatcher,
265 final ErrorReporter errRep, final SCInstance scInstance,
266 final Log appLog, final Collection derivedEvents)
267 throws ModelException, SCXMLExpressionException {
268
269 if (targettype != null && targettype.trim().toLowerCase().
270 equals(TARGETTYPE_SCXML)) {
271 if (SCXMLHelper.isStringEmpty(target)) {
272 derivedEvents.add(new TriggerEvent(event,
273 TriggerEvent.SIGNAL_EVENT));
274 } else {
275
276 appLog.warn("<send>: Unavailable target - " + target);
277 derivedEvents.add(new TriggerEvent(
278 EVENT_ERR_SEND_TARGETUNAVAILABLE,
279 TriggerEvent.ERROR_EVENT));
280 }
281
282 return;
283 }
284
285 State parentState = getParentState();
286 Context ctx = scInstance.getContext(parentState);
287 Evaluator eval = scInstance.getEvaluator();
288 Object hintsValue = null;
289 if (!SCXMLHelper.isStringEmpty(hints)) {
290 hintsValue = eval.eval(ctx, hints);
291 }
292 Map params = null;
293 if (!SCXMLHelper.isStringEmpty(namelist)) {
294 StringTokenizer tkn = new StringTokenizer(namelist);
295 params = new HashMap(tkn.countTokens());
296 while (tkn.hasMoreTokens()) {
297 String varName = tkn.nextToken();
298 Object varObj = ctx.get(varName);
299 if (varObj == null) {
300
301 errRep.onError(ErrorReporter.UNDEFINED_VARIABLE,
302 varName + " = null", parentState);
303 }
304 params.put(varName, varObj);
305 }
306 }
307 long wait = 0L;
308 if (delay != null && delay.length() > 0) {
309 try {
310 wait = Long.parseLong(delay.trim());
311 } catch (NumberFormatException nfe) {
312 appLog.warn("Could not parse delay for <send>, "
313 + "it will be treated as immediate", nfe);
314 }
315 }
316 evtDispatcher.send(sendid, target, targettype, event, params,
317 hintsValue, wait, externalNodes);
318 }
319
320 }
321