*/
@Override
public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException {
// Send attributes evaluation
EnterableState parentState = getParentEnterableState();
Context ctx = exctx.getContext(parentState);
ctx.setLocal(getNamespacesKey(), getNamespaces());
Evaluator eval = exctx.getEvaluator();
// Most attributes of <send> are expressions so need to be
// evaluated before the EventDispatcher callback
Object hintsValue = null;
if (hints != null) {
hintsValue = eval.eval(ctx, hints);
}
String targetValue = target;
if (target != null) {
targetValue = (String) eval.eval(ctx, target);
if ((targetValue == null || targetValue.trim().length() == 0)
&& exctx.getAppLog().isWarnEnabled()) {
exctx.getAppLog().warn("<send>: target expression \"" + target
+ "\" evaluated to null or empty String");
}
}
String typeValue;
if (type != null) {
typeValue = (String) eval.eval(ctx, type);
if ((typeValue == null || typeValue.trim().length() == 0)
&& exctx.getAppLog().isWarnEnabled()) {
exctx.getAppLog().warn("<send>: type expression \"" + type
+ "\" evaluated to null or empty String");
}
} else {
// must default to 'scxml' when unspecified
typeValue = TYPE_SCXML;
}
Map<String, Object> params = null;
if (namelist != null) {
StringTokenizer tkn = new StringTokenizer(namelist);
params = new HashMap<String, Object>(tkn.countTokens());
while (tkn.hasMoreTokens()) {
String varName = tkn.nextToken();
Object varObj = ctx.get(varName);
if (varObj == null) {
//considered as a warning here
exctx.getErrorReporter().onError(ErrorConstants.UNDEFINED_VARIABLE,
varName + " = null", parentState);
}
params.put(varName, varObj);
}
}
long wait = 0L;
if (delay != null) {
Object delayValue = eval.eval(ctx, delay);
if (delayValue != null) {
String delayString = delayValue.toString();
wait = parseDelay(delayString, exctx.getAppLog());
}
}
String eventValue = event;
if (event != null) {
eventValue = (String) eval.eval(ctx, event);
if ((eventValue == null || eventValue.trim().length() == 0) && exctx.getAppLog().isWarnEnabled()) {
exctx.getAppLog().warn("<send>: event expression \"" + event
+ "\" evaluated to null or empty String");
}
}
// Lets see if we should handle it ourselves
if (typeValue != null
&& typeValue.trim().equalsIgnoreCase(TYPE_SCXML)) {
if (targetValue == null || targetValue.trim().length() == 0) {
// TODO: Remove both short-circuit passes in v1.0
if (wait == 0L) {
if (exctx.getAppLog().isDebugEnabled()) {
exctx.getAppLog().debug("<send>: Enqueued event '" + eventValue
+ "' with no delay");
}
exctx.getInternalIOProcessor().addEvent(
new TriggerEvent(eventValue, TriggerEvent.SIGNAL_EVENT, params));
return;
}
} else {
// We know of no other
if (exctx.getAppLog().isWarnEnabled()) {
exctx.getAppLog().warn("<send>: Unavailable target - "
+ targetValue);
}
exctx.getInternalIOProcessor().addEvent(
new TriggerEvent(EVENT_ERR_SEND_TARGETUNAVAILABLE, TriggerEvent.ERROR_EVENT));
// short-circuit the EventDispatcher
return;
}
}
ctx.setLocal(getNamespacesKey(), null);
if (exctx.getAppLog().isDebugEnabled()) {
exctx.getAppLog().debug("<send>: Dispatching event '" + eventValue
+ "' to target '" + targetValue + "' of target type '"
+ typeValue + "' with suggested delay of " + wait
+ "ms");