1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml2.model;
18
19 import java.util.LinkedHashMap;
20 import java.util.Map;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.scxml2.ActionExecutionContext;
24 import org.apache.commons.scxml2.Context;
25 import org.apache.commons.scxml2.Evaluator;
26 import org.apache.commons.scxml2.SCXMLExpressionException;
27 import org.apache.commons.scxml2.SCXMLIOProcessor;
28 import org.apache.commons.scxml2.SCXMLSystemContext;
29
30
31
32
33
34
35 public class Send extends NamelistHolder implements ContentContainer {
36
37
38
39
40 private static final long serialVersionUID = 1L;
41
42
43
44
45 private static final String MILLIS = "ms";
46
47
48
49
50 private static final String SECONDS = "s";
51
52
53
54
55 private static final String MINUTES = "m";
56
57
58
59
60 private static final long MILLIS_IN_A_SECOND = 1000L;
61
62
63
64
65 private static final long MILLIS_IN_A_MINUTE = 60000L;
66
67
68
69
70 private String id;
71
72
73
74
75 private String idlocation;
76
77
78
79
80 private String target;
81
82
83
84
85
86 private String targetexpr;
87
88
89
90
91 private String type;
92
93
94
95
96 private String typeexpr;
97
98
99
100
101 private String delay;
102
103
104
105
106 private String delayexpr;
107
108
109
110
111 private String hints;
112
113
114
115
116 private String event;
117
118
119
120
121 private String eventexpr;
122
123
124
125
126 private Content content;
127
128
129
130
131 public Send() {
132 super();
133 }
134
135
136
137
138 public String getIdlocation() {
139 return idlocation;
140 }
141
142
143
144
145
146
147 public void setIdlocation(final String idlocation) {
148 this.idlocation = idlocation;
149 }
150
151
152
153
154
155
156 public final String getDelay() {
157 return delay;
158 }
159
160
161
162
163
164
165 public final void setDelay(final String delay) {
166 this.delay = delay;
167 }
168
169
170
171
172 public String getDelayexpr() {
173 return delayexpr;
174 }
175
176
177
178
179
180
181 public void setDelayexpr(final String delayexpr) {
182 this.delayexpr = delayexpr;
183 }
184
185
186
187
188
189
190 public final String getHints() {
191 return hints;
192 }
193
194
195
196
197
198
199 public final void setHints(final String hints) {
200 this.hints = hints;
201 }
202
203
204
205
206
207
208 public final String getId() {
209 return id;
210 }
211
212
213
214
215
216
217 public final void setId(final String id) {
218 this.id = id;
219 }
220
221
222
223
224
225
226 public final String getTarget() {
227 return target;
228 }
229
230
231
232
233
234
235 public final void setTarget(final String target) {
236 this.target = target;
237 }
238
239
240
241
242 public String getTargetexpr() {
243 return targetexpr;
244 }
245
246
247
248
249
250
251 public void setTargetexpr(final String targetexpr) {
252 this.targetexpr = targetexpr;
253 }
254
255
256
257
258
259
260 public final String getType() {
261 return type;
262 }
263
264
265
266
267
268
269 public final void setType(final String type) {
270 this.type = type;
271 }
272
273
274
275
276 public String getTypeexpr() {
277 return typeexpr;
278 }
279
280
281
282
283
284
285 public void setTypeexpr(final String typeexpr) {
286 this.typeexpr = typeexpr;
287 }
288
289
290
291
292
293
294 public final void setEvent(final String event) {
295 this.event = event;
296 }
297
298
299
300
301
302
303 public final String getEvent() {
304 return event;
305 }
306
307
308
309
310 public String getEventexpr() {
311 return eventexpr;
312 }
313
314
315
316
317
318
319 public void setEventexpr(final String eventexpr) {
320 this.eventexpr = eventexpr;
321 }
322
323
324
325
326
327
328 public Content getContent() {
329 return content;
330 }
331
332
333
334
335
336
337 public void setContent(final Content content) {
338 this.content = content;
339 }
340
341
342
343
344 @SuppressWarnings("unchecked")
345 @Override
346 public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException {
347
348 EnterableState parentState = getParentEnterableState();
349 Context ctx = exctx.getContext(parentState);
350 ctx.setLocal(getNamespacesKey(), getNamespaces());
351 Evaluator eval = exctx.getEvaluator();
352
353
354 Object hintsValue = null;
355 if (hints != null) {
356 hintsValue = eval.eval(ctx, hints);
357 }
358 if (id == null) {
359 id = ctx.getSystemContext().generateSessionId();
360 if (idlocation != null) {
361 eval.evalAssign(ctx, idlocation, id, Evaluator.AssignType.REPLACE_CHILDREN, null);
362 }
363 }
364 String targetValue = target;
365 if (targetValue == null && targetexpr != null) {
366 targetValue = (String) getTextContentIfNodeResult(eval.eval(ctx, targetexpr));
367 if ((targetValue == null || targetValue.trim().length() == 0)
368 && exctx.getAppLog().isWarnEnabled()) {
369 exctx.getAppLog().warn("<send>: target expression \"" + targetexpr
370 + "\" evaluated to null or empty String");
371 }
372 }
373 String typeValue = type;
374 if (typeValue == null && typeexpr != null) {
375 typeValue = (String) getTextContentIfNodeResult(eval.eval(ctx, typeexpr));
376 if ((typeValue == null || typeValue.trim().length() == 0)
377 && exctx.getAppLog().isWarnEnabled()) {
378 exctx.getAppLog().warn("<send>: type expression \"" + typeexpr
379 + "\" evaluated to null or empty String");
380 }
381 }
382 if (typeValue == null) {
383
384 typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
385 } else if (!SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR.equals(typeValue) && typeValue.trim().equalsIgnoreCase(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR)) {
386 typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
387 }
388 Object payload = null;
389 Map<String, Object> payloadDataMap = new LinkedHashMap<String, Object>();
390 addNamelistDataToPayload(exctx, payloadDataMap);
391 addParamsToPayload(exctx, payloadDataMap);
392 if (!payloadDataMap.isEmpty()) {
393 payload = makeEventPayload(eval, payloadDataMap);
394 }
395 else if (content != null) {
396 if (content.getExpr() != null) {
397 payload = clonePayloadValue(eval.eval(ctx, content.getExpr()));
398 } else {
399 payload = clonePayloadValue(content.getBody());
400 }
401 }
402 long wait = 0L;
403 String delayString = delay;
404 if (delayString == null && delayexpr != null) {
405 Object delayValue = getTextContentIfNodeResult(eval.eval(ctx, delayexpr));
406 if (delayValue != null) {
407 delayString = delayValue.toString();
408 }
409 }
410 if (delayString != null) {
411 wait = parseDelay(delayString, exctx.getAppLog());
412 }
413 String eventValue = event;
414 if (eventValue == null && eventexpr != null) {
415 eventValue = (String) getTextContentIfNodeResult(eval.eval(ctx, eventexpr));
416 if ((eventValue == null)) {
417 throw new SCXMLExpressionException("<send>: event expression \"" + eventexpr
418 + "\" evaluated to null");
419 }
420 }
421 Map<String, SCXMLIOProcessor> ioProcessors = (Map<String, SCXMLIOProcessor>) ctx.get(SCXMLSystemContext.IOPROCESSORS_KEY);
422 ctx.setLocal(getNamespacesKey(), null);
423 if (exctx.getAppLog().isDebugEnabled()) {
424 exctx.getAppLog().debug("<send>: Dispatching event '" + eventValue
425 + "' to target '" + targetValue + "' of target type '"
426 + typeValue + "' with suggested delay of " + wait
427 + "ms");
428 }
429 exctx.getEventDispatcher().send(ioProcessors, id, targetValue, typeValue, eventValue,
430 payload, hintsValue, wait);
431 }
432
433
434
435
436
437
438
439
440
441 private long parseDelay(final String delayString, final Log appLog)
442 throws SCXMLExpressionException {
443
444 long wait = 0L;
445 long multiplier = 1L;
446
447 if (delayString != null && delayString.trim().length() > 0) {
448
449 String trimDelay = delayString.trim();
450 String numericDelay = trimDelay;
451 if (trimDelay.endsWith(MILLIS)) {
452 numericDelay = trimDelay.substring(0, trimDelay.length() - 2);
453 } else if (trimDelay.endsWith(SECONDS)) {
454 multiplier = MILLIS_IN_A_SECOND;
455 numericDelay = trimDelay.substring(0, trimDelay.length() - 1);
456 } else if (trimDelay.endsWith(MINUTES)) {
457 multiplier = MILLIS_IN_A_MINUTE;
458 numericDelay = trimDelay.substring(0, trimDelay.length() - 1);
459 }
460
461 try {
462 wait = Long.parseLong(numericDelay);
463 } catch (NumberFormatException nfe) {
464 appLog.error(nfe.getMessage(), nfe);
465 throw new SCXMLExpressionException(nfe.getMessage(), nfe);
466 }
467 wait *= multiplier;
468
469 }
470 return wait;
471 }
472 }
473