You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ra...@apache.org on 2006/03/24 02:12:43 UTC

svn commit: r388312 [1/2] - in /jakarta/commons/sandbox/scxml/trunk/src: main/java/org/apache/commons/scxml/ main/java/org/apache/commons/scxml/env/ main/java/org/apache/commons/scxml/env/faces/ main/java/org/apache/commons/scxml/env/jexl/ main/java/or...

Author: rahul
Date: Thu Mar 23 17:12:40 2006
New Revision: 388312

URL: http://svn.apache.org/viewcvs?rev=388312&view=rev
Log:
Partial implementation for the datamodel section [1] (Section 5) of the latest W3C SCXML WD [2].

A <datamodel> tag may contain any number of <data> elements. Each data element can contain an XML data tree (a degenerate flavor exists matching the <var> element functionality as well). The XML data trees may be fetched from an external source (not yet implemented) or inline (implemented). The datamodel may be "distributed" within the document per author's convenience, that is, it may be a child of the <scxml> element or the <state> element. Visibility of data is structured like blocks in a procedural language (nested blocks -> nested states). A builtin function Data() is available to examine the Nodes within a XML data tree (for use with JEXL and EL expressions). Accompanied by a starter set of test cases and a couple of sample documents for illustration.

Also aligning SCXML Context to JEXL Context (provide a getVars() instead of a iterator()).

[1] http://www.w3.org/TR/scxml/#data
[2] http://www.w3.org/TR/2006/WD-scxml-20060124/

Added:
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java   (with props)
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java   (with props)
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml   (with props)
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml   (with props)
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/model/DatamodelTest.java   (with props)
Modified:
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Builtin.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Context.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Evaluator.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCInstance.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLExecutor.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLHelper.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/SimpleContext.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/faces/SessionContext.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlContext.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlEvaluator.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/ELEvaluator.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/RootContext.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLDigester.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Assign.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Send.java
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/TransitionTarget.java
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/SCXMLTestHelper.java
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/RootContextTest.java
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
    jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/model/ModelTestSuite.java

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Builtin.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Builtin.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Builtin.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Builtin.java Thu Mar 23 17:12:40 2006
@@ -20,7 +20,14 @@
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.commons.scxml.model.TransitionTarget;
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * Implementations of builtin functions defined by the SCXML
@@ -52,6 +59,84 @@
             }
         }
         return false;
+    }
+
+    /**
+     * Implements the Data() function for Commons SCXML documents, that
+     * can be used to obtain a node from one of the XML data trees.
+     * Manifests within "location" attribute of &lt;assign&gt; element,
+     * for Commons JEXL and Commons EL based documents.
+     *
+     * @param data The context Node, though the method accepts an Object
+     *             so error is reported by Commons SCXML, rather
+     *             than the underlying expression language.
+     * @param path The XPath expression.
+     * @return The first node matching the path, or null if no nodes match.
+     */
+    public static Node dataNode(final Object data, final String path) {
+        if (data == null || !(data instanceof Node)) {
+            Log log = LogFactory.getLog(Builtin.class);
+            log.error("Data(): Cannot evaluate an XPath expression"
+                + " in the absence of a context Node, null returned");
+            return null;
+        }
+        Node dataNode = (Node) data;
+        NodeList result = null;
+        try {
+            result = XPathAPI.selectNodeList(dataNode, path);
+        } catch (TransformerException te) {
+            Log log = LogFactory.getLog(Builtin.class);
+            log.error(te.getMessage(), te);
+            return null;
+        }
+        int length = result.getLength();
+        if (length == 0) {
+            Log log = LogFactory.getLog(Builtin.class);
+            log.warn("Data(): No nodes matching the XPath expression \""
+                + path + "\", returning null");
+            return null;
+        } else {
+            if (length > 1) {
+                Log log = LogFactory.getLog(Builtin.class);
+                log.warn("Data(): Multiple nodes matching XPath expression"
+                    + path + "\", returning first");
+            }
+            return result.item(0);
+        }
+    }
+
+    /**
+     * A variant of the Data() function for Commons SCXML documents,
+     * coerced to a Double, a Long or a String, whichever succeeds,
+     * in that order.
+     * Manifests within rvalue expressions in the document,
+     * for Commons JEXL and Commons EL based documents..
+     *
+     * @param data The context Node, though the method accepts an Object
+     *             so error is reported by Commons SCXML, rather
+     *             than the underlying expression language.
+     * @param path The XPath expression.
+     * @return The first node matching the path, coerced to a String, or null
+     *         if no nodes match.
+     */
+    public static Object data(final Object data, final String path) {
+        Object retVal = null;
+        String strVal = SCXMLHelper.getNodeValue(dataNode(data, path));
+        // try as a double
+        try {
+            double d = Double.parseDouble(strVal);
+            retVal = new Double(d);
+        } catch (NumberFormatException notADouble) {
+            // else as a long
+            try {
+                long l = Long.parseLong(strVal);
+                retVal = new Long(l);
+            } catch (NumberFormatException notALong) {
+                // fallback to string
+                retVal = strVal;
+            }
+        }
+        return retVal;
     }
 
 }

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Context.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Context.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Context.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Context.java Thu Mar 23 17:12:40 2006
@@ -17,7 +17,7 @@
  */
 package org.apache.commons.scxml;
 
-import java.util.Iterator;
+import java.util.Map;
 
 /**
  * A Context or &quot;scope&quot; for storing variables; usually tied to
@@ -61,13 +61,13 @@
     boolean has(String name);
 
     /**
-     * Get an Iterator over all variables in this Context.
+     * Get the Map of all variables in this Context.
      *
-     * @return Local entries iterator (Map.Entry)
-     * To get parent entries, call getParent().iterator().
+     * @return Local variable entries Map
+     * To get variables in parent Context, call getParent().getVars().
      * @see #getParent()
      */
-    Iterator iterator();
+    Map getVars();
 
     /**
      * Clear this Context.

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Evaluator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Evaluator.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Evaluator.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/Evaluator.java Thu Mar 23 17:12:40 2006
@@ -17,6 +17,8 @@
  */
 package org.apache.commons.scxml;
 
+import org.w3c.dom.Node;
+
 /**
  * Interface for a component that may be used by the SCXML engines to
  * evaluate the expressions within the SCXML document.
@@ -32,24 +34,41 @@
      * @return a result of the evaluation
      * @throws SCXMLExpressionException A malformed exception
      */
-    Object eval(Context ctx, String expr) throws SCXMLExpressionException;
+    Object eval(Context ctx, String expr)
+    throws SCXMLExpressionException;
 
     /**
-     * Create a new child context.
+     * Evaluate a condition.
+     * Manifests as "cond" attributes of &lt;transition&gt;,
+     * &lt;if&gt; and &lt;elseif&gt; elements.
      *
-     * @param parent parent context
-     * @return new child context
+     * @param ctx variable context
+     * @param expr expression
+     * @return true/false
+     * @throws SCXMLExpressionException A malformed exception
      */
-    Context newContext(Context parent);
+    Boolean evalCond(Context ctx, String expr)
+    throws SCXMLExpressionException;
 
     /**
-     * Evaluate a condition.
+     * Evaluate a location that returns a Node within an XML data tree.
+     * Manifests as "location" attributes of &lt;assign&gt; element.
      *
      * @param ctx variable context
      * @param expr expression
-     * @return true/false
+     * @return The location node.
      * @throws SCXMLExpressionException A malformed exception
      */
-    Boolean evalCond(Context ctx, String expr) throws SCXMLExpressionException;
+    Node evalLocation(Context ctx, String expr)
+    throws SCXMLExpressionException;
+
+    /**
+     * Create a new child context.
+     *
+     * @param parent parent context
+     * @return new child context
+     */
+    Context newContext(Context parent);
 
 }
