You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by at...@apache.org on 2014/10/10 09:13:30 UTC

svn commit: r1630676 - in /commons/proper/scxml/trunk/src: main/java/org/apache/commons/scxml2/ main/java/org/apache/commons/scxml2/env/ main/java/org/apache/commons/scxml2/io/ main/java/org/apache/commons/scxml2/model/ test/java/org/apache/commons/scx...

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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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