final ErrorReporter errRep, final SCInstance scInstance,
final Log appLog, final Collection derivedEvents)
throws ModelException, SCXMLExpressionException {
// Send attributes evaluation
State parentState = getParentState();
Context ctx = scInstance.getContext(parentState);
ctx.setLocal(getNamespacesKey(), getNamespaces());
Evaluator eval = scInstance.getEvaluator();
// Most attributes of <send> are expressions so need to be
// evaluated before the EventDispatcher callback
Object hintsValue = null;
if (!SCXMLHelper.isStringEmpty(hints)) {
hintsValue = eval.eval(ctx, hints);
}
String targetValue = target;
if (!SCXMLHelper.isStringEmpty(target)) {
targetValue = (String) eval.eval(ctx, target);
if (SCXMLHelper.isStringEmpty(targetValue)
&& appLog.isWarnEnabled()) {
appLog.warn("<send>: target expression \"" + target
+ "\" evaluated to null or empty String");
}
}
String targettypeValue = targettype;
if (!SCXMLHelper.isStringEmpty(targettype)) {
targettypeValue = (String) eval.eval(ctx, targettype);
if (SCXMLHelper.isStringEmpty(targettypeValue)
&& appLog.isWarnEnabled()) {
appLog.warn("<send>: targettype expression \"" + targettype
+ "\" evaluated to null or empty String");
}
} else {
// must default to 'scxml' when unspecified
targettypeValue = TARGETTYPE_SCXML;
}
Map params = null;
if (!SCXMLHelper.isStringEmpty(namelist)) {
StringTokenizer tkn = new StringTokenizer(namelist);
params = new HashMap(tkn.countTokens());
while (tkn.hasMoreTokens()) {
String varName = tkn.nextToken();
Object varObj = ctx.get(varName);
if (varObj == null) {
//considered as a warning here
errRep.onError(ErrorConstants.UNDEFINED_VARIABLE,
varName + " = null", parentState);
}
params.put(varName, varObj);
}
}
long wait = parseDelay(appLog);
// Lets see if we should handle it ourselves
if (targettypeValue != null
&& targettypeValue.trim().equalsIgnoreCase(TARGETTYPE_SCXML)) {
if (SCXMLHelper.isStringEmpty(targetValue)) {
// TODO: Remove both short-circuit passes in v1.0
if (wait == 0L) {
if (appLog.isDebugEnabled()) {
appLog.debug("<send>: Enqueued event '" + event
+ "' with no delay");
}
derivedEvents.add(new TriggerEvent(event,
TriggerEvent.SIGNAL_EVENT, params));
return;
}
} else {
// We know of no other
if (appLog.isWarnEnabled()) {
appLog.warn("<send>: Unavailable target - "
+ targetValue);
}
derivedEvents.add(new TriggerEvent(
EVENT_ERR_SEND_TARGETUNAVAILABLE,
TriggerEvent.ERROR_EVENT));
// short-circuit the EventDispatcher
return;
}
}
ctx.setLocal(getNamespacesKey(), null);
if (appLog.isDebugEnabled()) {
appLog.debug("<send>: Dispatching event '" + event
+ "' to target '" + targetValue + "' of target type '"
+ targettypeValue + "' with suggested delay of " + wait
+ "ms");