+

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCInstance.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCInstance.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCInstance.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCInstance.java Thu Mar 23 17:12:40 2006
@@ -22,6 +22,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.scxml.model.Datamodel;
 import org.apache.commons.scxml.model.History;
 import org.apache.commons.scxml.model.TransitionTarget;
 
@@ -144,6 +145,8 @@
             } else {
                 context = evaluator.newContext(getContext(parent));
             }
+            Datamodel datamodel = transitionTarget.getDatamodel();
+            SCXMLHelper.cloneDatamodel(datamodel, context, evaluator, null);
             contexts.put(transitionTarget, context);
         }
         return context;

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLExecutor.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLExecutor.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLExecutor.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLExecutor.java Thu Mar 23 17:12:40 2006
@@ -23,6 +23,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml.model.Datamodel;
 import org.apache.commons.scxml.model.History;
 import org.apache.commons.scxml.model.ModelException;
 import org.apache.commons.scxml.model.SCXML;
@@ -176,7 +177,17 @@
      */
     public void reset() throws ModelException {
         // Reset all variable contexts
-        scInstance.getRootContext().reset();
+        Context rootCtx = scInstance.getRootContext();
+        rootCtx.reset();
+        // Clone root datamodel
+        if (stateMachine == null) {
+            log.error(ERR_NO_STATE_MACHINE);
+            throw new ModelException(ERR_NO_STATE_MACHINE);
+        } else {
+            Datamodel rootdm = stateMachine.getDatamodel();
+            SCXMLHelper.cloneDatamodel(rootdm, rootCtx,
+                scInstance.getEvaluator(), log);
+        }
         // all states and parallels, only states have variable contexts
         for (Iterator i = stateMachine.getTargets().values().iterator();
                 i.hasNext();) {
@@ -185,6 +196,11 @@
                 Context context = scInstance.lookupContext(tt);
                 if (context != null) {
                     context.reset();
+                    Datamodel dm = tt.getDatamodel();
+                    if (dm != null) {
+                        SCXMLHelper.cloneDatamodel(dm, context,
+                            scInstance.getEvaluator(), log);
+                    }
                 }
             } else if (tt instanceof History) {
                 scInstance.reset((History) tt);
@@ -439,6 +455,12 @@
         scInstance.getRootContext().setLocal("_ALL_STATES",
             SCXMLHelper.getAncestorClosure(currentStatus.getStates(), null));
     }
+
+    /**
+     * SCXMLExecutor put into motion without setting a model (state machine).
+     */
+    private static final String ERR_NO_STATE_MACHINE =
+        "SCXMLExecutor: State machine not set";
 
 }
 

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLHelper.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLHelper.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLHelper.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/SCXMLHelper.java Thu Mar 23 17:12:40 2006
@@ -20,14 +20,22 @@
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml.model.Data;
+import org.apache.commons.scxml.model.Datamodel;
 import org.apache.commons.scxml.model.Parallel;
 import org.apache.commons.scxml.model.Path;
 import org.apache.commons.scxml.model.State;
 import org.apache.commons.scxml.model.Transition;
 import org.apache.commons.scxml.model.TransitionTarget;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
 
 /**
  * Helper class, all methods static final.
@@ -330,6 +338,133 @@
             }
         }
         return false;
+    }
+
+    /**
+     * 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
+     */
+    public static 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();
+                //Logger.logln(Logger.E, err);
+                throw new IllegalArgumentException(err);
+        }
+    }
+
+    /**
+     * Retrieve a DOM node value as a string depending on its type.
+     *
+     * @param node A node to be retreived
+     * @return The value as a string
+     */
+    public static String getNodeValue(final Node node) {
+        String result = "";
+        if (node == null) {
+            return result;
+        }
+        switch(node.getNodeType()) {
+            case Node.ATTRIBUTE_NODE:
+                result = node.getNodeValue();
+                break;
+            case Node.ELEMENT_NODE:
+                if (node.hasChildNodes()) {
+                    Node child = node.getFirstChild();
+                    StringBuffer buf = new StringBuffer();
+                    while (child != null) {
+                        if (child.getNodeType() == Node.TEXT_NODE) {
+                            buf.append(((CharacterData) child).getData());
+                        }
+                        child = child.getNextSibling();
+                    }
+                    result = buf.toString();
+                }
+                break;
+            case Node.TEXT_NODE:
+            case Node.CDATA_SECTION_NODE:
+                result = ((CharacterData) node).getData();
+                break;
+            default:
+                String err = "Trying to get value of a strange Node type: "
+                    + node.getNodeType();
+                //Logger.logln(Logger.W, err );
+                throw new IllegalArgumentException(err);
+        }
+        return result.trim();
+    }
+
+    /**
+     * Clone data model.
+     *
+     * @param ctx The context to clone to.
+     * @param datamodel The datamodel to clone.
+     * @param evaluator The expression evaluator.
+     * @param log The error log.
+     */
+    public static void cloneDatamodel(final Datamodel datamodel,
+            final Context ctx, final Evaluator evaluator,
+            final Log log) {
+        if (datamodel == null) {
+            return;
+        }
+        List data = datamodel.getData();
+        if (data == null) {
+            return;
+        }
+        for (Iterator iter = data.iterator(); iter.hasNext();) {
+            Data datum = (Data) iter.next();
+            Node datumNode = datum.getNode();
+            Node valueNode = null;
+            if (datumNode != null) {
+                valueNode = datumNode.cloneNode(true);
+            }
+            // prefer "src" over "expr" over "inline"
+            if (!SCXMLHelper.isStringEmpty(datum.getSrc())) {
+                ctx.setLocal(datum.getName(), valueNode);
+            } else if (!SCXMLHelper.isStringEmpty(datum.
+                    getExpr())) {
+                Object value = null;
+                try {
+                    value = evaluator.eval(ctx, datum.getExpr());
+                } catch (SCXMLExpressionException see) {
+                    if (log != null) {
+                        log.error(see.getMessage(), see);
+                    } else {
+                        Log defaultLog = LogFactory.getLog(SCXMLHelper.class);
+                        defaultLog.error(see.getMessage(), see);
+                    }
+                }
+                ctx.setLocal(datum.getName(), value);
+            } else {
+                ctx.setLocal(datum.getName(), valueNode);
+            }
+        }
     }
 
     /**

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/SimpleContext.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/SimpleContext.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/SimpleContext.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/SimpleContext.java Thu Mar 23 17:12:40 2006
@@ -18,7 +18,6 @@
 package org.apache.commons.scxml.env;
 
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
@@ -131,16 +130,6 @@
     }
 
     /**
-     * Get an Iterator over all variables in this Context.
-     *
-     * @return Iterator The Iterator over all variables in this Context
-     * @see org.apache.commons.scxml.Context#iterator()
-     */
-    public Iterator iterator() {
-        return vars.entrySet().iterator();
-    }
-
-    /**
      * Clear this Context.
      *
      * @see org.apache.commons.scxml.Context#reset()
@@ -185,11 +174,11 @@
     }
 
     /**
-     * Get the variables map.
+     * Get the Map of all local variables in this Context.
      *
      * @return Returns the vars.
      */
