Author: ate Date: Fri Oct 10 07:13:29 2014 New Revision: 1630676 URL: http://svn.apache.org/r1630676 Log: SCXML-210: align <send> action attributes support and handling with the latest specification: http://www.w3.org/TR/2014/WD-scxml-20140529/#send
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/EventDispatcher.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-03.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-04.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/wizard-02.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/invoked-02.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-initial-test.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-parallel-test.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-state-test.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-01.xml commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-02.xml Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/EventDispatcher.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/EventDispatcher.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/EventDispatcher.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/EventDispatcher.java Fri Oct 10 07:13:29 2014 @@ -40,7 +40,7 @@ public interface EventDispatcher { /** * Send this message to the target. * - * @param sendId The ID of the send message + * @param id The ID of the send message * @param target An expression returning the target location of the event * @param type The type of the Event I/O Processor that the event should * be dispatched to @@ -53,7 +53,7 @@ public interface EventDispatcher { * @param externalNodes The list of external nodes associated with * the <send> element. */ - void send(String sendId, String target, String type, + void send(String id, String target, String type, String event, Map<String, Object> params, Object hints, long delay, List<Node> externalNodes); Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java Fri Oct 10 07:13:29 2014 @@ -66,6 +66,12 @@ public class SCXMLSystemContext implemen private Context systemContext; /** + * The auto-generated next sessionId prefixed ID + * @see #generateSessionId() + */ + private long nextSessionSequenceId; + + /** * Initialize or replace systemContext * @param systemContext the system context to set */ @@ -87,6 +93,10 @@ public class SCXMLSystemContext implemen setSystemContext(systemContext); } + public String generateSessionId() { + return getContext().get(SESSIONID_KEY) + "-" + nextSessionSequenceId++; + } + @Override public void set(final String name, final Object value) { if (PROTECTED_NAMES.contains(name)) { Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java Fri Oct 10 07:13:29 2014 @@ -56,13 +56,13 @@ public final class SimpleDispatcher impl /** @see EventDispatcher#send(String,String,String,String,Map,Object,long,List) */ - public void send(final String sendId, final String target, + public void send(final String id, final String target, final String type, final String event, final Map<String, Object> params, final Object hints, final long delay, final List<Node> externalNodes) { if (log.isInfoEnabled()) { StringBuffer buf = new StringBuffer(); - buf.append("send ( sendId: ").append(sendId); + buf.append("send ( id: ").append(id); buf.append(", target: ").append(target); buf.append(", type: ").append(type); buf.append(", event: ").append(event); Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java Fri Oct 10 07:13:29 2014 @@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFac import org.apache.commons.scxml2.EventDispatcher; import org.apache.commons.scxml2.SCXMLExecutor; import org.apache.commons.scxml2.TriggerEvent; -import org.apache.commons.scxml2.model.ModelException; import org.w3c.dom.Node; /** @@ -100,14 +99,14 @@ public class SimpleScheduler implements /** @see EventDispatcher#send(String,String,String,String,Map,Object,long,List) */ - public void send(final String sendId, final String target, + public void send(final String id, final String target, final String type, final String event, final Map<String, Object> params, final Object hints, final long delay, final List<Node> externalNodes) { // Log callback if (log.isInfoEnabled()) { StringBuffer buf = new StringBuffer(); - buf.append("send ( sendId: ").append(sendId); + buf.append("send ( id: ").append(id); buf.append(", target: ").append(target); buf.append(", type: ").append(type); buf.append(", event: ").append(event); @@ -133,12 +132,12 @@ public class SimpleScheduler implements if (delay > 0L) { // Need to schedule this one Timer timer = new Timer(true); - timer.schedule(new DelayedEventTask(sendId, event, params), delay); - timers.put(sendId, timer); + timer.schedule(new DelayedEventTask(id, event, params), delay); + timers.put(id, timer); if (log.isDebugEnabled()) { log.debug("Scheduled event '" + event + "' with delay " + delay + "ms, as specified by <send> with id '" - + sendId + "'"); + + id + "'"); } } // else short-circuited by Send#execute() @@ -183,7 +182,7 @@ public class SimpleScheduler implements /** * The ID of the <send> element. */ - private String sendId; + private String id; /** * The event name. @@ -198,24 +197,24 @@ public class SimpleScheduler implements /** * Constructor. * - * @param sendId The ID of the send element. + * @param id The ID of the send element. * @param event The name of the event to be triggered. */ - DelayedEventTask(final String sendId, final String event) { - this(sendId, event, null); + DelayedEventTask(final String id, final String event) { + this(id, event, null); } /** * Constructor for events with payload. * - * @param sendId The ID of the send element. + * @param id The ID of the send element. * @param event The name of the event to be triggered. * @param payload The event payload, if any. */ - DelayedEventTask(final String sendId, final String event, + DelayedEventTask(final String id, final String event, final Map<String, Object> payload) { super(); - this.sendId = sendId; + this.id = id; this.event = event; this.payload = payload; } @@ -225,11 +224,11 @@ public class SimpleScheduler implements */ @Override public void run() { - timers.remove(sendId); + timers.remove(id); executor.addEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT, payload)); if (log.isDebugEnabled()) { log.debug("Fired event '" + event + "' as scheduled by " - + "<send> with id '" + sendId + "'"); + + "<send> with id '" + id + "'"); } } Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java Fri Oct 10 07:13:29 2014 @@ -271,11 +271,14 @@ public final class SCXMLReader { private static final String ATTR_AUTOFORWARD = "autoforward"; private static final String ATTR_COND = "cond"; private static final String ATTR_DELAY = "delay"; + private static final String ATTR_DELAYEXPR = "delayexpr"; private static final String ATTR_EVENT = "event"; + private static final String ATTR_EVENTEXPR = "eventexpr"; private static final String ATTR_EXMODE = "exmode"; private static final String ATTR_EXPR = "expr"; private static final String ATTR_HINTS = "hints"; private static final String ATTR_ID = "id"; + private static final String ATTR_IDLOCATION = "idlocation"; private static final String ATTR_INDEX = "index"; private static final String ATTR_INITIAL = "initial"; private static final String ATTR_ITEM = "item"; @@ -288,7 +291,9 @@ public final class SCXMLReader { private static final String ATTR_SRC = "src"; private static final String ATTR_SRCEXPR = "srcexpr"; private static final String ATTR_TARGET = "target"; + private static final String ATTR_TARGETEXPR = "targetexpr"; private static final String ATTR_TYPE = "type"; + private static final String ATTR_TYPEEXPR = "typeexpr"; private static final String ATTR_VERSION = "version"; //------------------------- PUBLIC API METHODS -------------------------// @@ -1756,13 +1761,58 @@ public final class SCXMLReader { } Send send = new Send(); + send.setId(readAV(reader, ATTR_ID)); + String attrValue = readAV(reader, ATTR_IDLOCATION); + if (attrValue != null) { + if (send.getId() != null) { + reportConflictingAttribute(reader, configuration, ELEM_SEND, ATTR_ID, ATTR_IDLOCATION); + } + else { + send.setIdlocation(attrValue); + } + } send.setDelay(readAV(reader, ATTR_DELAY)); + attrValue = readAV(reader, ATTR_DELAYEXPR); + if (attrValue != null) { + if (send.getDelay() != null) { + reportConflictingAttribute(reader, configuration, ELEM_SEND, ATTR_DELAY, ATTR_DELAYEXPR); + } + else { + send.setDelayexpr(attrValue); + } + } send.setEvent(readAV(reader, ATTR_EVENT)); + attrValue = readAV(reader, ATTR_EVENTEXPR); + if (attrValue != null) { + if (send.getEvent() != null) { + reportConflictingAttribute(reader, configuration, ELEM_SEND, ATTR_EVENT, ATTR_EVENTEXPR); + } + else { + send.setEventexpr(attrValue); + } + } send.setHints(readAV(reader, ATTR_HINTS)); send.setNamelist(readAV(reader, ATTR_NAMELIST)); - send.setSendid(readAV(reader, ATTR_SENDID)); send.setTarget(readAV(reader, ATTR_TARGET)); + attrValue = readAV(reader, ATTR_TARGETEXPR); + if (attrValue != null) { + if (send.getTarget() != null) { + reportConflictingAttribute(reader, configuration, ELEM_SEND, ATTR_TARGET, ATTR_TARGETEXPR); + } + else { + send.setTargetexpr(attrValue); + } + } send.setType(readAV(reader, ATTR_TYPE)); + attrValue = readAV(reader, ATTR_TYPEEXPR); + if (attrValue != null) { + if (send.getType() != null) { + reportConflictingAttribute(reader, configuration, ELEM_SEND, ATTR_TYPE, ATTR_TYPEEXPR); + } + else { + send.setTypeexpr(attrValue); + } + } readNamespaces(configuration, send); Node body = readNode(reader, configuration, XMLNS_SCXML, ELEM_SEND, new String [] {}); @@ -2251,6 +2301,41 @@ public final class SCXMLReader { } /** + * Report a conflicting attribute via the {@link XMLReporter} if available and the class + * {@link org.apache.commons.logging.Log}. + * + * @param reader The {@link XMLStreamReader} providing the SCXML document to parse. + * @param configuration The {@link Configuration} to use while parsing. + * @param element The element name. + * @param attr The attribute with which a conflict is detected. + * @param conflictingAttr The conflicting attribute + * + * @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}. + * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes + * errors in the SCXML document that may not be identified by the schema). + */ + private static void reportConflictingAttribute(final XMLStreamReader reader, final Configuration configuration, + final String element, final String attr, final String conflictingAttr) + throws XMLStreamException, ModelException { + + org.apache.commons.logging.Log log = LogFactory.getLog(SCXMLReader.class); + StringBuilder sb = new StringBuilder(); + sb.append("Ignoring <").append(element).append("> attribute \"").append(conflictingAttr) + .append("\" which conflicts with already defined attribute \"").append(attr) + .append("\" at ").append(reader.getLocation()); + if (!configuration.isSilent() && log.isWarnEnabled()) { + log.warn(sb.toString()); + } + if (configuration.isStrict()) { + throw new ModelException(sb.toString()); + } + XMLReporter reporter = configuration.reporter; + if (reporter != null) { + reporter.report(sb.toString(), "COMMONS_SCXML", null, reader.getLocation()); + } + } + + /** * Push any new namespace declarations on the configuration namespaces map. * * @param reader The {@link XMLStreamReader} providing the SCXML document to parse. Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java Fri Oct 10 07:13:29 2014 @@ -158,11 +158,14 @@ public class SCXMLWriter { private static final String ATTR_AUTOFORWARD = "autoforward"; private static final String ATTR_COND = "cond"; private static final String ATTR_DELAY = "delay"; + private static final String ATTR_DELAYEXPR = "delayexpr"; private static final String ATTR_EVENT = "event"; + private static final String ATTR_EVENTEXPR = "eventexpr"; private static final String ATTR_EXMODE = "exmode"; private static final String ATTR_EXPR = "expr"; private static final String ATTR_HINTS = "hints"; private static final String ATTR_ID = "id"; + private static final String ATTR_IDLOCATION = "idlocation"; private static final String ATTR_INDEX = "index"; private static final String ATTR_INITIAL = "initial"; private static final String ATTR_ITEM = "item"; @@ -175,7 +178,9 @@ public class SCXMLWriter { private static final String ATTR_SRC = "src"; private static final String ATTR_SRCEXPR = "srcexpr"; private static final String ATTR_TARGET = "target"; + private static final String ATTR_TARGETEXPR = "targetexpr"; private static final String ATTR_TYPE = "type"; + private static final String ATTR_TYPEEXPR = "typeexpr"; private static final String ATTR_VERSION = "version"; //------------------------- STATIC MEMBERS -------------------------// @@ -915,11 +920,16 @@ public class SCXMLWriter { throws XMLStreamException { writer.writeStartElement(XMLNS_SCXML, ELEM_SEND); - writeAV(writer, ATTR_SENDID, send.getSendid()); + writeAV(writer, ATTR_ID, send.getId()); + writeAV(writer, ATTR_IDLOCATION, send.getIdlocation()); writeAV(writer, ATTR_EVENT, send.getEvent()); + writeAV(writer, ATTR_EVENTEXPR, send.getEventexpr()); writeAV(writer, ATTR_TARGET, send.getTarget()); + writeAV(writer, ATTR_TARGETEXPR, send.getTargetexpr()); writeAV(writer, ATTR_TYPE, send.getType()); + writeAV(writer, ATTR_TYPEEXPR, send.getTypeexpr()); writeAV(writer, ATTR_DELAY, send.getDelay()); + writeAV(writer, ATTR_DELAYEXPR, send.getDelayexpr()); writeAV(writer, ATTR_NAMELIST, send.getNamelist()); writeAV(writer, ATTR_HINTS, send.getHints()); Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java Fri Oct 10 07:13:29 2014 @@ -27,9 +27,12 @@ import org.apache.commons.scxml2.ActionE import org.apache.commons.scxml2.Context; import org.apache.commons.scxml2.Evaluator; import org.apache.commons.scxml2.SCXMLExpressionException; +import org.apache.commons.scxml2.SCXMLSystemContext; import org.apache.commons.scxml2.TriggerEvent; import org.apache.commons.scxml2.semantics.ErrorConstants; import org.w3c.dom.Node; +import org.w3c.dom.Text; +import org.w3c.dom.CharacterData; /** * The class in this SCXML object model that corresponds to the @@ -73,25 +76,45 @@ public class Send extends Action impleme /** * The ID of the send message. */ - private String sendid; + private String id; /** - * An expression returning the target location of the event. + * Path expression evaluating to a location within a previously defined XML data tree. + */ + private String idlocation; + + /** + * The target location of the event. */ private String target; + + /** + * An expression specifying the target location of the event. + */ + private String targetexpr; + /** - * The type of the Event I/O Processor that the event. - * should be dispatched to + * The type of the Event I/O Processor that the event should be dispatched to. */ private String type; /** - * The event is dispatched after the delay interval elapses. + * An expression defining the type of the Event I/O Processor that the event should be dispatched to. + */ + private String typeexpr; + + /** + * The delay the event is dispatched after. */ private String delay; /** + * An expression defining the delay the event is dispatched after. + */ + private String delayexpr; + + /** * The data containing information which may be used by the * implementing platform to configure the event processor. */ @@ -113,6 +136,11 @@ public class Send extends Action impleme private String event; /** + * An expression defining the type of event being generated. + */ + private String eventexpr; + + /** * Constructor. */ public Send() { @@ -121,6 +149,21 @@ public class Send extends Action impleme } /** + * @return the idlocation + */ + public String getIdlocation() { + return idlocation; + } + + /** + * Set the idlocation expression + * @param idlocation The idlocation expression + */ + public void setIdlocation(final String idlocation) { + this.idlocation = idlocation; + } + + /** * Get the delay. * * @return Returns the delay. @@ -139,6 +182,21 @@ public class Send extends Action impleme } /** + * @return The delay expression + */ + public String getDelayexpr() { + return delayexpr; + } + + /** + * Set the delay expression + * @param delayexpr The delay expression to set + */ + public void setDelayexpr(final String delayexpr) { + this.delayexpr = delayexpr; + } + + /** * Get the list of external namespaced child nodes. * * @return List Returns the list of externalnodes. @@ -186,19 +244,19 @@ public class Send extends Action impleme /** * Get the identifier for this <send> element. * - * @return String Returns the sendid. + * @return String Returns the id. */ - public final String getSendid() { - return sendid; + public final String getId() { + return id; } /** * Set the identifier for this <send> element. * - * @param sendid The sendid to set. + * @param id The id to set. */ - public final void setSendid(final String sendid) { - this.sendid = sendid; + public final void setId(final String id) { + this.id = id; } /** @@ -220,6 +278,21 @@ public class Send extends Action impleme } /** + * @return The target expression + */ + public String getTargetexpr() { + return targetexpr; + } + + /** + * Set the target expression + * @param targetexpr The target expression to set + */ + public void setTargetexpr(final String targetexpr) { + this.targetexpr = targetexpr; + } + + /** * Get the type for this <send> element. * * @return String Returns the type. @@ -238,6 +311,21 @@ public class Send extends Action impleme } /** + * @return The type expression + */ + public String getTypeexpr() { + return typeexpr; + } + + /** + * Sets the type expression + * @param typeexpr The type expression to set + */ + public void setTypeexpr(final String typeexpr) { + this.typeexpr = typeexpr; + } + + /** * Get the event to send. * * @param event The event to set. @@ -256,6 +344,21 @@ public class Send extends Action impleme } /** + * @return The event expression + */ + public String getEventexpr() { + return eventexpr; + } + + /** + * Sets the event expression + * @param eventexpr The event expression to set + */ + public void setEventexpr(final String eventexpr) { + this.eventexpr = eventexpr; + } + + /** * {@inheritDoc} */ @Override @@ -271,27 +374,43 @@ public class Send extends Action impleme if (hints != null) { hintsValue = eval.eval(ctx, hints); } + if (id == null) { + id = ((SCXMLSystemContext)exctx.getGlobalContext().getParent()).generateSessionId(); + if (idlocation != null) { + Node location = eval.evalLocation(ctx, idlocation); + if (location != null) { + setNodeValue(location, id); + } + else { + throw new ModelException("<send>: idlocation does not point to a <data> node"); + } + } + } String targetValue = target; - if (target != null) { - targetValue = (String) eval.eval(ctx, target); + if (targetValue == null && targetexpr != null) { + targetValue = (String) eval.eval(ctx, targetexpr); if ((targetValue == null || targetValue.trim().length() == 0) && exctx.getAppLog().isWarnEnabled()) { - exctx.getAppLog().warn("<send>: target expression \"" + target + exctx.getAppLog().warn("<send>: target expression \"" + targetexpr + "\" evaluated to null or empty String"); } } - String typeValue; - if (type != null) { - typeValue = (String) eval.eval(ctx, type); + String typeValue = type; + if (typeValue == null && typeexpr != null) { + typeValue = (String) eval.eval(ctx, typeexpr); if ((typeValue == null || typeValue.trim().length() == 0) && exctx.getAppLog().isWarnEnabled()) { - exctx.getAppLog().warn("<send>: type expression \"" + type + exctx.getAppLog().warn("<send>: type expression \"" + typeexpr + "\" evaluated to null or empty String"); } - } else { + } + if (typeValue == null) { // must default to 'scxml' when unspecified typeValue = TYPE_SCXML; } + else if (!TYPE_SCXML.equals(typeValue) && typeValue.trim().equalsIgnoreCase(TYPE_SCXML)) { + typeValue = TYPE_SCXML; + } Map<String, Object> params = null; if (namelist != null) { StringTokenizer tkn = new StringTokenizer(namelist); @@ -308,24 +427,30 @@ public class Send extends Action impleme } } long wait = 0L; - if (delay != null) { + String delayString = delay; + if (delayString == null && delayexpr != null) { Object delayValue = eval.eval(ctx, delay); if (delayValue != null) { - String delayString = delayValue.toString(); - wait = parseDelay(delayString, exctx.getAppLog()); + delayString = delayValue.toString(); } } + if (delayString != null) { + wait = parseDelay(delayString, exctx.getAppLog()); + } String eventValue = event; - if (event != null) { - eventValue = (String) eval.eval(ctx, event); + if (eventValue == null && eventexpr != null) { + eventValue = (String) eval.eval(ctx, eventexpr); if ((eventValue == null || eventValue.trim().length() == 0) && exctx.getAppLog().isWarnEnabled()) { - exctx.getAppLog().warn("<send>: event expression \"" + event - + "\" evaluated to null or empty String"); + throw new SCXMLExpressionException("<send>: event expression \"" + eventexpr + + "\" evaluated to null or empty String"); } } // Lets see if we should handle it ourselves - if (typeValue != null - && typeValue.trim().equalsIgnoreCase(TYPE_SCXML)) { + if (typeValue != null && TYPE_SCXML.equals(typeValue)) { + if (eventValue == null) { + // event required when type == http://www.w3.org/TR/scxml/#SCXMLEventProcessor + throw new ModelException("Event parameter is required for <send> with type=\"scxml\""); + } if (targetValue == null || targetValue.trim().length() == 0) { // TODO: Remove both short-circuit passes in v1.0 if (wait == 0L) { @@ -357,7 +482,7 @@ public class Send extends Action impleme + "ms"); } // Else, let the EventDispatcher take care of it - exctx.getEventDispatcher().send(sendid, targetValue, typeValue, eventValue, + exctx.getEventDispatcher().send(id, targetValue, typeValue, eventValue, params, hintsValue, wait, externalNodes); } @@ -400,5 +525,42 @@ public class Send extends Action impleme } return wait; } + + /** + * Set node value, depending on its type, from a String. + * + * @param node A Node whose value is to be set + * @param value The new value + */ + private void setNodeValue(final Node node, final String value) { + switch(node.getNodeType()) { + case Node.ATTRIBUTE_NODE: + node.setNodeValue(value); + break; + case Node.ELEMENT_NODE: + //remove all text children + if (node.hasChildNodes()) { + Node child = node.getFirstChild(); + while (child != null) { + if (child.getNodeType() == Node.TEXT_NODE) { + node.removeChild(child); + } + child = child.getNextSibling(); + } + } + //create a new text node and append + Text txt = node.getOwnerDocument().createTextNode(value); + node.appendChild(txt); + break; + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: + ((CharacterData) node).setData(value); + break; + default: + String err = "Trying to set value of a strange Node type: " + + node.getNodeType(); + throw new IllegalArgumentException(err); + } + } } Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java Fri Oct 10 07:13:29 2014 @@ -109,7 +109,7 @@ public class WizardsTest { private static final long serialVersionUID = 1L; // If you change this, you must also change testWizard02Sample() int callback = 0; - public void send(String sendId, String target, String type, + public void send(String id, String target, String type, String event, Map<String, Object> params, Object hints, long delay, List<Node> externalNodes) { int i = ((Integer) params.get("aValue")).intValue(); Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-03.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-03.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-03.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-03.xml Fri Oct 10 07:13:29 2014 @@ -37,7 +37,7 @@ <onentry> <cs:var name="one" expr="Data(rootdata,'root/one')"/> <cs:var name="two" expr="Data(rootdata,'root/two')"/> - <send event="'event.bar'" namelist="one two"/> + <send event="event.bar" namelist="one two"/> </onentry> <transition event="event.bar" cond="_event.data.one + _event.data.two eq 3" Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-04.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-04.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-04.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/eventdata-04.xml Fri Oct 10 07:13:29 2014 @@ -28,7 +28,7 @@ </datamodel> <onentry> - <send event="'event.bar'" namelist="one two" delay="'100ms'"/> + <send event="event.bar" namelist="one two" delay="100ms"/> </onentry> <transition event="event.bar"> <log label="'simulatedUser'" expr="_event.data.one + ', ' + _event.data.two"/> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/wizard-02.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/wizard-02.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/wizard-02.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/wizard-02.xml Fri Oct 10 07:13:29 2014 @@ -25,7 +25,7 @@ default to be chosen as "scxml". This will cause the first transition to state2 to be immediately followed. --> - <send event="'event2'" /> + <send event="event2" /> </onentry> <transition event="event2" target="state2"/> <transition event="event3" target="state3"/> @@ -39,7 +39,7 @@ EventDispatcher implementation. See testWizard02Sample() in WizardsTest (org.apache.commons.scxml test package) --> - <send namelist="aValue" type="'foo'" /> + <send namelist="aValue" type="foo" /> </onentry> <transition event="event1" target="state1"/> <transition event="event3" target="state3"/> @@ -48,7 +48,7 @@ <state id="state3"> <onentry> <cs:var name="aValue" expr="3"/> - <send namelist="aValue" type="'foo'" /> + <send namelist="aValue" type="foo" /> </onentry> <transition event="event1" target="state1"/> <transition event="event2" target="state2"/> @@ -57,7 +57,7 @@ <state id="state4"> <onentry> <cs:var name="aValue" expr="4"/> - <send namelist="aValue" type="'foo'" /> + <send namelist="aValue" type="foo" /> </onentry> <transition event="event1" target="state1"/> <transition event="event2" target="state2"/> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/invoked-02.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/invoked-02.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/invoked-02.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/invoked-02.xml Fri Oct 10 07:13:29 2014 @@ -21,7 +21,7 @@ <state id="state1"> <onentry> - <send event="'invoked.next'" /> + <send event="invoked.next" /> </onentry> <transition event="invoked.next" target="state2" /> </state> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java Fri Oct 10 07:13:29 2014 @@ -171,7 +171,7 @@ public class SCXMLReaderTest { List<Action> actions = ten2twenty.getActions(); Assert.assertEquals(1, actions.size()); Send send = (Send) actions.get(0); - Assert.assertEquals("send1", send.getSendid()); + Assert.assertEquals("send1", send.getId()); /* Serialize scxmlAsString = serialize(scxml); Assert.assertNotNull(scxmlAsString); Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-initial-test.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-initial-test.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-initial-test.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-initial-test.xml Fri Oct 10 07:13:29 2014 @@ -35,9 +35,9 @@ </if> <cs:var name="drink" expr="'water'" /> <cs:var name="eat" expr="'flies'" /> - <send sendid="send12345" target="freddy" type="frog" + <send id="send12345" target="freddy" type="frog" event="croak" namelist="drink eat" hints="'h2o bzz'" - delay="1000+500" /> + delayexpr="1000+500" /> <cancel sendId="send12345"/> <log expr="leaving" label="entry001" /> <raise event="event.test"/> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-parallel-test.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-parallel-test.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-parallel-test.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-parallel-test.xml Fri Oct 10 07:13:29 2014 @@ -34,9 +34,9 @@ </if> <cs:var name="drink" expr="'water'" /> <cs:var name="eat" expr="'flies'" /> - <send sendid="send12345" target="freddy" type="frog" + <send id="send12345" target="freddy" type="frog" event="croak" namelist="drink eat" hints="'h2o bzz'" - delay="1000+500" /> + delayexpr="1000+500" /> <cancel sendId="send12345"/> <log expr="leaving" label="entry001" /> <raise event="event.test"/> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-state-test.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-state-test.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-state-test.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/actions-state-test.xml Fri Oct 10 07:13:29 2014 @@ -34,9 +34,9 @@ </if> <cs:var name="drink" expr="'water'" /> <cs:var name="eat" expr="'flies'" /> - <send sendid="send12345" target="freddy" type="frog" + <send id="send12345" target="freddy" type="frog" event="croak" namelist="drink eat" hints="'h2o bzz'" - delay="1000+500" /> + delayexpr="1000+500" /> <cancel sendId="send12345"/> <log expr="leaving" label="entry001" /> <raise event="event.test"/> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-01.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-01.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-01.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-01.xml Fri Oct 10 07:13:29 2014 @@ -21,8 +21,8 @@ <state id="ten"> <transition event="done.state.ten" target="twenty"> - <send sendid="send1" delay="'0'" - target="'http://localhost:8080/VXMLInterpreter'" type="'v3'" + <send id="send1" delay="0s" + target="http://localhost:8080/VXMLInterpreter" type="v3" xmlns:v3="http://foo.bar.com/vxml3" xmlns:test="http://my.test.namespace"> <v3:form id="Confirm"> Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-02.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-02.xml?rev=1630676&r1=1630675&r2=1630676&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-02.xml (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/send-02.xml Fri Oct 10 07:13:29 2014 @@ -25,49 +25,49 @@ the state "seventy", then hop over and end up in "ninety" --> <state id="ten"> <onentry> - <send event="'done.state.' + 'ten'" /> + <send eventexpr="'done.state.' + 'ten'" /> </onentry> <transition event="done.state.ten" target="twenty" /> </state> <state id="twenty"> <onentry> - <send event="'done.state.twenty'" type="'scxml'" /> + <send event="done.state.twenty" type="scxml" /> </onentry> <transition event="done.state.twenty" target="thirty" /> </state> <state id="thirty"> <onentry> - <send event="'done.state.thirty'" type="' sCxML '" /> + <send event="done.state.thirty" type=" sCxML " /> </onentry> <transition event="done.state.thirty" target="forty" /> </state> <state id="forty"> <onentry> - <send event="'done.state.forty'" type=" " target=" " /> + <send event="done.state.forty" type=" " target=" " /> </onentry> <transition event="done.state.forty" target="fifty" /> </state> <state id="fifty"> <onentry> - <send event="'done.state.fifty'" target="' '" /> + <send event="done.state.fifty" target=" " /> </onentry> <transition event="done.state.fifty" target="sixty" /> </state> <state id="sixty"> <onentry> - <send event="'done.state.sixty'" type="'scxml'" target=" " /> + <send event="done.state.sixty" type="scxml" target=" " /> </onentry> <transition event="done.state.sixty" target="seventy" /> </state> <state id="seventy"> <onentry> - <send event="'done.state.seventy'" type="'scxml'" target="'foo'" /> + <send event="done.state.seventy" type="scxml" target="foo" /> </onentry> <!-- This transition should not be followed since