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.HashMap;
20 import java.util.Map;
21
22 import org.apache.commons.scxml2.ActionExecutionContext;
23 import org.apache.commons.scxml2.Context;
24 import org.apache.commons.scxml2.Evaluator;
25 import org.apache.commons.scxml2.PathResolver;
26 import org.apache.commons.scxml2.SCXMLExecutionContext;
27 import org.apache.commons.scxml2.SCXMLExpressionException;
28 import org.apache.commons.scxml2.SCXMLSystemContext;
29 import org.apache.commons.scxml2.TriggerEvent;
30 import org.apache.commons.scxml2.invoke.Invoker;
31 import org.apache.commons.scxml2.invoke.InvokerException;
32 import org.apache.commons.scxml2.semantics.ErrorConstants;
33 import org.w3c.dom.Node;
34
35
36
37
38
39
40 public class Invoke extends NamelistHolder implements PathResolverHolder, ContentContainer {
41
42
43
44
45 private static final long serialVersionUID = 1L;
46
47
48
49
50 private static final String CURRENT_EXECUTION_CONTEXT_KEY = "_CURRENT_EXECUTION_CONTEXT";
51
52
53
54
55 private String id;
56
57
58
59
60 private String idlocation;
61
62
63
64
65 private String type;
66
67
68
69
70 private String typeexpr;
71
72
73
74
75 private String src;
76
77
78
79
80
81 private String srcexpr;
82
83
84
85
86 private Boolean autoForward;
87
88
89
90
91 private Finalize finalize;
92
93
94
95
96 private PathResolver pathResolver;
97
98
99
100
101 private Content content;
102
103 private EnterableState parent;
104
105
106
107
108
109
110 public final String getId() {
111 return id;
112 }
113
114
115
116
117
118
119 public final void setId(final String id) {
120 this.id = id;
121 }
122
123
124
125
126 public String getIdlocation() {
127 return idlocation;
128 }
129
130
131
132
133
134 public void setIdlocation(final String idlocation) {
135 this.idlocation = idlocation;
136 }
137
138
139
140
141
142
143 public final String getType() {
144 return type;
145 }
146
147
148
149
150
151
152 public final void setType(final String type) {
153 this.type = type;
154 }
155
156
157
158
159 public String getTypeexpr() {
160 return typeexpr;
161 }
162
163
164
165
166
167 public void setTypeexpr(final String typeexpr) {
168 this.typeexpr = typeexpr;
169 }
170
171
172
173
174
175
176 public final String getSrc() {
177 return src;
178 }
179
180
181
182
183
184
185 public final void setSrc(final String src) {
186 this.src = src;
187 }
188
189
190
191
192
193
194
195 public final String getSrcexpr() {
196 return srcexpr;
197 }
198
199
200
201
202
203
204
205 public final void setSrcexpr(final String srcexpr) {
206 this.srcexpr = srcexpr;
207 }
208
209
210
211
212
213 public final boolean isAutoForward() {
214 return autoForward != null && autoForward;
215 }
216
217
218
219
220 public final Boolean getAutoForward() {
221 return autoForward;
222 }
223
224
225
226
227
228 public final void setAutoForward(final Boolean autoForward) {
229 this.autoForward = autoForward;
230 }
231
232
233
234
235
236
237 public final Finalize getFinalize() {
238 return finalize;
239 }
240
241
242
243
244
245
246 public final void setFinalize(final Finalize finalize) {
247 this.finalize = finalize;
248 }
249
250
251
252
253
254
255 public PathResolver getPathResolver() {
256 return pathResolver;
257 }
258
259
260
261
262
263
264 public void setPathResolver(final PathResolver pathResolver) {
265 this.pathResolver = pathResolver;
266 }
267
268
269
270
271
272
273 @Override
274 public final boolean equals(final Object other) {
275 return this == other;
276 }
277
278
279
280
281
282 @Override
283 public final int hashCode() {
284 return System.identityHashCode(this);
285 }
286
287
288
289
290
291
292 public Content getContent() {
293 return content;
294 }
295
296
297
298
299 public String getCurrentSCXMLExecutionContextKey() {
300 return CURRENT_EXECUTION_CONTEXT_KEY;
301 }
302
303
304
305
306
307
308 public void setContent(final Content content) {
309 this.content = content;
310 }
311
312
313
314
315
316
317 public EnterableState getParentEnterableState() {
318 return parent;
319 }
320
321
322
323
324
325 public void setParentEnterableState(final EnterableState parent) {
326 if (parent == null) {
327 throw new IllegalArgumentException("Parent parameter cannot be null");
328 }
329 this.parent = parent;
330 }
331
332 @SuppressWarnings("unchecked")
333 @Override
334 public void execute(final ActionExecutionContext axctx) throws ModelException {
335 EnterableState parentState = getParentEnterableState();
336 Context ctx = axctx.getContext(parentState);
337 SCXMLExecutionContext exctx = (SCXMLExecutionContext)ctx.getVars().get(getCurrentSCXMLExecutionContextKey());
338 if (exctx == null) {
339 throw new ModelException("Missing current SCXMLExecutionContext instance in context under key: "+ getCurrentSCXMLExecutionContextKey());
340 }
341 try {
342 ctx.setLocal(getNamespacesKey(), getNamespaces());
343 Evaluator eval = axctx.getEvaluator();
344
345 String typeValue = type;
346 if (typeValue == null && typeexpr != null) {
347 typeValue = (String) getTextContentIfNodeResult(eval.eval(ctx, typeexpr));
348 if (typeValue == null) {
349 throw new SCXMLExpressionException("<invoke> for state "+parentState.getId() +
350 ": type expression \"" + typeexpr + "\" evaluated to null or empty String");
351 }
352 }
353 if (typeValue == null) {
354 typeValue = SCXMLExecutionContext.SCXML_INVOKER_TYPE;
355 }
356 Invoker invoker = exctx.newInvoker(typeValue);
357
358 String invokeId = getId();
359 if (invokeId == null) {
360 invokeId = parentState.getId() + "." + ctx.get(SCXMLSystemContext.SESSIONID_KEY);
361 }
362 if (getId() == null && getIdlocation() != null) {
363 eval.evalAssign(ctx, idlocation, invokeId, Evaluator.AssignType.REPLACE_CHILDREN, null);
364 }
365 invoker.setInvokeId(invokeId);
366
367 String src = getSrc();
368 if (src == null && getSrcexpr() != null) {
369 src = (String) getTextContentIfNodeResult(eval.eval(ctx, getSrcexpr()));
370 }
371 if (src != null) {
372 PathResolver pr = getPathResolver();
373 if (pr != null) {
374 src = getPathResolver().resolvePath(src);
375 }
376 }
377 Node srcNode = null;
378 if (src == null && getContent() != null) {
379 Object contentValue;
380 if (content.getExpr() != null) {
381 contentValue = eval.eval(ctx, content.getExpr());
382 } else {
383 contentValue = content.getBody();
384 }
385 if (contentValue instanceof Node) {
386 srcNode = ((Node)contentValue).cloneNode(true);
387 }
388 else if (contentValue != null) {
389 src = String.valueOf(contentValue);
390 }
391 }
392 if (src == null && srcNode == null) {
393 throw new SCXMLExpressionException("<invoke> for state "+parentState.getId() +
394 ": no src and no content defined");
395 }
396 Map<String, Object> payloadDataMap = new HashMap<String, Object>();
397 addNamelistDataToPayload(axctx, payloadDataMap);
398 addParamsToPayload(axctx, payloadDataMap);
399 invoker.setParentSCXMLExecutor(exctx.getSCXMLExecutor());
400 if (src != null) {
401 invoker.invoke(src, payloadDataMap);
402 }
403
404 exctx.registerInvoker(this, invoker);
405 }
406 catch (InvokerException e) {
407 axctx.getErrorReporter().onError(ErrorConstants.EXECUTION_ERROR, e.getMessage(), this);
408 axctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
409 }
410 catch (SCXMLExpressionException e) {
411 axctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
412 axctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), this);
413 }
414 finally {
415 ctx.setLocal(getNamespacesKey(), null);
416 }
417 }
418 }