-    protected Map getVars() {
+    public Map getVars() {
         return vars;
     }
 

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/faces/SessionContext.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/faces/SessionContext.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/faces/SessionContext.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/faces/SessionContext.java Thu Mar 23 17:12:40 2006
@@ -17,7 +17,6 @@
  */
 package org.apache.commons.scxml.env.faces;
 
-import java.util.Iterator;
 import java.util.Map;
 
 import javax.faces.context.FacesContext;
@@ -92,19 +91,6 @@
      */
     public boolean has(final String name) {
         return (sessionMap.containsKey(name) || getVars().containsKey(name));
-    }
-
-    /**
-     * Get the Iterator.
-     *
-     * @return Iterator The read-write variables in this Context.
-     * @see org.apache.commons.scxml.Context#iterator()
-     */
-    public Iterator iterator() {
-        // The reason why this method body exists is to emphasize that
-        // read-only (scoped/managed beans) variables are not included in
-        // this Iterator.
-        return super.iterator();
     }
 
 }

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlContext.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlContext.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlContext.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlContext.java Thu Mar 23 17:12:40 2006
@@ -59,7 +59,7 @@
     }
 
     /**
-     * Get the variables map.
+     * Set the variables map.
      *
      * @param vars The new variables map.
      *
@@ -74,7 +74,7 @@
     /**
      * Get the variables map.
      *
-     * @return Returns the vars.
+     * @return Map The variables map.
      *
      * @see org.apache.commons.jexl.JexlContext#getVars()
      * @see org.apache.commons.scxml.env.SimpleContext#getVars()

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlEvaluator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlEvaluator.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlEvaluator.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jexl/JexlEvaluator.java Thu Mar 23 17:12:40 2006
@@ -28,6 +28,7 @@
 import org.apache.commons.scxml.Context;
 import org.apache.commons.scxml.Evaluator;
 import org.apache.commons.scxml.SCXMLExpressionException;
+import org.w3c.dom.Node;
 
 /**
  * Evaluator implementation enabling use of JEXL expressions in
@@ -42,6 +43,8 @@
 
     /** Pattern for recognizing the SCXML In() special predicate. */
     private static Pattern inFct = Pattern.compile("In\\(");
+    /** Pattern for recognizing the Commons SCXML Data() builtin function. */
+    private static Pattern dataFct = Pattern.compile("Data\\(");
 
     /** Constructor. */
     public JexlEvaluator() {
@@ -69,6 +72,8 @@
         try {
             String evalExpr = inFct.matcher(expr).
                 replaceAll("_builtin.isMember(_ALL_STATES, ");
+            evalExpr = dataFct.matcher(evalExpr).
+                replaceAll("_builtin.data(");
             exp = ExpressionFactory.createExpression(evalExpr);
             return exp.evaluate(getEffectiveContext(jexlCtx));
         } catch (Exception e) {
@@ -77,20 +82,33 @@
     }
 
     /**
-     * Create a new child context.
-     *
-     * @param parent parent context
-     * @return new child context
-     * @see Evaluator#newContext(Context)
+     * @see Evaluator#evalCond(Context, String)
      */
-    public Context newContext(final Context parent) {
-        return new JexlContext(parent);
+    public Boolean evalCond(final Context ctx, final String expr)
+    throws SCXMLExpressionException {
+        JexlContext jexlCtx = null;
+        if (ctx instanceof JexlContext) {
+            jexlCtx = (JexlContext) ctx;
+        } else {
+            throw new SCXMLExpressionException(ERR_CTX_TYPE);
+        }
+        Expression exp = null;
+        try {
+            String evalExpr = inFct.matcher(expr).
+                replaceAll("_builtin.isMember(_ALL_STATES, ");
+            evalExpr = dataFct.matcher(evalExpr).
+                replaceAll("_builtin.data(");
+            exp = ExpressionFactory.createExpression(evalExpr);
+            return (Boolean) exp.evaluate(getEffectiveContext(jexlCtx));
+        } catch (Exception e) {
+            throw new SCXMLExpressionException(e);
+        }
     }
 
     /**
-     * @see Evaluator#evalCond(Context, String)
+     * @see Evaluator#evalLocation(Context, String)
      */
-    public Boolean evalCond(final Context ctx, final String expr)
+    public Node evalLocation(final Context ctx, final String expr)
     throws SCXMLExpressionException {
         JexlContext jexlCtx = null;
         if (ctx instanceof JexlContext) {
@@ -102,11 +120,26 @@
         try {
             String evalExpr = inFct.matcher(expr).
                 replaceAll("_builtin.isMember(_ALL_STATES, ");
+            evalExpr = dataFct.matcher(evalExpr).
+                replaceFirst("_builtin.dataNode(");
+            evalExpr = dataFct.matcher(evalExpr).
+                replaceAll("_builtin.data(");
             exp = ExpressionFactory.createExpression(evalExpr);
-            return (Boolean) exp.evaluate(getEffectiveContext(jexlCtx));
+            return (Node) exp.evaluate(getEffectiveContext(jexlCtx));
         } catch (Exception e) {
             throw new SCXMLExpressionException(e);
         }
+    }
+
+    /**
+     * Create a new child context.
+     *
+     * @param parent parent context
+     * @return new child context
+     * @see Evaluator#newContext(Context)
+     */
+    public Context newContext(final Context parent) {
+        return new JexlContext(parent);
     }
 
     /**

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/ELEvaluator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/ELEvaluator.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/ELEvaluator.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/ELEvaluator.java Thu Mar 23 17:12:40 2006
@@ -33,6 +33,7 @@
 import org.apache.commons.scxml.Context;
 import org.apache.commons.scxml.Evaluator;
 import org.apache.commons.scxml.SCXMLExpressionException;
+import org.w3c.dom.Node;
 
 /**
  * Evaluator implementation enabling use of EL expressions in
@@ -47,6 +48,8 @@
     private FunctionMapper functionMapper = new BuiltinFunctionWrapper();
     /** Pattern for recognizing the SCXML In() special predicate. */
     private static Pattern inFct = Pattern.compile("In\\(");
+    /** Pattern for recognizing the Commons SCXML Data() builtin function. */
+    private static Pattern dataFct = Pattern.compile("Data\\(");
 
     /** The expression evaluator implementation for the JSP/EL environment. */
     private ExpressionEvaluator ee = null;
@@ -90,20 +93,34 @@
     }
 
     /**
-     * Create a new child context.
-     *
-     * @param parent parent context
-     * @return new child context
-     * @see Evaluator#newContext(Context)
+     * @see Evaluator#evalCond(Context, String)
      */
-    public Context newContext(final Context parent) {
-        return new ELContext(parent);
+    public Boolean evalCond(final Context ctx, final String expr)
+    throws SCXMLExpressionException {
+        VariableResolver vr = null;
+        if (ctx instanceof VariableResolver) {
+            vr = (VariableResolver) ctx;
+        } else {
+            vr = new ContextWrapper(ctx);
+        }
+        try {
+            String evalExpr = inFct.matcher(expr).
+                replaceAll("In(_ALL_STATES, ");
+            Boolean rslt = (Boolean) ee.evaluate(evalExpr, Boolean.class,
+                vr, functionMapper);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug(expr + " = " + String.valueOf(rslt));
+            }
+            return rslt;
+        } catch (ELException e) {
+            throw new SCXMLExpressionException(e);
+        }
     }
 
     /**
-     * @see Evaluator#evalCond(Context, String)
+     * @see Evaluator#evalLocation(Context, String)
      */
-    public Boolean evalCond(final Context ctx, final String expr)
+    public Node evalLocation(final Context ctx, final String expr)
     throws SCXMLExpressionException {
         VariableResolver vr = null;
         if (ctx instanceof VariableResolver) {
@@ -114,7 +131,9 @@
         try {
             String evalExpr = inFct.matcher(expr).
                 replaceAll("In(_ALL_STATES, ");
-            Boolean rslt = (Boolean) ee.evaluate(evalExpr, Boolean.class,
+            evalExpr = dataFct.matcher(evalExpr).
+                replaceFirst("LData(");
+            Node rslt = (Node) ee.evaluate(evalExpr, Node.class,
                 vr, functionMapper);
             if (LOG.isDebugEnabled()) {
                 LOG.debug(expr + " = " + String.valueOf(rslt));
@@ -126,6 +145,17 @@
     }
 
     /**
+     * Create a new child context.
+     *
+     * @param parent parent context
+     * @return new child context
+     * @see Evaluator#newContext(Context)
+     */
+    public Context newContext(final Context parent) {
+        return new ELContext(parent);
+    }
+
+    /**
      * A Context wrapper that implements VariableResolver.
      */
     static class ContextWrapper implements VariableResolver {
@@ -166,6 +196,26 @@
                     LOG.error("resolving isMember(Set, String)", e);
                 } catch (NoSuchMethodException e) {
                     LOG.error("resolving isMember(Set, String)", e);
+                }
+            } else if (localName.equals("Data")) {
+                // rvalue in expressions, coerce to String
+                Class[] attrs = new Class[] {Object.class, String.class};
+                try {
+                    return Builtin.class.getMethod("data", attrs);
+                } catch (SecurityException e) {
+                    LOG.error("resolving data(Node, String)", e);
+                } catch (NoSuchMethodException e) {
+                    LOG.error("resolving data(Node, String)", e);
+                }
+            } else if (localName.equals("LData")) {
+                // lvalue in expressions, retain as Node
+                Class[] attrs = new Class[] {Object.class, String.class};
+                try {
+                    return Builtin.class.getMethod("dataNode", attrs);
+                } catch (SecurityException e) {
+                    LOG.error("resolving data(Node, String)", e);
+                } catch (NoSuchMethodException e) {
+                    LOG.error("resolving data(Node, String)", e);
                 }
             }
             return null;

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/RootContext.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/RootContext.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/RootContext.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/jsp/RootContext.java Thu Mar 23 17:12:40 2006
@@ -17,8 +17,6 @@
  */
 package org.apache.commons.scxml.env.jsp;
 
-import java.util.Iterator;
-
 import javax.servlet.jsp.JspContext;
 import javax.servlet.jsp.el.ELException;
 import javax.servlet.jsp.el.VariableResolver;
@@ -92,17 +90,6 @@
             }
         }
         return exists;
-    }
-
-    /**
-     * Get the Iterator.
-     *
-     * @see org.apache.commons.scxml.Context#iterator()
-     */
-    public Iterator iterator() {
-        // The reason why this method body exists is to emphasize that
-        // read-only (JSP) variables are not included in the Iterator
-        return super.iterator();
     }
 
     /**

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLDigester.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLDigester.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLDigester.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLDigester.java Thu Mar 23 17:12:40 2006
@@ -24,6 +24,8 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.commons.digester.Digester;
@@ -41,6 +43,8 @@
 import org.apache.commons.scxml.model.Action;
 import org.apache.commons.scxml.model.Assign;
 import org.apache.commons.scxml.model.Cancel;
+import org.apache.commons.scxml.model.Data;
+import org.apache.commons.scxml.model.Datamodel;
 import org.apache.commons.scxml.model.Else;
 import org.apache.commons.scxml.model.ElseIf;
 import org.apache.commons.scxml.model.Executable;
@@ -61,6 +65,7 @@
 import org.apache.commons.scxml.model.Var;
 
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 import org.xml.sax.Attributes;
@@ -381,6 +386,13 @@
     /** &lt;onexit&gt; child element. */
     private static final String XPF_ONEX = "/onexit";
 
+    // Datamodel section
+    /** &lt;datamodel&gt; child element. */
+    private static final String XPF_DM = "/datamodel";
+
+    /** Individual &lt;data&gt; elements. */
+    private static final String XPF_DATA = "/data";
+
     // Initial
     /** &lt;initial&gt; child element. */
     private static final String XPF_INI = "/initial";
@@ -530,6 +542,9 @@
         scxmlRules.add(XP_SM, new ObjectCreateRule(SCXML.class));
         scxmlRules.add(XP_SM, new SetPropertiesRule());
 
+        //// Datamodel at document root i.e. <scxml> datamodel
+        addDatamodelRules(XP_SM + XPF_DM, scxmlRules, scxml, pr);
+
         //// States
         // Level one states
         addStateRules(XP_SM_ST, scxmlRules, scxml, pr, 0);
@@ -571,7 +586,8 @@
             final PathResolver pr, final int parent) {
         scxmlRules.add(xp, new ObjectCreateRule(State.class));
         addStatePropertiesRules(xp, scxmlRules, pr);
-        addInitialRule(xp + XPF_INI, scxmlRules, pr, scxml);
+        addDatamodelRules(xp + XPF_DM, scxmlRules, scxml, pr);
+        addInitialRules(xp + XPF_INI, scxmlRules, pr, scxml);
         addHistoryRules(xp + XPF_HIST, scxmlRules, pr, scxml);
         addParentRule(xp, scxmlRules, parent);
         addTransitionRules(xp + XPF_TR, scxmlRules, "addTransition");
@@ -612,6 +628,31 @@
     }
 
     /**
+     * Add Digester rules for all &lt;datamodel&gt; elements.
+     *
+     * @param xp The Digester style XPath expression of the parent
+     *           XML element
+     * @param scxmlRules The rule set to be used for digestion
+     * @param pr The PathResolver
+     * @param scxml The parent SCXML document (or null)
+     */
+    private static void addDatamodelRules(final String xp,
+            final ExtendedBaseRules scxmlRules, final SCXML scxml,
+            final PathResolver pr) {
+        scxmlRules.add(xp, new ObjectCreateRule(Datamodel.class));
+        scxmlRules.add(xp + XPF_DATA, new ObjectCreateRule(Data.class));
+        scxmlRules.add(xp + XPF_DATA, new SetPropertiesRule());
+        scxmlRules.add(xp + XPF_DATA, new SetNextRule("addData"));
+        try {
+            scxmlRules.add(xp + XPF_DATA, new ParseDataRule(pr));
+        } catch (ParserConfigurationException pce) {
+            log.error("Error registering rule for parsing <data>"
+                + " element content", pce);
+        }
+        scxmlRules.add(xp, new SetNextRule("setDatamodel"));
+    }
+
+    /**
      * Add Digester rules for all &lt;initial&gt; elements.
      *
      * @param xp The Digester style XPath expression of the parent
@@ -620,7 +661,7 @@
      * @param pr The PathResolver
      * @param scxml The parent SCXML document (or null)
      */
-    private static void addInitialRule(final String xp,
+    private static void addInitialRules(final String xp,
             final ExtendedBaseRules scxmlRules, final PathResolver pr,
             final SCXML scxml) {
         scxmlRules.add(xp, new ObjectCreateRule(Initial.class));
@@ -771,8 +812,8 @@
         try {
             scxmlRules.add(xp, new ParseExternalContentRule());
         } catch (ParserConfigurationException pce) {
-            log.error("Error parsing <send> element content",
-                pce);
+            log.error("Error registering rule for parsing <send>"
+                + " element content", pce);
         }
     }
 
@@ -1126,6 +1167,91 @@
     }
 
     /**
+     * Custom digestion rule for parsing bodies of &lt;data&gt; elements.
+     *
+     */
+    public static class ParseDataRule extends NodeCreateRule {
+
+        /**
+         * The PathResolver used to resolve the src attribute to the
+         * SCXML document it points to.
+         * @see PathResolver
+         */
+        private PathResolver pr;
+
+        /**
+         * The "src" attribute, retained to check if body content is legal.
+         */
+        private String src;
+
+        /**
+         * The "expr" attribute, retained to check if body content is legal.
+         */
+        private String expr;
+
+        /**
+         * The XML tree for this data, parse as a Node, obtained from
+         * either the "src" or the "expr" attributes.
+         */
+        private Node attrNode;
+
+        /**
+         * Constructor.
+         *
+         * @param pr The <code>PathResolver</code>
+         * @throws ParserConfigurationException A JAXP configuration error
+         */
+        public ParseDataRule(final PathResolver pr)
+        throws ParserConfigurationException {
+            super();
+            this.pr = pr;
+        }
+
+        /**
+         * @see Rule#begin(String, String, Attributes)
+         */
+        public final void begin(final String namespace, final String name,
+                final Attributes attributes) throws Exception {
+            super.begin(namespace, name, attributes);
+            src = attributes.getValue("src");
+            expr = attributes.getValue("expr");
+            if (!SCXMLHelper.isStringEmpty(src)) {
+                String path = null;
+                if (pr == null) {
+                    path = src;
+                } else {
+                    path = pr.resolvePath(src);
+                }
+                try {
+                    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.
+                        newInstance();
+                    DocumentBuilder db = dbFactory.newDocumentBuilder();
+                    attrNode = db.parse(path);
+                } catch (Throwable t) { // you read that correctly
+                    log.error(t.getMessage(), t);
+                }
+                return;
+            }
+        }
+
+        /**
+         * @see Rule#end(String, String)
+         */
+        public final void end(final String namespace, final String name) {
+            Node bodyNode = (Node) getDigester().pop();
+            Data data = ((Data) getDigester().peek());
+            // Prefer "src" over "expr", "expr" over child nodes
+            // "expr" can only be evaluated at execution time
+            if (!SCXMLHelper.isStringEmpty(src)) {
+                data.setNode(attrNode);
+            } else  if (SCXMLHelper.isStringEmpty(expr)) {
+                // both "src" and "expr" are empty
+                data.setNode(bodyNode);
+            }
+        }
+    }
+
+    /**
      * Custom digestion rule for external sources, that is, the src attribute of
      * the &lt;state&gt; element.
      *
@@ -1174,10 +1300,9 @@
             try {
                 externalSCXML = (SCXML) externalSrcDigester.parse(path);
             } catch (Exception e) {
-                log.error(null, e);
+                log.error(e.getMessage(), e);
             }
-            // 2) Adopt the children
-            // TODO - Clarify spec; Priority: High
+            // 2) Adopt the children and datamodel
             if (externalSCXML == null) {
                 return;
             }
@@ -1192,6 +1317,7 @@
             for (int i = 0; i < ids.length; i++) {
                 s.addChild((State) children.get(ids[i]));
             }
+            s.setDatamodel(externalSCXML.getDatamodel());
         }
     }
 }

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java Thu Mar 23 17:12:40 2006
@@ -17,17 +17,33 @@
  */
 package org.apache.commons.scxml.io;
 
+import java.io.StringWriter;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
 
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml.SCXMLHelper;
 import org.apache.commons.scxml.model.Action;
 import org.apache.commons.scxml.model.Assign;
 import org.apache.commons.scxml.model.Cancel;
+import org.apache.commons.scxml.model.Data;
+import org.apache.commons.scxml.model.Datamodel;
 import org.apache.commons.scxml.model.Else;
 import org.apache.commons.scxml.model.ElseIf;
 import org.apache.commons.scxml.model.Exit;
+import org.apache.commons.scxml.model.ExternalContent;
 import org.apache.commons.scxml.model.History;
 import org.apache.commons.scxml.model.If;
 import org.apache.commons.scxml.model.Initial;
@@ -41,6 +57,7 @@
 import org.apache.commons.scxml.model.Transition;
 import org.apache.commons.scxml.model.TransitionTarget;
 import org.apache.commons.scxml.model.Var;
+import org.w3c.dom.Node;
 
 /**
  * Utility class for serializing the Commons SCXML Java object
@@ -53,6 +70,8 @@
 
     /** The indent to be used while serializing an SCXML object. */
     private static final String INDENT = " ";
+    /** The JAXP transformer. */
+    private static final Transformer XFORMER = getTransformer();
 
     /**
      * Serialize this SCXML object (primarily for debugging).
@@ -62,10 +81,23 @@
      * @return String The serialized SCXML
      */
     public static String serialize(final SCXML scxml) {
-        StringBuffer b = new StringBuffer("<scxml xmlns=\"").append(
-                scxml.getXmlns()).append("\" version=\"").append(
-                scxml.getVersion()).append("\" initialstate=\"").append(
-                scxml.getInitialstate()).append("\">\n");
+        StringBuffer b =
+            new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n").
+                append("<scxml xmlns=\"").append(scxml.getXmlns()).
+                append("\" version=\"").append(scxml.getVersion()).
+                append("\" initialstate=\"").append(scxml.getInitialstate()).
+                append("\">\n");
+        if (XFORMER == null) {
+            org.apache.commons.logging.Log log = LogFactory.
+                getLog(SCXMLSerializer.class);
+            log.warn("SCXMLSerializer: DOM serialization pertinent to"
+                + " the document will be skipped since a suitable"
+                + " JAXP Transformer could not be instantiated.");
+        }
+        Datamodel dm = scxml.getDatamodel();
+        if (dm != null) {
+            serializeDatamodel(b, dm, INDENT);
+        }
         Map s = scxml.getStates();
         Iterator i = s.keySet().iterator();
         while (i.hasNext()) {
@@ -99,6 +131,10 @@
         if (h != null) {
             serializeHistory(b, h, indent + INDENT);
         }
+        Datamodel dm = s.getDatamodel();
+        if (dm != null) {
+            serializeDatamodel(b, dm, indent + INDENT);
+        }
         serializeOnEntry(b, s, indent + INDENT);
         Map t = s.getTransitions();
         Iterator i = t.keySet().iterator();
@@ -106,7 +142,7 @@
             List et = (List) t.get(i.next());
             for (int len = 0; len < et.size(); len++) {
                 serializeTransition(b, (Transition) et.get(len), indent
-                        + INDENT);
+                    + INDENT);
             }
         }
         Parallel p = s.getParallel();
@@ -198,7 +234,7 @@
     public static void serializeTransition(final StringBuffer b,
             final Transition t, final String indent) {
         b.append(indent).append("<transition event=\"").append(t.getEvent())
-                .append("\" cond=\"").append(t.getCond()).append("\">\n");
+            .append("\" cond=\"").append(t.getCond()).append("\">\n");
         boolean exit = serializeActions(b, t.getActions(), indent + INDENT);
         if (!exit) {
             serializeTarget(b, t, indent + INDENT);
@@ -231,6 +267,51 @@
     }
 
     /**
+     * Serialize this Datamodel object.
+     *
+     * @param b The buffer to append the serialization to
+     * @param dm The Datamodel to be serialized
+     * @param indent The indent for this XML element
+     */
+    public static void serializeDatamodel(final StringBuffer b,
+            final Datamodel dm, final String indent) {
+        List data = dm.getData();
+        if (data != null && data.size() > 0) {
+            b.append(indent).append("<datamodel>\n");
+            if (XFORMER == null) {
+                b.append(indent).append(INDENT).
+                    append("<!-- Body content was not serialized -->\n");
+                b.append(indent).append("</datamodel>\n");
+                return;
+            }
+            for (Iterator iter = data.iterator(); iter.hasNext();) {
+                Data datum = (Data) iter.next();
+                Node dataNode = datum.getNode();
+                if (dataNode != null) {
+                    StringWriter out = new StringWriter();
+                    try {
+                        Source input = new DOMSource(dataNode);
+                        Result output = new StreamResult(out);
+                        XFORMER.transform(input, output);
+                    } catch (TransformerException te) {
+                        org.apache.commons.logging.Log log = LogFactory.
+                            getLog(SCXMLSerializer.class);
+                        log.error(te.getMessage(), te);
+                        b.append(indent).append(INDENT).
+                            append("<!-- Data content not serialized -->\n");
+                    }
+                    b.append(indent).append(INDENT).append(out.toString());
+                } else {
+                    b.append(indent).append(INDENT).append("<data name=\"").
+                        append(datum.getName()).append("\" expr=\"").
+                        append(datum.getExpr()).append("\" />\n");
+                }
+            }
+            b.append(indent).append("</datamodel>\n");
+        }
+    }
+
+    /**
      * Serialize this OnEntry object.
      *
      * @param b The buffer to append the serialization to
@@ -288,9 +369,19 @@
                                 "\"/>\n");
             } else if (a instanceof Assign) {
                 Assign asn = (Assign) a;
-                b.append(indent).append("<assign name=\"")
-                        .append(asn.getName()).append("\" expr=\"")
-                        .append(asn.getExpr()).append("\"/>\n");
+                b.append(indent).append("<assign");
+                if (!SCXMLHelper.isStringEmpty(asn.getLocation())) {
+                    b.append(" location=\"").append(asn.getLocation());
+                    if (!SCXMLHelper.isStringEmpty(asn.getSrc())) {
+                        b.append("\" src=\"").append(asn.getSrc());
+                    } else {
+                        b.append("\" expr=\"").append(asn.getExpr());
+                    }
+                } else {
+                    b.append(" name=\"").append(asn.getName()).
+                        append("\" expr=\"").append(asn.getExpr());
+                }
+                b.append("\"/>\n");
             } else if (a instanceof Send) {
                 serializeSend(b, (Send) a, indent);
             } else if (a instanceof Cancel) {
@@ -344,15 +435,40 @@
             .append(send.getNamelist()).append("\" delay=\"")
             .append(send.getDelay()).append("\" events=\"")
             .append(send.getEvent()).append("\" hints=\"")
-            .append(send.getHints()).append("\">\n");
-        /* TODO - Serialize body content
-        try {
-            b.append(send.getBodyContent());
-        } catch (IOException ioe) {
-            log.error("Failed to serialize external nodes for <send>", ioe);
+            .append(send.getHints()).append("\">\n")
+            .append(getBodyContent(send))
+            .append(indent).append("</send>\n");
+    }
+
+    /**
+     * Return serialized body of <code>ExternalContent</code>.
+     *
+     * @param externalContent The model element containing the body content
+     * @return String The serialized body content
+     */
+    public static final String getBodyContent(
+            final ExternalContent externalContent) {
+        StringBuffer buf = new StringBuffer();
+        List externalNodes = externalContent.getExternalNodes();
+        if (externalNodes.size() > 0 && XFORMER == null) {
+            buf.append("<!-- Body content was not serialized -->\n");
+            return buf.toString();
+        }
+        for (int i = 0; i < externalNodes.size(); i++) {
+            Source input = new DOMSource((Node) externalNodes.get(i));
+            StringWriter out = new StringWriter();
+            Result output = new StreamResult(out);
+            try {
+                XFORMER.transform(input, output);
+            } catch (TransformerException te) {
+                org.apache.commons.logging.Log log = LogFactory.
+                    getLog(SCXMLSerializer.class);
+                log.error(te.getMessage(), te);
+                buf.append("<!-- Not all body content was serialized -->");
+            }
+            buf.append(out.toString()).append("\n");
         }
-        */
-        b.append(indent).append("</send>\n");
+        return buf.toString();
     }
 
     /**
@@ -370,16 +486,6 @@
         b.append(indent).append("</if>\n");
     }
 
-    /*
-     * Private methods.
-     */
-    /**
-     * Discourage instantiation since this is a utility class.
-     */
-    private SCXMLSerializer() {
-        super();
-    }
-
     /**
      * Serialize properties of TransitionTarget which are element attributes.
      *
@@ -401,4 +507,36 @@
         }
     }
 
+    /**
+     * Get a <code>Transformer</code> instance.
+     *
+     * @return Transformer The <code>Transformer</code> instance.
+     */
+    private static Transformer getTransformer() {
+        Transformer transformer = null;
+        Properties outputProps = new Properties();
+        outputProps.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        outputProps.put(OutputKeys.STANDALONE, "no");
+        outputProps.put(OutputKeys.INDENT, "yes");
+        try {
+            TransformerFactory tfFactory = TransformerFactory.newInstance();
+            transformer = tfFactory.newTransformer();
+            transformer.setOutputProperties(outputProps);
+        } catch (Throwable t) {
+            return null;
+        }
+        return transformer;
+    }
+
+    /*
+     * Private methods.
+     */
+    /**
+     * Discourage instantiation since this is a utility class.
+     */
+    private SCXMLSerializer() {
+        super();
+    }
+
 }
+

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Assign.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Assign.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Assign.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Assign.java Thu Mar 23 17:12:40 2006
@@ -26,7 +26,9 @@
 import org.apache.commons.scxml.EventDispatcher;
 import org.apache.commons.scxml.SCInstance;
 import org.apache.commons.scxml.SCXMLExpressionException;
+import org.apache.commons.scxml.SCXMLHelper;
 import org.apache.commons.scxml.TriggerEvent;
+import org.w3c.dom.Node;
 
 /**
  * The class in this SCXML object model that corresponds to the
@@ -42,6 +44,17 @@
     private String name;
 
     /**
+     * Left hand side expression evaluating to a location within
+     * a previously defined XML data tree.
+     */
+    private String location;
+
+    /**
+     * The source where the new XML instance for this location exists.
+     */
+    private String src;
+
+    /**
      * Expression evaluating to the new value of the variable.
      */
     private String expr;
@@ -54,6 +67,24 @@
     }
 
     /**
+     * Get the variable to be assigned a new value.
+     *
+     * @return Returns the name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Get the variable to be assigned a new value.
+     *
+     * @param name The name to set.
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
      * Get the expr that will evaluate to the new value.
      *
      * @return Returns the expr.
@@ -72,21 +103,39 @@
     }
 
     /**
-     * Get the variable to be assigned a new value.
+     * Get the location for a previously defined XML data tree.
      *
-     * @return Returns the name.
+     * @return Returns the location.
      */
-    public String getName() {
-        return name;
+    public String getLocation() {
+        return location;
     }
 
     /**
-     * Get the variable to be assigned a new value.
+     * Set the location for a previously defined XML data tree.
      *
-     * @param name The name to set.
+     * @param location The location.
      */
-    public void setName(final String name) {
-        this.name = name;
+    public void setLocation(final String location) {
+        this.location = location;
+    }
+
+    /**
+     * Get the source where the new XML instance for this location exists.
+     *
+     * @return Returns the source.
+     */
+    public String getSrc() {
+        return src;
+    }
+
+    /**
+     * Set the source where the new XML instance for this location exists.
+     *
+     * @param src The source.
+     */
+    public void setSrc(final String src) {
+        this.src = src;
     }
 
     /**
@@ -99,15 +148,48 @@
         State parentState = getParentState();
         Context ctx = scInstance.getContext(parentState);
         Evaluator eval = scInstance.getEvaluator();
-        if (!ctx.has(name)) {
-            errRep.onError(ErrorReporter.UNDEFINED_VARIABLE, name
-                    + " = null", parentState);
+        // "location" gets preference over "name"
+        if (!SCXMLHelper.isStringEmpty(location)) {
+            Node oldNode = eval.evalLocation(ctx, location);
+            if (oldNode != null) {
+                //// rvalue may be ...
+                // a Node, if so, import it at location
+                Node newNode = null;
+                try {
+                    newNode = eval.evalLocation(ctx, expr);
+                    if (newNode != null) {
+                        // adopt children, possible spec clarification needed
+                        Node importedNode = oldNode.getOwnerDocument().
+                            importNode(newNode, true);
+                        for (Node child = importedNode.getFirstChild();
+                            child != null; child = child.getNextSibling()) {
+                                oldNode.appendChild(child);
+                        }
+                    }
+                } catch (SCXMLExpressionException see) {
+                    // or something else, stuff toString() into lvalue
+                    Object valueObject = eval.eval(ctx, expr);
+                    SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
+                }
+                TriggerEvent ev = new TriggerEvent(name + ".change",
+                    TriggerEvent.CHANGE_EVENT);
+                derivedEvents.add(ev);
+            } else {
+                appLog.error("<assign>: location does not point to"
+                    + " a <data> node");
+            }
         } else {
-            Object varObj = eval.eval(ctx, expr);
-            ctx.set(name, varObj);
-            TriggerEvent ev = new TriggerEvent(name + ".change",
+            // lets try "name" (usage as in Sep '05 WD, useful with <var>)
+            if (!ctx.has(name)) {
+                errRep.onError(ErrorReporter.UNDEFINED_VARIABLE, name
+                    + " = null", parentState);
+            } else {
+                Object varObj = eval.eval(ctx, expr);
+                ctx.set(name, varObj);
+                TriggerEvent ev = new TriggerEvent(name + ".change",
                     TriggerEvent.CHANGE_EVENT);
-            derivedEvents.add(ev);
+                derivedEvents.add(ev);
+            }
         }
     }
 

Added: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java?rev=388312&view=auto
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java (added)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java Thu Mar 23 17:12:40 2006
@@ -0,0 +1,133 @@
+/*
+ *
+ *   Copyright 2006 The Apache Software Foundation.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.commons.scxml.model;
+
+import org.w3c.dom.Node;
+
+/**
+ * The class in this SCXML object model that corresponds to the SCXML
+ * &lt;data&gt; child element of the &lt;datamodel&gt; element.
+ *
+ */
+public class Data {
+
+    /**
+     * The name of this data instance, that is used as its identifier.
+     */
+    private String name;
+
+    /**
+     * The URL to get the XML data tree from.
+     */
+    private String src;
+
+    /**
+     * The expression that evaluates to the value of this data instance.
+     */
+    private String expr;
+
+    /**
+     * The child XML data tree, parsed as a Node, cloned per execution
+     * instance.
+     */
+    private Node node;
+
+    /**
+     * Constructor.
+     */
+    public Data() {
+        this.name = null;
+        this.src = null;
+        this.expr = null;
+        this.node = null;
+    }
+
+    /**
+     * Get the name.
+     *
+     * @return String The name.
+     */
+    public final String getName() {
+        return name;
+    }
+
+    /**
+     * Set the name.
+     *
+     * @param name The name.
+     */
+    public final void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Get the URL where the XML data tree resides.
+     *
+     * @return String The URL.
+     */
+    public final String getSrc() {
+        return src;
+    }
+
+    /**
+     * Set the URL where the XML data tree resides.
+     *
+     * @param src The source URL.
+     */
+    public final void setSrc(final String src) {
+        this.src = src;
+    }
+
+    /**
+     * Get the expression that evaluates to the value of this data instance.
+     *
+     * @return String The expression.
+     */
+    public final String getExpr() {
+        return expr;
+    }
+
+    /**
+     * Set the expression that evaluates to the value of this data instance.
+     *
+     * @param expr The expression.
+     */
+    public final void setExpr(final String expr) {
+        this.expr = expr;
+    }
+
+    /**
+     * Get the XML data tree.
+     *
+     * @return Node The XML data tree, parsed as a <code>Node</code>.
+     */
+    public final Node getNode() {
+        return node;
+    }
+
+    /**
+     * Set the XML data tree.
+     *
+     * @param node The XML data tree, parsed as a <code>Node</code>.
+     */
+    public final void setNode(final Node node) {
+        this.node = node;
+    }
+
+}
+

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Data.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java?rev=388312&view=auto
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java (added)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java Thu Mar 23 17:12:40 2006
@@ -0,0 +1,64 @@
+/*
+ *
+ *   Copyright 2006 The Apache Software Foundation.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.commons.scxml.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class in this SCXML object model that corresponds to the SCXML
+ * &lt;datamodel&gt; element.
+ *
+ */
+public class Datamodel {
+
+   /**
+    * The set of &lt;data&gt; elements, parsed as Elements, that are
+    * children of this &lt;datamodel&gt; element.
+    */
+   private List data;
+
+   /**
+    * Constructor.
+    */
+   public Datamodel() {
+       this.data = new ArrayList();
+   }
+
+   /**
+    * Get all the data children of this datamodel.
+    *
+    * @return Returns the data.
+    */
+   public final List getData() {
+       return data;
+   }
+
+   /**
+    * Add a Data.
+    *
+    * @param datum The data child to be added.
+    */
+   public final void addData(final Data datum) {
+       if (datum != null) {
+           data.add(datum);
+       }
+   }
+
+}
+

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Datamodel.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java Thu Mar 23 17:12:40 2006
@@ -57,6 +57,13 @@
     private transient String initialstate;
 
     /**
+     * Optional property holding the data model for this SCXML document.
+     * This gets merged with the root context and potentially hides any
+     * (namesake) variables in the root context.
+     */
+    private Datamodel datamodel;
+
+    /**
      * The immediate child states of this SCXML document root.
      */
     private Map states;
@@ -91,6 +98,24 @@
      */
     public final void setInitialState(final State initialState) {
         this.initialState = initialState;
+    }
+
+    /**
+     * Get the data model placed at document root.
+     *
+     * @return Returns the data model.
+     */
+    public final Datamodel getDatamodel() {
+        return datamodel;
+    }
+
+    /**
+     * Set the data model at document root.
+     *
+     * @param datamodel The Datamodel to set.
+     */
+    public final void setDatamodel(final Datamodel datamodel) {
+        this.datamodel = datamodel;
     }
 
     /**

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Send.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Send.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Send.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/Send.java Thu Mar 23 17:12:40 2006
@@ -17,8 +17,6 @@
  */
 package org.apache.commons.scxml.model;
 
-//import java.io.IOException;
-//import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -35,10 +33,6 @@
 import org.apache.commons.scxml.SCXMLExpressionException;
 import org.apache.commons.scxml.SCXMLHelper;
 
-//import org.apache.xml.serialize.OutputFormat;
-//import org.apache.xml.serialize.XMLSerializer;
-//import org.w3c.dom.Element;
-
 /**
  * The class in this SCXML object model that corresponds to the
  * &lt;send&gt; SCXML element.
@@ -249,24 +243,6 @@
     public final String getEvent() {
         return event;
     }
-
-    /**
-     * Return serialized external nodes.
-     *
-     * @throws IOException Serialization failed
-     *
-    public final String getBodyContent() throws IOException {
-        StringBuffer buf = new StringBuffer();
-        for (int i = 0; i < externalNodes.size(); i++) {
-            StringWriter out = new StringWriter();
-            XMLSerializer output = new XMLSerializer(out, format);
-            output.setNamespaces(true);
-            output.serialize((Element) externalNodes.get(i));
-            buf.append(out.toString()).append("\n");
-        }
-        return buf.toString();
-    }
-    */
 
     /**
      * {@inheritDoc}

Modified: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/TransitionTarget.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/TransitionTarget.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/TransitionTarget.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/model/TransitionTarget.java Thu Mar 23 17:12:40 2006
@@ -43,6 +43,11 @@
     private OnExit onExit;
 
     /**
+     * Optional property holding the data model for this transition target.
+     */
+    private Datamodel datamodel;
+
+    /**
      * The parent of this transition target (may be null, if the parent
      * is the SCXML document root).
      */
@@ -112,6 +117,24 @@
      */
     public final void setOnExit(final OnExit onExit) {
         this.onExit = onExit;
+    }
+
+    /**
+     * Get the data model for this transition target.
+     *
+     * @return Returns the data model.
+     */
+    public final Datamodel getDatamodel() {
+        return datamodel;
+    }
+
+    /**
+     * Set the data model for this transition target.
+     *
+     * @param datamodel The Datamodel to set.
+     */
+    public final void setDatamodel(final Datamodel datamodel) {
+        this.datamodel = datamodel;
     }
 
     /**

Modified: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/SCXMLTestHelper.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/SCXMLTestHelper.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/SCXMLTestHelper.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/SCXMLTestHelper.java Thu Mar 23 17:12:40 2006
@@ -97,6 +97,13 @@
         return getExecutor(ctx, evaluator, scxml, ed, trc);
     }
 
+    public static SCXMLExecutor getExecutor(final SCXML scxml,
+            final Context ctx, final Evaluator evaluator) {
+        EventDispatcher ed = new SimpleDispatcher();
+        Tracer trc = new Tracer();
+        return getExecutor(ctx, evaluator, scxml, ed, trc);
+    }
+
     public static SCXMLExecutor getExecutor(Context context,
             Evaluator evaluator, SCXML scxml, EventDispatcher ed, Tracer trc) {
         return getExecutor(context, evaluator, scxml, ed, trc, null);

Added: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml?rev=388312&view=auto
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml (added)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml Thu Mar 23 17:12:40 2006
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!-- A fictitious state machine used by test cases.
+     Meant to illustrate the usage of SCXML <datamodel> element
+     and the Commons SCXML Data() function -->
+<scxml xmlns="http://www.w3.org/2005/07/SCXML"
+       version="1.0"
+       initialstate="main">
+
+    <!-- Root or document datamodel -->
+    <datamodel>
+        <data name="docdata">
+            <root xmlns="">
+                <foo>
+                    <bar>alpha</bar>
+                </foo>
+            </root>
+        </data>
+    </datamodel>
+
+    <state id="main">
+
+        <initial>
+            <transition target="ten"/>
+        </initial>
+
+        <!-- datamodel scoped to state "main" -->
+        <datamodel>
+            <!-- Degenerate usage, similar to the <var> element -->
+            <data name="mainvar" expr="0" />
+            <!-- Usage where the value is an XML data tree -->
+            <data name="maindata">
+                <root xmlns="">
+                    <a>
+                        <b>
+                            <c>beta</c>
+                            <d>123</d>
+                            <e>456.789</e>
+                        </b>
+                    </a>
+                </root>
+            </data>
+        </datamodel>
+
+        <state id="ten">
+            <onentry>
+                <!-- Assign Usage 1: name is previously defined
+                      <var> or degenerate <data> (as in this case) -->
+                <assign name="mainvar" expr="10" />
+            </onentry>
+            <!-- Commons SCXML defines a Data() function to use in conjunction
+                 with the Commons JEXL expression language. The
+                 first argument is the named XML data tree and the second is
+                 the XPath expression to a node whose value is to be
+                 examined  -->
+            <transition event="ten.done"
+             cond="mainvar eq 10 and Data(maindata,'root/a/b/c') eq 'beta'"
+             target="twenty" />
+            <onexit>
+                <!-- Assign Usage 2: location must point to an existing
+                      node  -->
+                <assign location="Data(maindata,'root/a/b/c')" expr="'gamma'" />
+            </onexit>
+        </state>
+
+        <state id="twenty">
+            <onentry>
+                <assign name="mainvar" expr="20" />
+            </onentry>
+            <transition event="twenty.done"
+             cond="Data(maindata,'root/a/b/c') eq 'gamma' and mainvar eq 20"
+             target="thirty" />
+            <onexit>
+                <!-- Assign Usage 3: location points to an existing
+                      node, and expr points to an existing node.
+                      In this case, location adopts expr's child nodes.  -->
+                <assign location="Data(docdata,'root/foo')"
+                        expr="Data(maindata,'root')" />
+            </onexit>
+        </state>
+
+        <state id="thirty">
+            <!-- Arithmetic operations are possible with results from
+                 the Data() function. Note that data "docdata"
+                 did not have a node at 'root/foo/a/b/d' to begin with,
+                 the XML tree was manipulated by the <assign> above -->
+            <transition event="thirty.done"
+             cond="Data(docdata,'root/foo/a/b/d') + Data(docdata,'root/foo/a/b/e') eq 579.789"
+             target="forty" />
+        </state>
+
+        <state id="forty" final="true" />
+
+    </state>
+
+</scxml>
+

Propchange: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jexl/datamodel-01.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/RootContextTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/RootContextTest.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/RootContextTest.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/RootContextTest.java Thu Mar 23 17:12:40 2006
@@ -95,7 +95,7 @@
         } catch (Exception e) {
             fail(e.getMessage());
         }
-        assertNotNull(ctx.iterator());
+        assertNotNull(ctx.getVars());
     }
 
      public static void main(String args[]) {

Added: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml?rev=388312&view=auto
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml (added)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml Thu Mar 23 17:12:40 2006
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!-- A fictitious state machine used by test cases.
+     Meant to illustrate the usage of SCXML <datamodel> element
+     and the Commons SCXML Data() function -->
+<scxml xmlns="http://www.w3.org/2005/07/SCXML"
+       version="1.0"
+       initialstate="main">
+
+    <!-- Root or document datamodel -->
+    <datamodel>
+        <data name="docdata">
+            <root xmlns="">
+                <foo>foo</foo>
+            </root>
+        </data>
+    </datamodel>
+
+    <state id="main">
+
+        <initial>
+            <transition target="ten"/>
+        </initial>
+
+        <!-- datamodel scoped to state "main" -->
+        <datamodel>
+            <data name="mainvar" expr="${0}" />
+            <data name="maindata">
+                <root xmlns="">
+                    <foo>
+                        <bar>bar</bar>
+                    </foo>
+                </root>
+            </data>
+        </datamodel>
+
+        <state id="ten">
+            <onentry>
+                <!-- Assign Usage 1: name is previously defined
+                      <var> or degenerate <data> (as in this case) -->
+                <assign name="mainvar" expr="${10}" />
+            </onentry>
+            <!-- Commons SCXML defines a Data() function to use in conjunction
+                 with the Commons EL expression language. The
+                 first argument is the named XML data tree and the second is
+                 the XPath expression to a node whose value is to be
+                 examined  -->
+            <transition event="ten.done"
+             cond="${mainvar eq 10 and Data(maindata,'root/foo/bar') eq 'bar'}"
+             target="twenty" />
+            <onexit>
+                <!-- Assign Usage 2: location must point to an existing
+                      node  -->
+                <assign location="${Data(maindata,'root/foo/bar')}" expr="baz" />
+            </onexit>
+        </state>
+
+        <state id="twenty">
+            <onentry>
+                <assign name="mainvar" expr="${20}" />
+            </onentry>
+            <transition event="twenty.done"
+             cond="${Data(maindata,'root/foo/bar') eq 'baz' and mainvar eq 20}"
+             target="thirty" />
+            <onexit>
+                <!-- Assign Usage 3: location points to an existing
+                      node, and expr points to an existing node.
+                      In this case, location adopts expr's child nodes.  -->
+                <assign location="${Data(docdata,'root/foo')}"
+                        expr="${Data(maindata,'root/foo')}" />
+                <assign location="${Data(docdata,'root/foo/bar')}"
+                        expr="${10}" />
+            </onexit>
+        </state>
+
+        <state id="thirty">
+            <!-- Arithmetic operations are possible with results from
+                 the Data() function. Note that data "docdata"
+                 did not have a node at 'root/foo/bar' to begin with,
+                 the XML tree was manipulated by the <assign> above -->
+            <transition event="thirty.done"
+             cond="${Data(docdata,'root/foo/bar') gt 5}"
+             target="forty" />
+        </state>
+
+        <state id="forty" final="true" />
+
+    </state>
+
+</scxml>
+

Propchange: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/env/jsp/datamodel-01.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java Thu Mar 23 17:12:40 2006
@@ -109,10 +109,9 @@
         assertEquals(1, actions.size());
         Send send = (Send) actions.get(0);
         assertEquals("send1", send.getSendid());
-        // Serialize
+        /* Serialize
         scxmlAsString = serialize(scxml);
         assertNotNull(scxmlAsString);
-        /* FIXME
         String expectedFoo2Serialization =
             "<foo xmlns=\"http://my.test.namespace\" id=\"foo2\">"
             + "<prompt xmlns=\"http://foo.bar.com/vxml3\">This is just"

Modified: jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java?rev=388312&r1=388311&r2=388312&view=diff
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java (original)
+++ jakarta/commons/sandbox/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java Thu Mar 23 17:12:40 2006
@@ -59,7 +59,9 @@
         scxml.setInitialstate("off");
         scxml.addState(new State());
         
-        String assertValue = "<scxml xmlns=\"namespace\" version=\"version1\" initialstate=\"off\">\n <state>\n </state>\n</scxml>\n";
+        String assertValue = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<scxml xmlns=\"namespace\" version=\"version1\" "
+            + "initialstate=\"off\">\n <state>\n </state>\n</scxml>\n";
         
         assertEquals(assertValue, SCXMLSerializer.serialize(scxml));
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org