summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--embedding/csharp/uSCXMLEmbedding.suobin0 -> 29184 bytes
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Examples.csproj13
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Extensions/CustomDataModel.cs (renamed from embedding/csharp/uSCXMLEmbedding/Extensions/SampleDataModel.cs)11
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Extensions/CustomExecutableContent.cs (renamed from embedding/csharp/uSCXMLEmbedding/Extensions/SampleExecutableContent.cs)4
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Extensions/CustomIOProc.cs (renamed from embedding/csharp/uSCXMLEmbedding/Extensions/SampleIOProc.cs)8
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Extensions/CustomInterpreterMonitor.cs (renamed from embedding/csharp/uSCXMLEmbedding/Extensions/SampleInterpreterMonitor.cs)2
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Extensions/CustomInvoker.cs (renamed from embedding/csharp/uSCXMLEmbedding/Extensions/SampleInvoker.cs)10
-rw-r--r--embedding/csharp/uSCXMLEmbedding/Program.cs34
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java18
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java21
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java31
-rw-r--r--embedding/java/src/org/uscxml/tests/TestData.java11
-rw-r--r--embedding/java/src/org/uscxml/tests/TestLifecycle.java124
-rw-r--r--embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java4
-rw-r--r--embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java55
-rw-r--r--embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java115
-rw-r--r--src/bindings/swig/csharp/org/uscxml/InterpreterException.cs2
-rw-r--r--src/bindings/swig/csharp/uscxml.i147
-rw-r--r--src/bindings/swig/java/org/uscxml/Data.java89
-rw-r--r--src/bindings/swig/java/uscxml.i211
-rw-r--r--src/bindings/swig/uscxml_beautify.i97
-rw-r--r--src/bindings/swig/uscxml_ignores.i6
-rw-r--r--src/bindings/swig/wrapped/WrappedDataModel.h1
-rw-r--r--src/bindings/swig/wrapped/WrappedExecutableContent.h2
-rw-r--r--src/bindings/swig/wrapped/WrappedIOProcessor.h1
-rw-r--r--src/bindings/swig/wrapped/WrappedInvoker.h1
-rw-r--r--src/uscxml/Factory.cpp53
-rw-r--r--src/uscxml/Interpreter.cpp82
-rw-r--r--src/uscxml/Interpreter.h5
-rw-r--r--src/uscxml/URL.cpp18
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp178
-rw-r--r--src/uscxml/messages/Data.h8
-rw-r--r--src/uscxml/messages/Event.cpp2
-rw-r--r--src/uscxml/messages/Event.h57
-rw-r--r--src/uscxml/messages/InvokeRequest.cpp2
-rw-r--r--src/uscxml/messages/SendRequest.cpp4
-rw-r--r--src/uscxml/plugins/DataModel.h4
-rw-r--r--src/uscxml/plugins/EventHandler.h4
-rw-r--r--src/uscxml/plugins/Invoker.h5
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp31
-rw-r--r--src/uscxml/plugins/datamodel/null/NULLDataModel.cpp5
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp10
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp30
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaParser.cpp13
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp54
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp4
-rw-r--r--src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp13
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp4
-rw-r--r--test/src/test-lifecycle.cpp346
-rw-r--r--test/w3c/confEcma.xsl14
-rw-r--r--test/w3c/confXPath.xsl9
-rw-r--r--test/w3c/ecma/test175.scxml6
-rw-r--r--test/w3c/ecma/test185.scxml2
-rw-r--r--test/w3c/ecma/test186.scxml2
-rw-r--r--test/w3c/ecma/test187.scxml4
-rw-r--r--test/w3c/ecma/test207.scxml6
-rw-r--r--test/w3c/ecma/test208.scxml4
-rw-r--r--test/w3c/ecma/test210.scxml4
-rw-r--r--test/w3c/ecma/test236.scxml2
-rw-r--r--test/w3c/ecma/test237.scxml6
-rw-r--r--test/w3c/ecma/test409.scxml2
-rw-r--r--test/w3c/ecma/test422.scxml2
-rw-r--r--test/w3c/ecma/test423.scxml2
-rw-r--r--test/w3c/ecma/test553.scxml2
-rw-r--r--test/w3c/ecma/test554.scxml2
-rw-r--r--test/w3c/ecma/test579.scxml2
-rw-r--r--test/w3c/txml/test175.txml6
-rw-r--r--test/w3c/txml/test185.txml2
-rw-r--r--test/w3c/txml/test186.txml2
-rw-r--r--test/w3c/txml/test187.txml4
-rw-r--r--test/w3c/txml/test207.txml6
-rw-r--r--test/w3c/txml/test208.txml4
-rw-r--r--test/w3c/txml/test210.txml4
-rw-r--r--test/w3c/txml/test236.txml2
-rw-r--r--test/w3c/txml/test237.txml6
-rw-r--r--test/w3c/txml/test409.txml2
-rw-r--r--test/w3c/txml/test422.txml2
-rw-r--r--test/w3c/txml/test423.txml2
-rw-r--r--test/w3c/txml/test553.txml2
-rw-r--r--test/w3c/txml/test554.txml2
-rw-r--r--test/w3c/txml/test579.txml2
-rwxr-xr-xtest/w3c/update-txml.sh7
-rw-r--r--test/w3c/xpath/test175.scxml4
-rw-r--r--test/w3c/xpath/test185.scxml2
-rw-r--r--test/w3c/xpath/test186.scxml2
-rw-r--r--test/w3c/xpath/test187.scxml4
-rw-r--r--test/w3c/xpath/test207.scxml6
-rw-r--r--test/w3c/xpath/test208.scxml4
-rw-r--r--test/w3c/xpath/test210.scxml4
-rw-r--r--test/w3c/xpath/test236.scxml2
-rw-r--r--test/w3c/xpath/test237.scxml6
-rw-r--r--test/w3c/xpath/test409.scxml2
-rw-r--r--test/w3c/xpath/test422.scxml2
-rw-r--r--test/w3c/xpath/test423.scxml2
-rw-r--r--test/w3c/xpath/test553.scxml2
-rw-r--r--test/w3c/xpath/test554.scxml2
-rw-r--r--test/w3c/xpath/test579.scxml2
98 files changed, 1426 insertions, 700 deletions
diff --git a/.gitignore b/.gitignore
index d861b13..46258d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,7 @@ package/windows*
/package/*
contrib/prebuilt/include/*
+
+/embedding/csharp/uSCXMLEmbedding/bin/
+
+/embedding/csharp/uSCXMLEmbedding/obj/
diff --git a/embedding/csharp/uSCXMLEmbedding.suo b/embedding/csharp/uSCXMLEmbedding.suo
new file mode 100644
index 0000000..b08325e
--- /dev/null
+++ b/embedding/csharp/uSCXMLEmbedding.suo
Binary files differ
diff --git a/embedding/csharp/uSCXMLEmbedding/Examples.csproj b/embedding/csharp/uSCXMLEmbedding/Examples.csproj
index b1579bf..b312b5f 100644
--- a/embedding/csharp/uSCXMLEmbedding/Examples.csproj
+++ b/embedding/csharp/uSCXMLEmbedding/Examples.csproj
@@ -41,18 +41,19 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
- <Reference Include="uscxmlCSharp">
+ <Reference Include="uscxmlCSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
<HintPath>C:\Users\sradomski\Desktop\build\uscxml\lib\uscxmlCSharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Extensions\SampleDataModel.cs" />
- <Compile Include="Extensions\SampleExecutableContent.cs" />
- <Compile Include="Extensions\SampleInterpreterMonitor.cs" />
- <Compile Include="Extensions\SampleInvoker.cs" />
- <Compile Include="Extensions\SampleIOProc.cs" />
+ <Compile Include="Extensions\CustomDataModel.cs" />
+ <Compile Include="Extensions\CustomExecutableContent.cs" />
+ <Compile Include="Extensions\CustomInterpreterMonitor.cs" />
+ <Compile Include="Extensions\CustomInvoker.cs" />
+ <Compile Include="Extensions\CustomIOProc.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleDataModel.cs b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomDataModel.cs
index 4d70594..b2ee1de 100644
--- a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleDataModel.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomDataModel.cs
@@ -4,13 +4,13 @@ using System.Linq;
using System.Text;
using org.uscxml;
-namespace EmbeddedDataModel
+namespace embedding
{
- class SampleDataModel : DataModel
+ class CustomDataModel : DataModel
{
public override DataModel create(Interpreter interpreter)
{
- return new SampleDataModel();
+ return new CustomDataModel();
}
public override void eval(string scriptElem, string expr)
@@ -54,10 +54,9 @@ namespace EmbeddedDataModel
return names;
}
- public override DataNative getStringAsData(string content)
+ public override Data getStringAsData(string content)
{
- // DataNative ought to be wrapped by a Data.cs class - used to carry JSONesque structures
- DataNative data = new DataNative();
+ Data data = new Data();
return data;
}
diff --git a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleExecutableContent.cs b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomExecutableContent.cs
index a86776f..4789020 100644
--- a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleExecutableContent.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomExecutableContent.cs
@@ -6,7 +6,7 @@ using org.uscxml;
namespace embedding
{
- class SampleExecutableContent : ExecutableContent
+ class CustomExecutableContent : ExecutableContent
{
public override string getLocalName()
{
@@ -25,7 +25,7 @@ namespace embedding
public override ExecutableContent create(Interpreter interpreter)
{
- return new SampleExecutableContent();
+ return new CustomExecutableContent();
}
diff --git a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleIOProc.cs b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomIOProc.cs
index 5abbf37..0480a34 100644
--- a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleIOProc.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomIOProc.cs
@@ -6,16 +6,16 @@ using org.uscxml;
namespace embedding
{
- class SampleIOProc : IOProcessor
+ class CustomIOProc : IOProcessor
{
public override IOProcessor create(Interpreter interpreter)
{
- return new SampleIOProc();
+ return new CustomIOProc();
}
- public override DataNative getDataModelVariables()
+ public override Data getDataModelVariables()
{
- DataNative data = new DataNative();
+ Data data = new Data();
return data;
}
diff --git a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleInterpreterMonitor.cs b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomInterpreterMonitor.cs
index 2a2f561..8009aa0 100644
--- a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleInterpreterMonitor.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomInterpreterMonitor.cs
@@ -6,7 +6,7 @@ using org.uscxml;
namespace embedding
{
- class SampleInterpreterMonitor : InterpreterMonitor
+ class CustomInterpreterMonitor : InterpreterMonitor
{
public override void afterCompletion(Interpreter interpreter) { }
public override void afterMicroStep(Interpreter interpreter) { }
diff --git a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleInvoker.cs b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomInvoker.cs
index f5fb363..3fd01ce 100644
--- a/embedding/csharp/uSCXMLEmbedding/Extensions/SampleInvoker.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Extensions/CustomInvoker.cs
@@ -4,18 +4,18 @@ using System.Linq;
using System.Text;
using org.uscxml;
-namespace EmbeddedInvoker
+namespace embedding
{
- class SampleInvoker : Invoker
+ class CustomInvoker : Invoker
{
public override Invoker create(Interpreter interpreter)
{
- return new SampleInvoker();
+ return new CustomInvoker();
}
- public override DataNative getDataModelVariables()
+ public override Data getDataModelVariables()
{
- DataNative data = new DataNative();
+ Data data = new Data();
return data;
}
diff --git a/embedding/csharp/uSCXMLEmbedding/Program.cs b/embedding/csharp/uSCXMLEmbedding/Program.cs
index 559d28f..0c76cb4 100644
--- a/embedding/csharp/uSCXMLEmbedding/Program.cs
+++ b/embedding/csharp/uSCXMLEmbedding/Program.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Diagnostics;
using System.Runtime.InteropServices;
namespace embedding
@@ -13,6 +14,34 @@ namespace embedding
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern void SetDllDirectory(string lpPathName);
+ static bool testLifecycle() {
+ // try to instantiate an interpreter with a parse error
+ try
+ {
+ Interpreter interpreter = Interpreter.fromXML("<invalid");
+ Debug.Assert(false);
+ }
+ catch (InterpreterException e) {
+ Console.Write(e.Message);
+ }
+
+ // try to instantiate an interpreter with invalid XML (no scxml element)
+ try
+ {
+ Interpreter interpreter = Interpreter.fromXML("<invalid />");
+ Debug.Assert(interpreter.getState() == InterpreterState.USCXML_INSTANTIATED);
+ InterpreterState state = interpreter.step();
+
+ Debug.Assert(false);
+ }
+ catch (InterpreterException e)
+ {
+ Console.Write(e.Message);
+ }
+
+ return true;
+ }
+
static void Main(string[] args)
{
@@ -28,9 +57,8 @@ namespace embedding
SetDllDirectory("C:\\Users\\sradomski\\Desktop\\build\\uscxml\\lib\\csharp");
}
- Interpreter interpreter = Interpreter.fromXML("<scxml><state id=\"f oo\" final=\"true\" /></scxml>");
- interpreter.addMonitor(new SampleInterpreterMonitor());
- interpreter.interpret();
+ testLifecycle();
+ Console.ReadKey();
}
}
}
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java
index 56d7090..035da61 100644
--- a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java
@@ -19,8 +19,8 @@ public class ECMAData implements Scriptable {
}
public Object unwrap(Data data) {
- if (data.atom.length() > 0) {
- return data.atom;
+ if (data.getAtom().length() > 0) {
+ return data.getAtom();
}
return new ECMAData(data);
@@ -28,26 +28,26 @@ public class ECMAData implements Scriptable {
@Override
public Object get(String name, Scriptable start) {
- if (data.compound.containsKey(name))
- return unwrap(data.compound.get(name));
+ if (data.hasKey(name))
+ return unwrap(data.at(name));
return NOT_FOUND;
}
@Override
public Object get(int index, Scriptable start) {
- if (data.array.size() > index)
- return unwrap(data.array.get(index));
+ if (data.getArray().size() > index)
+ return unwrap(data.item(index));
return NOT_FOUND;
}
@Override
public boolean has(String name, Scriptable start) {
- return data.compound.containsKey(name);
+ return data.hasKey(name);
}
@Override
public boolean has(int index, Scriptable start) {
- return data.array.size() > index;
+ return data.getArray().size() > index;
}
@Override
@@ -88,7 +88,7 @@ public class ECMAData implements Scriptable {
@Override
public Object[] getIds() {
- return data.compound.keySet().toArray();
+ return data.getCompound().keySet().toArray();
}
@Override
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java
index 58fff72..45d93b8 100644
--- a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java
@@ -1,13 +1,12 @@
package org.uscxml.datamodel.ecmascript;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.mozilla.javascript.Scriptable;
import org.uscxml.Data;
import org.uscxml.Event;
-import org.uscxml.ParamPair;
-import org.uscxml.ParamPairVector;
public class ECMAEvent implements Scriptable {
@@ -19,17 +18,17 @@ public class ECMAEvent implements Scriptable {
public ECMAEvent(Event event) {
this.event = event;
-
- Data data = new Data(event.getData());
-
- // insert params into event.data
- ParamPairVector ppv = event.getParamPairs();
- for (int i = 0; i < ppv.size(); i++) {
- ParamPair pp = ppv.get(i);
- data.compound.put(pp.getFirst(), new Data(pp.getSecond()));
+
+ // copy event params to data
+ Data data = event.getData();
+ Map<String, List<Data>> params = event.getParams();
+ for (String key : params.keySet()) {
+ for (Data param : params.get(key)) {
+ data.put(key, param);
+ }
}
- members.put("type", event.getEventType().toString());
+ members.put("type", event.getEventType());
members.put("data", new ECMAData(data));
members.put("sendid", event.getSendId());
members.put("origin", event.getOrigin());
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java
index 152f5e3..0b2b576 100644
--- a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java
@@ -12,7 +12,6 @@ import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
import org.uscxml.Data;
import org.uscxml.DataModel;
-import org.uscxml.DataNative;
import org.uscxml.Event;
import org.uscxml.Interpreter;
import org.uscxml.StringList;
@@ -45,20 +44,20 @@ public class ECMAScriptDataModel extends DataModel {
ScriptableObject obj = (ScriptableObject) Context.toObject(s,
scope);
for (Object key : obj.getIds()) {
- data.compound.put(Context.toString(key),
+ data.put(Context.toString(key),
getScriptableAsData(obj.get(key)));
}
}
} catch (ClassCastException e) {
if (object instanceof Boolean) {
- data.atom = (Context.toBoolean(object) ? "true" : "false");
- data.type = Data.Type.INTERPRETED;
+ data.setAtom(Context.toBoolean(object) ? "true" : "false");
+ data.setType(Data.Type.INTERPRETED);
} else if (object instanceof String) {
- data.atom = (String) object;
- data.type = Data.Type.VERBATIM;
+ data.setAtom((String) object);
+ data.setType(Data.Type.VERBATIM);
} else if (object instanceof Integer) {
- data.atom = ((Integer) object).toString();
- data.type = Data.Type.INTERPRETED;
+ data.setAtom(((Integer) object).toString());
+ data.setType(Data.Type.INTERPRETED);
} else {
throw new RuntimeException("Unhandled ECMA type "
+ object.getClass().getName());
@@ -102,9 +101,9 @@ public class ECMAScriptDataModel extends DataModel {
Data ioProcs = new Data();
StringVector keys = interpreter.getIOProcessorKeys();
for (int i = 0; i < keys.size(); i++) {
- ioProcs.compound.put(keys.get(i), new Data(interpreter
+ ioProcs.put(keys.get(i), interpreter
.getIOProcessors().get(keys.get(i))
- .getDataModelVariables()));
+ .getDataModelVariables());
}
newDM.scope
.put("_ioprocessors", newDM.scope, new ECMAData(ioProcs));
@@ -115,9 +114,9 @@ public class ECMAScriptDataModel extends DataModel {
Data invokers = new Data();
StringVector keys = interpreter.getInvokerKeys();
for (int i = 0; i < keys.size(); i++) {
- invokers.compound.put(keys.get(i), new Data(interpreter
+ invokers.put(keys.get(i), interpreter
.getInvokers().get(keys.get(i))
- .getDataModelVariables()));
+ .getDataModelVariables());
}
newDM.scope
.put("_ioprocessors", newDM.scope, new ECMAData(invokers));
@@ -176,7 +175,7 @@ public class ECMAScriptDataModel extends DataModel {
}
@Override
- public DataNative getStringAsData(String content) {
+ public Data getStringAsData(String content) {
if (debug) {
System.out.println(interpreter.getName() + " getStringAsData");
}
@@ -186,7 +185,7 @@ public class ECMAScriptDataModel extends DataModel {
* JSON-like Data structure
*/
if (content.length() == 0) {
- return Data.toNative(new Data());
+ return new Data();
}
// is it a json expression?
@@ -194,7 +193,7 @@ public class ECMAScriptDataModel extends DataModel {
Object json = NativeJSON.parse(ctx, scope, content,
new NullCallable());
if (json != NativeJSON.NOT_FOUND) {
- return Data.toNative(getScriptableAsData(json));
+ return getScriptableAsData(json);
}
} catch (org.mozilla.javascript.EcmaError e) {
System.err.println(e);
@@ -207,7 +206,7 @@ public class ECMAScriptDataModel extends DataModel {
x = ctx.evaluateString(scope, '"' + content + '"', "uscxml", 0,
null);
}
- return Data.toNative(getScriptableAsData(x));
+ return getScriptableAsData(x);
}
@Override
diff --git a/embedding/java/src/org/uscxml/tests/TestData.java b/embedding/java/src/org/uscxml/tests/TestData.java
index 44f1ce0..d1ebf20 100644
--- a/embedding/java/src/org/uscxml/tests/TestData.java
+++ b/embedding/java/src/org/uscxml/tests/TestData.java
@@ -1,7 +1,7 @@
package org.uscxml.tests;
import org.uscxml.Data;
-import org.uscxml.DataNative;
+import org.uscxml.Event;
public class TestData {
@@ -9,15 +9,12 @@ public class TestData {
System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
{
Data data = Data.fromJSON("[1,2,3,4,5]");
- DataNative nData2 = Data.toNative(data);
- Data data2 = new Data(nData2);
- System.out.println(data2);
+ System.out.println(data);
}
{
Data data = Data.fromJSON("{ \"foo\": \"bar\", \"faz\": 12 }");
- DataNative nData2 = Data.toNative(data);
- Data data2 = new Data(nData2);
- System.out.println(data2);
+ System.out.println(data);
}
+
}
}
diff --git a/embedding/java/src/org/uscxml/tests/TestLifecycle.java b/embedding/java/src/org/uscxml/tests/TestLifecycle.java
new file mode 100644
index 0000000..9278cbe
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/TestLifecycle.java
@@ -0,0 +1,124 @@
+package org.uscxml.tests;
+
+import org.uscxml.Interpreter;
+import org.uscxml.InterpreterException;
+import org.uscxml.InterpreterState;
+
+public class TestLifecycle {
+ public static void main(String[] args) {
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
+
+ // syntactic xml parse error -> throws
+ try {
+ String xml = "<invalid";
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ throw new RuntimeException("");
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+
+ // semantic xml parse error -> throws
+ try {
+ String xml = "<invalid />";
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ interpreter.step();
+ throw new RuntimeException("");
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+
+ // request unknown datamodel -> throws
+ try {
+ String xml =
+ "<scxml datamodel=\"invalid\">" +
+ " <state id=\"start\">" +
+ " <transition target=\"done\" />" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ interpreter.step();
+ throw new RuntimeException("");
+
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+
+ try {
+ // two microsteps
+ String xml =
+ "<scxml>" +
+ " <state id=\"start\">" +
+ " <transition target=\"s2\" />" +
+ " </state>" +
+ " <state id=\"s2\">" +
+ " <transition target=\"done\" />" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+
+ Interpreter interpreter = Interpreter.fromXML(xml);
+
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_MICROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_MICROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_FINISHED) throw new RuntimeException("");
+
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+
+ try {
+ // single macrostep, multiple runs
+ String xml =
+ "<scxml>" +
+ " <state id=\"start\">" +
+ " <transition target=\"done\" />" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_MICROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_FINISHED) throw new RuntimeException("");
+ interpreter.reset();
+
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_MICROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_FINISHED) throw new RuntimeException("");
+
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+
+ try {
+ // macrostep in between
+ String xml =
+ "<scxml>" +
+ " <state id=\"start\">" +
+ " <onentry>" +
+ " <send event=\"continue\" delay=\"2s\"/>" +
+ " </onentry>" +
+ " <transition target=\"s2\" event=\"continue\" />" +
+ " </state>" +
+ " <state id=\"s2\">" +
+ " <transition target=\"done\" />" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ if (interpreter.getState() != InterpreterState.USCXML_INSTANTIATED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_IDLE) throw new RuntimeException("");
+ if (interpreter.step(true) != InterpreterState.USCXML_MACROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_MICROSTEPPED) throw new RuntimeException("");
+ if (interpreter.step() != InterpreterState.USCXML_FINISHED) throw new RuntimeException("");
+
+ } catch (InterpreterException e) {
+ System.err.println(e);
+ }
+ }
+}
diff --git a/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java b/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java
index 92d7ed3..7a97ab4 100644
--- a/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java
+++ b/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java
@@ -1,11 +1,9 @@
package org.uscxml.tests.execContent;
-import org.uscxml.Data;
-import org.uscxml.Event;
+import org.uscxml.ExecutableContent;
import org.uscxml.Factory;
import org.uscxml.Interpreter;
import org.uscxml.InterpreterException;
-import org.uscxml.ExecutableContent;
public class TestCustomExecContent extends ExecutableContent {
diff --git a/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java b/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java
index b17b52e..25420ed 100644
--- a/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java
+++ b/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java
@@ -1,7 +1,6 @@
package org.uscxml.tests.invoker;
import org.uscxml.Data;
-import org.uscxml.DataNative;
import org.uscxml.Event;
import org.uscxml.Factory;
import org.uscxml.Interpreter;
@@ -21,27 +20,29 @@ public class TestCustomInvoker extends Invoker {
}
@Override
- public DataNative getDataModelVariables() {
+ public Data getDataModelVariables() {
Data data = new Data();
- data.array.add(new Data("foo", Data.Type.VERBATIM));
- return Data.toNative(data);
+ return data;
}
@Override
public void send(SendRequest req) {
- System.out.println("send");
+ System.out.println(req);
+ if ("foo".equals(req.getName()))
+ returnEvent(new Event("received2"), true); // enqueue an external event
}
@Override
public void invoke(InvokeRequest req) {
- System.out.println("invoke");
-
- System.out.println(req.getData());
- System.out.println(req.getXML());
+ System.out.println(req);
+ if ("Some string content".equals(req.getContent())) {
+ returnEvent(new Event("received1"), true); // enqueue an external event
+ }
+ }
- Event ev = new Event();
- ev.setName("foo");
- returnEvent(ev);
+ @Override
+ public void uninvoke() {
+ System.out.println("uninvoke");
}
@Override
@@ -54,15 +55,35 @@ public class TestCustomInvoker extends Invoker {
* @throws InterpreterException
*/
public static void main(String[] args) throws InterpreterException {
- System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib");
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
TestCustomInvoker invoker = new TestCustomInvoker();
+ // just register prototype at global factory
Factory.getInstance().registerInvoker(invoker);
- Interpreter interpreter = Interpreter
- .fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/samples/uscxml/test-java-invoker.scxml");
- while (true)
- interpreter.interpret();
+ String xml =
+ "<scxml>" +
+ " <state id=\"s1\">" +
+ " <invoke type=\"java\" id=\"javainvoker1\">" +
+ " <content>Some string content</content>" +
+ " </invoke>" +
+ " <invoke type=\"java\" id=\"javainvoker2\" />" +
+ " <state id=\"s11\">" +
+ " <transition event=\"received1\" target=\"s12\" />" +
+ " </state>" +
+ " <state id=\"s12\">" +
+ " <onentry>" +
+ " <send target=\"#_javainvoker2\" event=\"foo\" />" +
+ " </onentry>" +
+ " <transition event=\"received2\" target=\"done\" />" +
+ " </state>" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+
+ // parse and interpret
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ interpreter.interpret();
}
}
diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java
index cc4d332..277c505 100644
--- a/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java
+++ b/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java
@@ -1,16 +1,30 @@
package org.uscxml.tests.ioprocessor;
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
import org.uscxml.Data;
-import org.uscxml.DataNative;
+import org.uscxml.Event;
import org.uscxml.Factory;
import org.uscxml.IOProcessor;
import org.uscxml.Interpreter;
import org.uscxml.InterpreterException;
import org.uscxml.SendRequest;
import org.uscxml.StringList;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
public class TestCustomIOProc extends IOProcessor {
+ public Interpreter interpreter;
+
+ /**
+ * The types we will handle on a <send> element
+ */
@Override
public StringList getNames() {
StringList ss = new StringList();
@@ -18,38 +32,111 @@ public class TestCustomIOProc extends IOProcessor {
return ss;
}
+ /**
+ * Optional data we want to make available at
+ * _ioprocessors[this.getNames.front()] in the datamodel
+ */
@Override
- public DataNative getDataModelVariables() {
- Data data = new Data();
- data.array.add(new Data("foo", Data.Type.VERBATIM));
- return Data.toNative(data);
+ public Data getDataModelVariables() {
+ return new Data();
}
+ /**
+ * Send from the SCXML interpreter to this ioprocessor
+ */
@Override
public void send(SendRequest req) {
- System.out.println("send");
+ System.out.println(req);
+ // send in s1.onentry
+ if ("This is some content!".equals(req.getContent())) {
+ returnEvent(new Event("received1"));
+ return;
+ }
+ // send in s2.onentry
+ if (req.getParams().containsKey("foo")
+ && "bar".equals(req.getParams().get("foo").get(0).getAtom())) {
+ returnEvent(new Event("received2"));
+ return;
+ }
+ // send in s3
+ if (req.getXML().length() > 0) {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ Document doc = factory.newDocumentBuilder().parse(
+ new InputSource(new StringReader(req.getXML())));
+ System.out.println("Root element :"
+ + doc.getDocumentElement().getNodeName());
+ if ("this".equals(doc.getDocumentElement().getNodeName())) {
+ returnEvent(new Event("received3"));
+ return;
+ }
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
}
+ /**
+ * Create a new instance of this
+ */
@Override
public IOProcessor create(Interpreter interpreter) {
- return new TestCustomIOProc();
+ TestCustomIOProc ioProc = new TestCustomIOProc();
+ ioProc.interpreter = interpreter;
+ return ioProc;
}
/**
* @param args
- * @throws InterpreterException
+ * @throws InterpreterException
*/
public static void main(String[] args) throws InterpreterException {
- System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib");
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
TestCustomIOProc ioproc = new TestCustomIOProc();
+ // just register prototype at global factory
Factory.getInstance().registerIOProcessor(ioproc);
- Interpreter interpreter = Interpreter
- .fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/samples/uscxml/test-java-invoker.scxml");
-
- while (true)
- interpreter.interpret();
+ String xml =
+ "<scxml>" +
+ " <state id=\"s1\">" +
+ " <onentry>" +
+ " <send type=\"java\">" +
+ " <content>This is some content!</content>" +
+ " </send>" +
+ " </onentry>" +
+ " <transition event=\"received1\" target=\"s2\" />" +
+ " </state>" +
+ " <state id=\"s2\">" +
+ " <onentry>" +
+ " <send type=\"java\">" +
+ " <param name=\"foo\" expr=\"bar\" />" +
+ " </send>" +
+ " </onentry>" +
+ " <transition event=\"received2\" target=\"s3\" />" +
+ " </state>" +
+ " <state id=\"s3\">" +
+ " <onentry>" +
+ " <send type=\"java\">" +
+ " <content>" +
+ " <this><is><xml/></is></this>" +
+ " </content>" +
+ " </send>" +
+ " </onentry>" +
+ " <transition event=\"received3\" target=\"done\" />" +
+ " </state>" +
+ " <final id=\"done\" />" +
+ "</scxml>";
+
+ // parse and interpret
+ Interpreter interpreter = Interpreter.fromXML(xml);
+ interpreter.interpret();
}
}
diff --git a/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs b/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
index f86dc0e..38430d8 100644
--- a/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
+++ b/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
@@ -1,5 +1,5 @@
namespace org.uscxml {
- class InterpreterException : System.ApplicationException {
+ public class InterpreterException : System.ApplicationException {
public InterpreterException(string message)
: base(message) {
}
diff --git a/src/bindings/swig/csharp/uscxml.i b/src/bindings/swig/csharp/uscxml.i
index 988c541..8e9a297 100644
--- a/src/bindings/swig/csharp/uscxml.i
+++ b/src/bindings/swig/csharp/uscxml.i
@@ -12,10 +12,19 @@
%include <boost_shared_ptr.i>
+// these are needed at least for the templates to work
typedef uscxml::Data Data;
typedef uscxml::Event Event;
typedef uscxml::InvokeRequest InvokeRequest;
typedef uscxml::SendRequest SendRequest;
+typedef uscxml::Invoker Invoker;
+typedef uscxml::IOProcessor IOProcessor;
+typedef uscxml::DataModel DataModel;
+typedef uscxml::ExecutableContent ExecutableContent;
+typedef uscxml::InvokerImpl InvokerImpl;
+typedef uscxml::IOProcessorImpl IOProcessorImpl;
+typedef uscxml::DataModelImpl DataModelImpl;
+typedef uscxml::ExecutableContentImpl ExecutableContentImpl;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
@@ -54,6 +63,7 @@ typedef uscxml::SendRequest SendRequest;
using namespace uscxml;
using namespace Arabica::DOM;
+// the wrapped* C++ classes get rid of DOM nodes and provide more easily wrapped base classes
#include "../wrapped/WrappedInvoker.cpp"
#include "../wrapped/WrappedDataModel.cpp"
#include "../wrapped/WrappedExecutableContent.cpp"
@@ -125,11 +135,139 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%include "../uscxml_ignores.i"
-%rename Data DataNative;
+//***********************************************
+// Beautify important classes
+//***********************************************
%include "../uscxml_beautify.i"
+%rename(getCompoundNative) uscxml::Data::getCompound();
+%rename(getArrayNative) uscxml::Data::getArray();
+%rename(setCompoundNative) uscxml::Data::setCompound(const std::map<std::string, Data>&);
+%rename(setArrayNative) uscxml::Data::setArray(const std::list<Data>&);
+%csmethodmodifiers uscxml::Data::getCompound() "private";
+%csmethodmodifiers uscxml::Data::getArray() "private";
+%csmethodmodifiers uscxml::Data::setCompound(const std::map<std::string, Data>&) "private";
+%csmethodmodifiers uscxml::Data::setArray(const std::list<Data>&) "private";
+%csmethodmodifiers uscxml::Data::getCompoundKeys() "private";
+
+%typemap(csimports) uscxml::Data %{
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+%}
+
+%typemap(cscode) uscxml::Data %{
+ public Data(List<Data> arr) : this() {
+ setArray(arr);
+ }
+
+ public Data(Dictionary<string, Data> compound) : this() {
+ setCompound(compound);
+ }
+
+ public Dictionary<string, Data> getCompound() {
+ Dictionary<string, Data> compound = new Dictionary<string, Data>();
+ DataMap dataMap = getCompoundNative();
+ StringVector dataMapKeys = getCompoundKeys();
+ for (int i = 0; i < dataMapKeys.Count; i++) {
+ compound[dataMapKeys[i]] = dataMap[dataMapKeys[i]];
+ }
+ return compound;
+ }
+
+ public void setCompound(Dictionary<string, Data> compound) {
+ DataMap dataMap = new DataMap();
+ foreach(KeyValuePair<string, Data> entry in compound) {
+ dataMap.Add(entry);
+ }
+ setCompoundNative(dataMap);
+ }
+
+ public List<Data> getArray() {
+ List<Data> arr = new List<Data>();
+ DataList dataList = getArrayNative();
+ for (int i = 0; i < dataList.size(); i++) {
+ arr.Add(dataList.get(i));
+ }
+ return arr;
+ }
+
+ public void setArray(List<Data> arr) {
+ DataList dataList = new DataList();
+ foreach (Data data in arr) {
+ dataList.add(data);
+ }
+ setArrayNative(dataList);
+ }
+
+%}
+
+%rename(getNameListNative) uscxml::Event::getNameList();
+%rename(getParamsNative) uscxml::Event::getParams();
+%rename(setNameListNative) uscxml::Event::setNameList(const std::map<std::string, Data>&);
+%rename(setParamsNative) uscxml::Event::setParams(const std::multimap<std::string, Data>&);
+%csmethodmodifiers uscxml::Event::getNameList() "private";
+%csmethodmodifiers uscxml::Event::getNameListKeys() "private";
+%csmethodmodifiers uscxml::Event::getParams() "private";
+%csmethodmodifiers uscxml::Event::setNameList(const std::map<std::string, Data>&) "private";
+%csmethodmodifiers uscxml::Event::setParams(const std::multimap<std::string, Data>&) "private";
+
+%typemap(csimports) uscxml::Event %{
+ using System;
+ using System.Collections.Generic;
+ using System.Runtime.InteropServices;
+%}
+
+%typemap(cscode) uscxml::Event %{
+ public Dictionary<string, List<Data> > getParams() {
+ Dictionary<string, List<Data>> parameters = new Dictionary<string, List<Data>>();
+ ParamMap paramMap = getParamMap();
+
+ foreach (KeyValuePair<string, DataList> entry in paramMap) {
+ DataList dataList = entry.Value;
+ List<Data> paramList = new List<Data>();
+ for (int i = 0; i < dataList.size(); i++) {
+ Data data = dataList.get(i);
+ paramList.Add(data);
+ }
+ parameters.Add(entry.Key, paramList);
+ }
+ return parameters;
+ }
+
+ public void setParams(Dictionary<string, List<Data>> parameters) {
+ ParamMap paramMap = new ParamMap();
+ foreach(KeyValuePair<string, List<Data>> entry in parameters) {
+ DataList dataList = new DataList();
+ foreach (Data data in entry.Value) {
+ dataList.add(data);
+ }
+ paramMap.Add(entry.Key, dataList);
+ }
+ setParamMap(paramMap);
+ }
+
+ public Dictionary<string, Data> getNameList() {
+ Dictionary<string, Data> nameList = new Dictionary<string, Data>();
+ DataMap nameListMap = getNameListNative();
+ StringVector nameListMapKeys = getNameListKeys();
+ for (int i = 0; i < nameListMapKeys.Count; i++) {
+ nameList[nameListMapKeys[i]] = nameListMap[nameListMapKeys[i]];
+ }
+ return nameList;
+ }
+
+ public void setNameList(Dictionary<string, Data> nameList) {
+ DataMap dataMap = new DataMap();
+ foreach (KeyValuePair<string, Data> entry in nameList) {
+ dataMap.Add(entry);
+ }
+ setNameListNative(dataMap);
+ }
+%}
+
//***********************************************
// Parse the header file to generate wrappers
//***********************************************
@@ -164,8 +302,7 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%template(StringSet) std::set<std::string>;
%template(StringVector) std::vector<std::string>;
%template(StringList) std::list<std::string>;
-%template(ParamPair) std::pair<std::string, uscxml::Data>;
-%template(ParamPairVector) std::vector<std::pair<std::string, uscxml::Data> >;
-%template(IOProcMap) std::map<std::string, uscxml::IOProcessor>;
-%template(InvokerMap) std::map<std::string, uscxml::Invoker>;
+%template(ParamMap) std::map<std::string, std::list<uscxml::Data> >;
+%template(IOProcMap) std::map<std::string, IOProcessor>;
+%template(InvokerMap) std::map<std::string, Invoker>;
%template(ParentQueue) uscxml::concurrency::BlockingQueue<uscxml::SendRequest>;
diff --git a/src/bindings/swig/java/org/uscxml/Data.java b/src/bindings/swig/java/org/uscxml/Data.java
deleted file mode 100644
index 7781f47..0000000
--- a/src/bindings/swig/java/org/uscxml/Data.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.uscxml;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-public class Data {
- public Map<String, Data> compound = new HashMap<String, Data>();
- public List<Data> array = new LinkedList<Data>();
- public String atom;
- public Type type = Type.INTERPRETED;
-
- public enum Type {
- VERBATIM, INTERPRETED
- }
-
- public static Data fromJSON(String jsonString) {
- return new Data(DataNative.fromJSON(jsonString));
- }
-
- public Data() {
- }
-
- public Data(String atom, Data.Type type) {
- this.atom = atom;
- this.type = type;
- }
-
- public Data(DataNative nativeData) {
- if (!nativeData.getCompound().empty()) {
- // data is a key value compound
- StringVector keys = nativeData.getCompundKeys();
- for(int i = 0; i < keys.size(); i++) {
- this.compound.put(keys.get(i), new Data(nativeData.getCompound().get(keys.get(i))));
- }
- } else if (!nativeData.getArray().isEmpty()) {
- // data is an array
- for (int i = 0; i < nativeData.getArray().size(); i++) {
- this.array.add(new Data(nativeData.getArray().get(i)));
- }
- } else {
- // data is a single atom
- this.atom = nativeData.getAtom();
- if (nativeData.getType() == DataNative.Type.INTERPRETED) {
- this.type = Type.INTERPRETED;
- } else {
- this.type = Type.VERBATIM;
- }
- }
- }
-
- @Override
- public String toString() {
- return toJSON();
- }
-
- public String toJSON() {
- DataNative nativeData = toNative(this);
- return DataNative.toJSON(nativeData);
- }
-
- public static DataNative toNative(Data data) {
- DataNative nativeData = new DataNative();
- //nativeData.swigCMemOwn = false;
- if (data.compound != null && !data.compound.isEmpty()) {
- DataMap nativeDataMap = new DataMap();
- for (String key : data.compound.keySet()) {
- nativeDataMap.set(key, toNative(data.compound.get(key)));
- }
- nativeData.setCompound(nativeDataMap);
- } else if (data.array != null && !data.array.isEmpty()) {
- DataList nativeDataList = new DataList();
- for (Data item : data.array) {
- nativeDataList.add(toNative(item));
- }
- nativeData.setArray(nativeDataList);
- } else if (data.atom != null) {
- nativeData.setAtom(data.atom);
- if (data.type == Type.INTERPRETED) {
- nativeData.setType(DataNative.Type.INTERPRETED);
- } else {
- nativeData.setType(DataNative.Type.VERBATIM);
- }
- }
- return nativeData;
- }
-
-}
diff --git a/src/bindings/swig/java/uscxml.i b/src/bindings/swig/java/uscxml.i
index 880b02d..cb760e4 100644
--- a/src/bindings/swig/java/uscxml.i
+++ b/src/bindings/swig/java/uscxml.i
@@ -12,10 +12,19 @@
%include <boost_shared_ptr.i>
+// these are needed at least for the templates to work
typedef uscxml::Data Data;
typedef uscxml::Event Event;
typedef uscxml::InvokeRequest InvokeRequest;
typedef uscxml::SendRequest SendRequest;
+typedef uscxml::Invoker Invoker;
+typedef uscxml::IOProcessor IOProcessor;
+typedef uscxml::DataModel DataModel;
+typedef uscxml::ExecutableContent ExecutableContent;
+typedef uscxml::InvokerImpl InvokerImpl;
+typedef uscxml::IOProcessorImpl IOProcessorImpl;
+typedef uscxml::DataModelImpl DataModelImpl;
+typedef uscxml::ExecutableContentImpl ExecutableContentImpl;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
@@ -33,7 +42,6 @@ typedef uscxml::SendRequest SendRequest;
%rename(equals) operator==;
%rename(isValid) operator bool;
-
//**************************************************
// This ends up in the generated wrapper code
//**************************************************
@@ -54,6 +62,7 @@ typedef uscxml::SendRequest SendRequest;
using namespace uscxml;
using namespace Arabica::DOM;
+// the wrapped* C++ classes get rid of DOM nodes and provide more easily wrapped base classes
#include "../wrapped/WrappedInvoker.cpp"
#include "../wrapped/WrappedDataModel.cpp"
#include "../wrapped/WrappedExecutableContent.cpp"
@@ -86,11 +95,202 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%include "../uscxml_ignores.i"
-%rename Data DataNative;
+// see http://swig.org/Doc2.0/Java.html#Java_date_marshalling
+%define BEAUTIFY_NATIVE( MATCH, WRAPPER, NATIVE )
+
+%rename WRAPPER NATIVE;
+
+%typemap(jstype) const MATCH & "WRAPPER"
+%typemap(jstype) MATCH "WRAPPER"
+
+%typemap(javain,
+ pre=" NATIVE temp$javainput = $javainput.toNative();",
+ pgcppname="temp$javainput") const MATCH &
+ "$javaclassname.getCPtr(temp$javainput)"
+
+ %typemap(javain,
+ pre=" NATIVE temp$javainput = $javainput.toNative();",
+ pgcppname="temp$javainput") MATCH
+ "$javaclassname.getCPtr(temp$javainput)"
+
+%typemap(javaout) const MATCH & {
+ NATIVE nativeData = new NATIVE($jnicall, $owner);
+ return new WRAPPER(nativeData);
+}
+
+%typemap(javaout) MATCH {
+ NATIVE nativeData = new NATIVE($jnicall, $owner);
+ return new WRAPPER(nativeData);
+}
+
+%typemap(javadirectorout) MATCH "NATIVE.getCPtr($javacall.toNative())"
+
+%typemap(javadirectorin) MATCH "WRAPPER.fromNative(new NATIVE($jniinput, false))";
+%typemap(javadirectorin) const MATCH & "WRAPPER.fromNative(new NATIVE($jniinput, false))";
+
+%typemap(directorin,descriptor="L/org/uscxml/"##"WRAPPER;") const MATCH & "*(MATCH **)&$input = (MATCH *) &$1;"
+
+%typemap(directorout) MATCH ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Unexpected null return for type $1_type");
+ return $null;
+ }
+ $result = *argp; %}
+
+%enddef
+
+/*
+// not used as it will not work for directors :(
+BEAUTIFY_NATIVE(uscxml::Data, Data, DataNative);
+BEAUTIFY_NATIVE(uscxml::Event, Event, EventNative);
+BEAUTIFY_NATIVE(uscxml::SendRequest, SendRequest, SendRequestNative);
+BEAUTIFY_NATIVE(uscxml::InvokeRequest, InvokeRequest, InvokeRequestNative);
+*/
+
+
+//***********************************************
+// Beautify important classes
+//***********************************************
%include "../uscxml_beautify.i"
+%rename(getCompoundNative) uscxml::Data::getCompound();
+%rename(getArrayNative) uscxml::Data::getArray();
+%rename(setCompoundNative) uscxml::Data::setCompound(const std::map<std::string, Data>&);
+%rename(setArrayNative) uscxml::Data::setArray(const std::list<Data>&);
+%javamethodmodifiers uscxml::Data::getCompound() "private";
+%javamethodmodifiers uscxml::Data::getArray() "private";
+%javamethodmodifiers uscxml::Data::setCompound(const std::map<std::string, Data>&) "private";
+%javamethodmodifiers uscxml::Data::setArray(const std::list<Data>&) "private";
+%javamethodmodifiers uscxml::Data::getCompoundKeys() "private";
+
+%typemap(javaimports) uscxml::Data %{
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+%}
+
+%typemap(javacode) uscxml::Data %{
+ public Data(Map<String, Data> compound) {
+ this(uscxmlNativeJavaJNI.new_Data__SWIG_0(), true);
+ setCompound(compound);
+ }
+
+ public Data(List<Data> array) {
+ this(uscxmlNativeJavaJNI.new_Data__SWIG_0(), true);
+ setArray(array);
+ }
+
+ public Map<String, Data> getCompound() {
+ Map<String, Data> compound = new HashMap<String, Data>();
+ DataMap dataMap = getCompoundNative();
+ StringVector dataMapKeys = getCompoundKeys();
+ for (int i = 0; i < dataMapKeys.size(); i++) {
+ compound.put(dataMapKeys.get(i), dataMap.get(dataMapKeys.get(i)));
+ }
+ return compound;
+ }
+
+ public void setCompound(Map<String, Data> compound) {
+ DataMap dataMap = new DataMap();
+ for (String key : compound.keySet()) {
+ dataMap.set(key, compound.get(key));
+ }
+ setCompoundNative(dataMap);
+ }
+
+ public List<Data> getArray() {
+ List<Data> array = new LinkedList<Data>();
+ DataList dataList = getArrayNative();
+ for (int i = 0; i < dataList.size(); i++) {
+ array.add(dataList.get(i));
+ }
+ return array;
+ }
+
+ public void setArray(List<Data> array) {
+ DataList dataList = new DataList();
+ for (Data data : array) {
+ dataList.add(data);
+ }
+ setArrayNative(dataList);
+ }
+
+%}
+
+%rename(getNameListNative) uscxml::Event::getNameList();
+%rename(getParamstNative) uscxml::Event::getParams();
+%rename(setNameListNative) uscxml::Event::setNameList(const std::map<std::string, Data>&);
+%rename(setParamsNative) uscxml::Event::setParams(const std::multimap<std::string, Data>&);
+%javamethodmodifiers uscxml::Event::getNameList() "private";
+%javamethodmodifiers uscxml::Event::getNameListKeys() "private";
+%javamethodmodifiers uscxml::Event::getParams() "private";
+%javamethodmodifiers uscxml::Event::setNameList(const std::map<std::string, Data>&) "private";
+%javamethodmodifiers uscxml::Event::setParams(const std::multimap<std::string, Data>&) "private";
+
+%typemap(javaimports) uscxml::Event %{
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+%}
+
+%typemap(javacode) uscxml::Event %{
+ public Map<String, List<Data>> getParams() {
+ Map<String, List<Data>> params = new HashMap<String, List<Data>>();
+ ParamMap paramMap = getParamMap();
+ StringVector paramMapKeys = getParamMapKeys();
+
+ for (int i = 0; i < paramMapKeys.size(); i++) {
+ String key = paramMapKeys.get(i);
+ DataList dataList = paramMap.get(key);
+
+ for (int j = 0; j < dataList.size(); j++) {
+ Data data = dataList.get(j);
+ if (!params.containsKey(key))
+ params.put(key, new LinkedList<Data>());
+ params.get(key).add(data);
+ }
+ }
+ return params;
+ }
+
+ public void setParams(Map<String, List<Data>> params) {
+ ParamMap paramMap = new ParamMap();
+ for (String key : params.keySet()) {
+ DataList datalist = new DataList();
+ for (Data data : params.get(key)) {
+ datalist.add(data);
+ }
+ paramMap.set(key, datalist);
+ }
+ setParamMap(paramMap);
+ }
+
+ public Map<String, Data> getNameList() {
+ Map<String, Data> namelist = new HashMap<String, Data>();
+ StringVector nameMapKeys = getNameListKeys();
+ DataMap nameMap = getNameListNative();
+
+ for (int i = 0; i < nameMapKeys.size(); i++) {
+ namelist.put(nameMapKeys.get(i), nameMap.get(nameMapKeys.get(i)));
+ }
+ return namelist;
+ }
+
+ public void setNameList(Map<String, Data> namelist) {
+ DataMap nameListMap = new DataMap();
+ for (String key : namelist.keySet()) {
+ nameListMap.set(key, namelist.get(key));
+ }
+ setNameListNative(nameListMap);
+ }
+%}
+
+
//***********************************************
// Parse the header file to generate wrappers
//***********************************************
@@ -125,8 +325,7 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%template(StringSet) std::set<std::string>;
%template(StringVector) std::vector<std::string>;
%template(StringList) std::list<std::string>;
-%template(ParamPair) std::pair<std::string, uscxml::Data>;
-%template(ParamPairVector) std::vector<std::pair<std::string, uscxml::Data> >;
-%template(IOProcMap) std::map<std::string, uscxml::IOProcessor>;
-%template(InvokerMap) std::map<std::string, uscxml::Invoker>;
+%template(ParamMap) std::map<std::string, std::list<uscxml::Data> >;
+%template(IOProcMap) std::map<std::string, IOProcessor>;
+%template(InvokerMap) std::map<std::string, Invoker>;
%template(ParentQueue) uscxml::concurrency::BlockingQueue<uscxml::SendRequest>;
diff --git a/src/bindings/swig/uscxml_beautify.i b/src/bindings/swig/uscxml_beautify.i
index 8a53fbb..ac3ed44 100644
--- a/src/bindings/swig/uscxml_beautify.i
+++ b/src/bindings/swig/uscxml_beautify.i
@@ -9,15 +9,76 @@
%rename(NativeInterpreterMonitor) InterpreterMonitor;
%rename(InterpreterMonitor) WrappedInterpreterMonitor;
-%extend uscxml::Event {
- std::vector<std::pair<std::string, Data> > getParamPairs() {
- std::vector<std::pair<std::string, Data> > pairs;
- std::multimap<std::string, Data>::iterator paramPairIter = self->getParams().begin();
+%extend uscxml::Event {
+/* std::vector<std::pair<std::string, uscxml::Data> > getParamPairs() {
+ std::vector<std::pair<std::string, Data> > pairs;
+ std::multimap<std::string, Data>::iterator paramPairIter = self->getParams().begin();
+ while(paramPairIter != self->getParams().end()) {
+ pairs.push_back(*paramPairIter);
+ paramPairIter++;
+ }
+ return pairs;
+ }
+
+ void setParamPairs(const std::vector<std::pair<std::string, uscxml::Data> >& pairs) {
+ std::multimap<std::string, Data> params;
+ std::vector<std::pair<std::string, Data> >::const_iterator pairIter = pairs.begin();
+ while(pairIter != pairs.end()) {
+ params.insert(std::make_pair(pairIter->first, pairIter->second));
+ pairIter++;
+ }
+ self->setParams(params);
+ }
+*/
+
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+
+ std::map<std::string, std::list<uscxml::Data> > getParamMap() {
+ std::map<std::string, std::list<uscxml::Data> > paramMap;
+ std::multimap<std::string, Data>::const_iterator paramPairIter = self->getParams().begin();
while(paramPairIter != self->getParams().end()) {
- pairs.push_back(*paramPairIter);
+ paramMap[paramPairIter->first].push_back(paramPairIter->second);
paramPairIter++;
}
- return pairs;
+ return paramMap;
+ }
+
+ std::vector<std::string> getParamMapKeys() {
+ std::vector<std::string> keys;
+ for(std::multimap<std::string, Data>::const_iterator iter = self->getParams().begin();
+ iter != self->getParams().end();
+ iter = self->getParams().upper_bound(iter->first)) {
+ keys.push_back(iter->first);
+ }
+ return keys;
+ }
+
+ void setParamMap(const std::map<std::string, std::list<uscxml::Data> >& paramMap) {
+ std::multimap<std::string, Data> params;
+ std::map<std::string, std::list<uscxml::Data> >::const_iterator mapIter = paramMap.begin();
+ while(mapIter != paramMap.end()) {
+ std::list<uscxml::Data>::const_iterator dataIter = mapIter->second.begin();
+ while(dataIter != mapIter->second.end()) {
+ params.insert(std::make_pair(mapIter->first, *dataIter));
+ dataIter++;
+ }
+ mapIter++;
+ }
+ self->setParams(params);
+ }
+
+ std::vector<std::string> getNameListKeys() {
+ std::vector<std::string> keys;
+ std::map<std::string, Data>::const_iterator iter = self->getNameList().begin();
+ while(iter != self->getNameList().end()) {
+ keys.push_back(iter->first);
+ iter++;
+ }
+ return keys;
}
};
@@ -66,7 +127,13 @@
};
%extend uscxml::Data {
- std::vector<std::string> getCompundKeys() {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+
+ std::vector<std::string> getCompoundKeys() {
std::vector<std::string> keys;
std::map<std::string, Data>::const_iterator iter = self->compound.begin();
while(iter != self->compound.end()) {
@@ -76,3 +143,19 @@
return keys;
}
};
+
+%extend uscxml::SendRequest {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+};
+
+%extend uscxml::InvokeRequest {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+}; \ No newline at end of file
diff --git a/src/bindings/swig/uscxml_ignores.i b/src/bindings/swig/uscxml_ignores.i
index c5bf88b..d54dae2 100644
--- a/src/bindings/swig/uscxml_ignores.i
+++ b/src/bindings/swig/uscxml_ignores.i
@@ -21,7 +21,6 @@
%ignore uscxml::EventHandler::getElement;
%ignore uscxml::EventHandler::runOnMainThread;
-
%ignore uscxml::NameSpaceInfo::NameSpaceInfo(const std::map<std::string, std::string>&);
%ignore uscxml::NameSpaceInfo::NameSpaceInfo(const NameSpaceInfo&);
%ignore uscxml::NameSpaceInfo::setPrefix(Arabica::DOM::Element<std::string>);
@@ -180,6 +179,11 @@
%ignore uscxml::Event::toDocument();
%ignore uscxml::Event::getParams();
%ignore uscxml::Event::getParam;
+%ignore uscxml::Event::setParams;
+
+%ignore uscxml::SendRequest::fromXML;
+%ignore uscxml::InvokeRequest::fromXML;
+
// Data
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h
index 013f22c..e1b29af 100644
--- a/src/bindings/swig/wrapped/WrappedDataModel.h
+++ b/src/bindings/swig/wrapped/WrappedDataModel.h
@@ -46,6 +46,7 @@ public:
_interpreter = interpreter->shared_from_this();
return boost::shared_ptr<DataModelImpl>(create(_interpreter));
}
+
virtual std::list<std::string> getNames() {
return std::list<std::string>();
};
diff --git a/src/bindings/swig/wrapped/WrappedExecutableContent.h b/src/bindings/swig/wrapped/WrappedExecutableContent.h
index e00704a..b1ce4f9 100644
--- a/src/bindings/swig/wrapped/WrappedExecutableContent.h
+++ b/src/bindings/swig/wrapped/WrappedExecutableContent.h
@@ -72,11 +72,9 @@ public:
}
virtual void enterElement(const std::string& node) {
-
}
virtual void exitElement(const std::string& node) {
-
}
private:
diff --git a/src/bindings/swig/wrapped/WrappedIOProcessor.h b/src/bindings/swig/wrapped/WrappedIOProcessor.h
index 1d134dc..b4e4938 100644
--- a/src/bindings/swig/wrapped/WrappedIOProcessor.h
+++ b/src/bindings/swig/wrapped/WrappedIOProcessor.h
@@ -47,6 +47,7 @@ public:
_interpreter = interpreter->shared_from_this();
return boost::shared_ptr<IOProcessorImpl>(create(_interpreter));
}
+
virtual std::list<std::string> getNames() {
return std::list<std::string>();
};
diff --git a/src/bindings/swig/wrapped/WrappedInvoker.h b/src/bindings/swig/wrapped/WrappedInvoker.h
index b3ff200..6251c6e 100644
--- a/src/bindings/swig/wrapped/WrappedInvoker.h
+++ b/src/bindings/swig/wrapped/WrappedInvoker.h
@@ -50,6 +50,7 @@ public:
virtual void send(const SendRequest& req) {}
virtual void invoke(const InvokeRequest& req) {}
+ virtual void uninvoke() {}
virtual WrappedInvoker* create(Interpreter interpreter) {
return new WrappedInvoker();
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 3556aba..22482e6 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -516,7 +516,7 @@ boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, I
if (_parentFactory) {
return _parentFactory->createInvoker(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " Invoker known";
+ ERROR_EXECUTION_THROW("No Invoker named '" + type + "' known");
}
return boost::shared_ptr<InvokerImpl>();
@@ -538,7 +538,7 @@ boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& typ
if (_parentFactory) {
return _parentFactory->createDataModel(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " Datamodel known";
+ ERROR_EXECUTION_THROW("No Datamodel name '" + type + "' known");
}
return boost::shared_ptr<DataModelImpl>();
@@ -559,7 +559,7 @@ boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string&
if (_parentFactory) {
return _parentFactory->createIOProcessor(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " IOProcessor known";
+ ERROR_EXECUTION_THROW("No IOProcessor named '" + type + "' known");
}
return boost::shared_ptr<IOProcessorImpl>();
@@ -578,7 +578,7 @@ boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const
if (_parentFactory) {
return _parentFactory->createExecutableContent(localName, nameSpace, interpreter);
} else {
- LOG(ERROR) << "Executable content " << localName << " in " << actualNameSpace << " not available in factory";
+ ERROR_EXECUTION_THROW("No Executable content name '" + localName + "' in namespace '" + actualNameSpace + "' known");
}
return boost::shared_ptr<ExecutableContentImpl>();
@@ -654,51 +654,32 @@ Factory* Factory::getInstance() {
}
void EventHandlerImpl::returnErrorExecution(const std::string& cause) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(cause, Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
- returnEvent(exceptionEvent);
+ ERROR_EXECUTION(exc, cause);
+ returnEvent(exc);
}
-void EventHandlerImpl::returnErrorPlatform(const std::string& cause) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(cause, Data::VERBATIM);
- exceptionEvent.name = "error.platform";
- exceptionEvent.eventType = Event::PLATFORM;
- returnEvent(exceptionEvent);
+void EventHandlerImpl::returnErrorCommunication(const std::string& cause) {
+ ERROR_COMMUNICATION(exc, cause);
+ returnEvent(exc);
}
-void EventHandlerImpl::returnEvent(Event& event) {
+void EventHandlerImpl::returnEvent(Event& event, bool external) {
if (event.invokeid.length() == 0)
event.invokeid = _invokeId;
if (event.eventType == 0)
- event.eventType = Event::EXTERNAL;
+ event.eventType = (external ? Event::EXTERNAL : Event::INTERNAL);
if (event.origin.length() == 0)
event.origin = "#_" + _invokeId;
if (event.origintype.length() == 0)
event.origintype = _type;
-
- _interpreter->receive(event);
-}
-
-void DataModelImpl::throwErrorExecution(const std::string& cause) {
- uscxml::Event exc;
- exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
- exc.name = "error.execution";
- exc.eventType = uscxml::Event::PLATFORM;
- throw exc;
-}
-
-void DataModelImpl::throwErrorPlatform(const std::string& cause) {
- uscxml::Event exc;
- exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
- exc.name = "error.platform";
- exc.eventType = uscxml::Event::PLATFORM;
- throw exc;
+
+ if (external) {
+ _interpreter->receive(event);
+ } else {
+ _interpreter->receiveInternal(event);
+ }
}
-
Factory* Factory::_instance = NULL;
std::string Factory::_defaultPluginPath;
} \ No newline at end of file
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 22fb79e..47a6182 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -83,6 +83,7 @@
#define VALID_FROM_MACROSTEPPED(newState) ( \
newState == USCXML_DESTROYED || \
newState == USCXML_MICROSTEPPED || \
+ newState == USCXML_MACROSTEPPED || \
newState == USCXML_IDLE || \
newState == USCXML_FINISHED \
)
@@ -96,14 +97,7 @@
#define VALID_FROM_FINISHED(newState) ( \
newState == USCXML_DESTROYED || \
newState == USCXML_INSTANTIATED \
-)
-
-#define THROW_ERROR_PLATFORM(msg) \
- Event e; \
- e.name = "error.platform"; \
- e.data.compound["cause"] = Data(msg, Data::VERBATIM); \
- throw e; \
-
+)
/// macro to catch exceptions in executeContent
#define CATCH_AND_DISTRIBUTE(msg) \
@@ -113,6 +107,7 @@ catch (Event e) {\
throw(e);\
} else {\
e.name = "error.execution";\
+ e.data.compound["cause"] = uscxml::Data(msg, uscxml::Data::VERBATIM); \
e.eventType = Event::PLATFORM;\
receiveInternal(e);\
}\
@@ -120,11 +115,14 @@ catch (Event e) {\
#define CATCH_AND_DISTRIBUTE2(msg, node) \
catch (Event e) {\
- LOG(ERROR) << msg << " " << DOMUtils::xPathForNode(node) << ":" << std::endl << e << std::endl;\
+ std::string xpathPos = DOMUtils::xPathForNode(node); \
+ LOG(ERROR) << msg << " " << xpathPos << ":" << std::endl << e << std::endl;\
if (rethrow) {\
throw(e);\
} else {\
e.name = "error.execution";\
+ e.data.compound["cause"] = uscxml::Data(msg, uscxml::Data::VERBATIM); \
+ e.data.compound["xpath"] = uscxml::Data(xpathPos, uscxml::Data::VERBATIM); \
e.eventType = Event::PLATFORM;\
e.dom = node;\
receiveInternal(e);\
@@ -394,7 +392,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
URL absUrl(uri);
if (!absUrl.isAbsolute()) {
if (!absUrl.toAbsoluteCwd()) {
- THROW_ERROR_PLATFORM("Given URL is not absolute or does not have file schema");
+ ERROR_COMMUNICATION_THROW("URL is not absolute or does not have file schema");
}
}
@@ -416,7 +414,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
std::stringstream ss;
ss << absUrl;
if (absUrl.downloadFailed()) {
- THROW_ERROR_PLATFORM("Downloading SCXML document from " + absUrl.asString() + " failed");
+ ERROR_COMMUNICATION_THROW("Downloading SCXML document from '" + absUrl.asString() + "' failed");
}
interpreter = fromXML(ss.str());
}
@@ -426,7 +424,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
interpreter._impl->_baseURI = URL::asBaseURL(absUrl);
interpreter._impl->_sourceURI = absUrl;
} else {
- THROW_ERROR_PLATFORM("Cannot create interpreter from URI " + absUrl.asString() + "'");
+ ERROR_PLATFORM_THROW("Cannot create interpreter from URI '" + absUrl.asString() + "'");
}
return interpreter;
}
@@ -454,9 +452,9 @@ Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>&
interpreterImpl->_document = parser.getDocument();
} else {
if (parser.errorsReported()) {
- THROW_ERROR_PLATFORM(parser.errors())
+ ERROR_PLATFORM_THROW(parser.errors())
} else {
- THROW_ERROR_PLATFORM("Failed to create interpreter");
+ ERROR_PLATFORM_THROW("Failed to create interpreter");
// interpreterImpl->setInterpreterState(USCXML_FAULTED, parser.errors());
}
}
@@ -680,11 +678,13 @@ void InterpreterImpl::reset() {
_internalQueue.clear();
_historyValue.clear();
+ _currEvent = Event();
_alreadyEntered = NodeSet<std::string>();
_configuration = NodeSet<std::string>();
_topLevelFinalReached = false;
_isInitialized = false;
-
+ _stable = false;
+
setInterpreterState(USCXML_INSTANTIATED);
}
@@ -693,9 +693,7 @@ void InterpreterImpl::setupAndNormalizeDOM() {
return;
if (!_document) {
- Event error("error.platform");
- error.data.compound["cause"] = Data("Interpreter has no DOM", Data::VERBATIM);
- throw error;
+ ERROR_PLATFORM_THROW("Interpreter has no DOM");
}
// find scxml element
@@ -707,9 +705,7 @@ void InterpreterImpl::setupAndNormalizeDOM() {
}
if (scxmls.getLength() == 0) {
- Event error("error.platform");
- error.data.compound["cause"] = Data("Cannot find SCXML element in DOM", Data::VERBATIM);
- throw error;
+ ERROR_PLATFORM_THROW("Cannot find SCXML element in DOM");
}
_scxml = (Arabica::DOM::Element<std::string>)scxmls.item(0);
@@ -777,12 +773,8 @@ void InterpreterImpl::init() {
// instantiate datamodel
if (HAS_ATTR(_scxml, "datamodel")) {
+ // might throw
_dataModel = _factory->createDataModel(ATTR(_scxml, "datamodel"), this);
- if (!_dataModel) {
- Event e;
- e.data.compound["cause"] = Data("Cannot instantiate datamodel", Data::VERBATIM);
- throw e;
- }
} else {
_dataModel = _factory->createDataModel("null", this);
}
@@ -1264,9 +1256,8 @@ void InterpreterImpl::delayedSend(void* userdata, std::string eventName) {
* If the SCXML Processor does not support the type that is specified, it
* must place the event error.execution on the internal event queue.
*/
- Event exceptionEvent("error.execution", Event::PLATFORM);
-// exceptionEvent.sendid = sendReq.sendid;
- INSTANCE->receiveInternal(exceptionEvent);
+ ERROR_EXECUTION(exc, "Unsupported type '" + sendReq.type + "' with send element");
+ INSTANCE->receiveInternal(exc);
}
assert(INSTANCE->_sendIds.find(sendReq.sendid) != INSTANCE->_sendIds.end());
@@ -1372,7 +1363,12 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) {
if (invokeReq.type.size() == 0)
invokeReq.type = "http://www.w3.org/TR/scxml/";
- Invoker invoker(_factory->createInvoker(invokeReq.type, this));
+ Invoker invoker;
+ try {
+ invoker = _factory->createInvoker(invokeReq.type, this);
+ } catch (Event e) {
+ receiveInternal(e);
+ }
if (invoker) {
tthread::lock_guard<tthread::recursive_mutex> lock(_pluginMutex);
try {
@@ -1439,7 +1435,7 @@ void InterpreterImpl::cancelInvoke(const Arabica::DOM::Node<std::string>& elemen
}
USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId)
-
+ _invokers[invokeId].uninvoke();
_invokers.erase(invokeId);
USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId)
@@ -1689,8 +1685,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
try {
if (!_dataModel.isDeclared(ATTR(content, "location"))) {
// test 286, 331
- LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl;
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Assigning to undeclared location '" + ATTR(content, "location") + "' not allowed.");
} else {
Node<std::string> dom;
std::string text;
@@ -1745,7 +1740,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
try {
_dataModel.eval((Element<std::string>)content, srcContent.str());
}
- CATCH_AND_DISTRIBUTE("Syntax error while executing script element from '" << ATTR(content, "src") << "':")
+ CATCH_AND_DISTRIBUTE("Syntax error while executing script element from '" + ATTR(content, "src") + "':")
} else {
if (content.hasChildNodes()) {
// search for the text node with the actual script
@@ -1791,16 +1786,9 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
// --- Custom Executable Content
ExecutableContent execContent;
if (_executableContent.find(content) == _executableContent.end()) {
- execContent = _factory->createExecutableContent(content.getLocalName(), content.getNamespaceURI(), this);
- if (!execContent) {
- LOG(ERROR) << "No custom executable content known for element '"
- << content.getLocalName() << "' in namespace '" << content.getNamespaceURI() << "'";
- return;
- }
- _executableContent[content] = execContent;
- } else {
- execContent = _executableContent[content];
+ _executableContent[content] = _factory->createExecutableContent(content.getLocalName(), content.getNamespaceURI(), this);
}
+ execContent = _executableContent[content];
execContent.enterElement(content);
if (execContent.processChildren()) {
@@ -2005,13 +1993,8 @@ Arabica::DOM::Node<std::string> InterpreterImpl::getState(const std::string& sta
if (target.size() > 0)
goto FOUND;
- LOG(ERROR) << "No state with id " << stateId << " found!";
{
- Event ev;
- ev.name = "error.execution";
- ev.eventType = Event::PLATFORM;
- ev.data.compound["cause"] = Data("No state with id " + stateId + " found", Data::VERBATIM);
- throw ev;
+ ERROR_EXECUTION_THROW("No state with id '" + stateId + "' found");
}
FOUND:
if (target.size() > 0) {
@@ -2403,6 +2386,7 @@ void InterpreterImpl::setupIOProcessors() {
continue;
}
+ // this might throw error.execution
_ioProcessors[ioProcIter->first] = _factory->createIOProcessor(ioProcIter->first, this);
_ioProcessors[ioProcIter->first].setType(ioProcIter->first);
_ioProcessors[ioProcIter->first].setInterpreter(this);
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index a07d9af..cf281b5 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -46,6 +46,11 @@
#include "uscxml/plugins/Invoker.h"
#include "uscxml/plugins/ExecutableContent.h"
+#define ERROR_PLATFORM_THROW(msg) \
+ Event e; \
+ e.name = "error.platform"; \
+ e.data.compound["cause"] = Data(msg, Data::VERBATIM); \
+ throw e; \
#define USCXML_MONITOR_CATCH(callback) \
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index aaf4cde..08135fd 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -364,19 +364,19 @@ const void URLImpl::download(bool blocking) {
_condVar.wait(_mutex); // wait for notification
}
if (_hasFailed) {
- Event exception;
- exception.name = "error.communication";
- exception.data = URL(shared_from_this());
+ ERROR_COMMUNICATION(exc, _error);
+ exc.data = URL(shared_from_this());
if (_error.length() > 0)
- exception.data.compound["reason"] = Data(_error, Data::VERBATIM);
- throw exception;
+ exc.data.compound["cause"] = Data(_error, Data::VERBATIM);
+ throw exc;
}
if (iequals(scheme(), "http")) {
if (_statusCode.size() > 0 && boost::lexical_cast<int>(_statusCode) > 400) {
- Event exception;
- exception.name = "error.communication";
- exception.data = URL(shared_from_this());
- throw exception;
+ ERROR_COMMUNICATION(exc, _error);
+ exc.data = URL(shared_from_this());
+ if (_error.length() > 0)
+ exc.data.compound["cause"] = Data(_error, Data::VERBATIM);
+ throw exc;
}
}
}
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index dd23a87..048adf9 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -135,21 +135,23 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
NodeSet<std::string> initialTransitions = getDocumentInitialTransitions();
assert(initialTransitions.size() > 0);
enterStates(initialTransitions);
+ setInterpreterState(USCXML_MICROSTEPPED);
}
- _stable = false;
-
// are there spontaneous transitions?
- enabledTransitions = selectEventlessTransitions();
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
+ if (!_stable) {
+ enabledTransitions = selectEventlessTransitions();
+ if (!enabledTransitions.empty()) {
+ // test 403b
+ enabledTransitions.to_document_order();
+ microstep(enabledTransitions);
- setInterpreterState(USCXML_MICROSTEPPED);
- return _state;
+ setInterpreterState(USCXML_MICROSTEPPED);
+ return _state;
+ }
+ _stable = true;
}
-
+
// test415
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
@@ -158,6 +160,7 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
if (!_internalQueue.empty()) {
_currEvent = _internalQueue.front();
_internalQueue.pop_front();
+ _stable = false;
USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent)
@@ -178,14 +181,15 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
} else {
_stable = true;
}
- // even if we did nothing - count as microstep
- setInterpreterState(USCXML_MICROSTEPPED);
+
+ if (_state != USCXML_MACROSTEPPED && _state != USCXML_IDLE)
+ USCXML_MONITOR_CALLBACK(onStableConfiguration)
+
+ setInterpreterState(USCXML_MACROSTEPPED);
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
- setInterpreterState(USCXML_MACROSTEPPED);
- USCXML_MONITOR_CALLBACK(onStableConfiguration)
// when we reach a stable configuration, invoke
for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
@@ -227,7 +231,8 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
_currEvent = _externalQueue.pop();
_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
-
+ _stable = false;
+
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
@@ -350,149 +355,6 @@ void InterpreterDraft6::stabilize() {
}
-#if 0
-void InterpreterDraft6::mainEventLoop() {
-
- while(_running) {
- NodeSet<std::string> enabledTransitions;
- _stable = false;
-
- // Here we handle eventless transitions and transitions
- // triggered by internal events until machine is stable
- while(_running && !_stable) {
-#if VERBOSE
- std::cout << "Configuration: ";
- for (int i = 0; i < _configuration.size(); i++) {
- std::cout << ATTR(_configuration[i], "id") << ", ";
- }
- std::cout << std::endl;
-#endif
-
- enabledTransitions = selectEventlessTransitions();
- if (enabledTransitions.size() == 0) {
- if (_internalQueue.size() == 0) {
- _stable = true;
- } else {
- _currEvent = _internalQueue.front();
- _internalQueue.pop_front();
-#if VERBOSE
- std::cout << "Received internal event " << _currEvent.name << std::endl;
-#endif
-
- USCXML_MONITOR_CALLBACK(beforeProcessingEvent)
-
- if (_dataModel)
- _dataModel.setEvent(_currEvent);
- enabledTransitions = selectTransitions(_currEvent.name);
- }
- }
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
- }
- }
-
- for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
- NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]);
- for (unsigned int j = 0; j < invokes.size(); j++) {
- if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
- invoke(invokes[j]);
- }
- }
- }
- _statesToInvoke = NodeSet<std::string>();
-
- if (!_internalQueue.empty())
- continue;
-
- // assume that we have a legal configuration as soon as the internal queue is empty
- assert(hasLegalConfiguration());
-
- USCXML_MONITOR_CALLBACK(onStableConfiguration)
-
- _mutex.unlock();
-
- // whenever we have a stable configuration, run the mainThread hooks with 200fps
- while(_externalQueue.isEmpty() && _thread == NULL) {
- runOnMainThread(200);
- }
- _mutex.lock();
-
- while(_externalQueue.isEmpty()) {
- _condVar.wait(_mutex);
- }
- _currEvent = _externalQueue.pop();
-#if VERBOSE
- std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
- if (_running && _currEvent.name == "unblock.and.die") {
- std::cout << "Still running " << this << std::endl;
- } else {
- std::cout << "Aborting " << this << std::endl;
- }
-#endif
- _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
- if (!_running)
- goto EXIT_INTERPRETER;
-
- USCXML_MONITOR_CALLBACK(beforeProcessingEvent)
-
- if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId))
- break;
-
- if (_dataModel) {
- try {
- _dataModel.setEvent(_currEvent);
- } catch (Event e) {
- LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
- }
- }
- for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
- invokeIter != _invokers.end();
- invokeIter++) {
- if (iequals(invokeIter->first, _currEvent.invokeid)) {
- Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
- for (int k = 0; k < finalizes.size(); k++) {
- Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
- executeContent(finalizeElem);
- }
- }
- if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
- try {
- // do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
- // Yes do so, see test229!
- // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
- invokeIter->second.send(_currEvent);
- } catch(...) {
- LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
- }
- }
- }
- enabledTransitions = selectTransitions(_currEvent.name);
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
- }
- }
-
-EXIT_INTERPRETER:
- USCXML_MONITOR_CALLBACK(beforeCompletion)
-
- exitInterpreter();
- if (_sendQueue) {
- std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
- while(sendIter != _sendIds.end()) {
- _sendQueue->cancelEvent(sendIter->first);
- sendIter++;
- }
- }
-
- USCXML_MONITOR_CALLBACK(afterCompletion)
-
-}
-#endif
-
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const std::string& event) {
Arabica::XPath::NodeSet<std::string> enabledTransitions;
diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h
index bf13409..9b5bea7 100644
--- a/src/uscxml/messages/Data.h
+++ b/src/uscxml/messages/Data.h
@@ -141,6 +141,14 @@ public:
return data;
}
+ void put(std::string key, const Data& data) {
+ compound[key] = data;
+ }
+
+ void put(size_t index, const Data& data) {
+ this[index] = data;
+ }
+
bool operator==(const Data &other) const {
if (other.atom.size() != atom.size())
return false;
diff --git a/src/uscxml/messages/Event.cpp b/src/uscxml/messages/Event.cpp
index a3e6a20..f8a880f 100644
--- a/src/uscxml/messages/Event.cpp
+++ b/src/uscxml/messages/Event.cpp
@@ -155,6 +155,8 @@ std::ostream& operator<< (std::ostream& os, const Event& event) {
os << indent << " origin: " << event.origin << std::endl;
if (event.origintype.size() > 0)
os << indent << " origintype: " << event.origintype << std::endl;
+ if (event.content.size() > 0)
+ os << indent << " content: '" << event.content << "'" << std::endl;
if (event.params.size() > 0) {
std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin();
os << indent << " params:" << std::endl;
diff --git a/src/uscxml/messages/Event.h b/src/uscxml/messages/Event.h
index 1acfce7..6697bb9 100644
--- a/src/uscxml/messages/Event.h
+++ b/src/uscxml/messages/Event.h
@@ -22,6 +22,56 @@
#include "uscxml/messages/Data.h"
+#define ERROR_EXECUTION(identifier, cause) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.execution"; \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_EXECUTION2(identifier, cause, node) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.execution"; \
+ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_COMMUNICATION(identifier, cause) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.communication"; \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_COMMUNICATION2(identifier, cause, node) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.communication"; \
+ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_EXECUTION_THROW(cause) \
+{\
+ ERROR_EXECUTION(exc, cause); \
+ throw exc;\
+}
+
+#define ERROR_EXECUTION_THROW2(cause, node) \
+{\
+ ERROR_EXECUTION2(exc, cause, node); \
+ throw exc;\
+}
+
+#define ERROR_COMMUNICATION_THROW(cause) \
+{\
+ ERROR_COMMUNICATION(exc, cause); \
+ throw exc;\
+}
+
+#define ERROR_COMMUNICATION_THROW2(cause, node) \
+{\
+ ERROR_COMMUNICATION(exc, cause, node); \
+ throw exc;\
+}
+
namespace uscxml {
class USCXML_API Event {
@@ -145,6 +195,13 @@ public:
return params;
}
+ void setNameList(const std::map<std::string, Data>& nameList) {
+ this->namelist = nameList;
+ }
+ void setParams(const std::multimap<std::string, Data>& params) {
+ this->params = params;
+ }
+
typedef std::multimap<std::string, Data> params_t;
typedef std::map<std::string, Data> namelist_t;
diff --git a/src/uscxml/messages/InvokeRequest.cpp b/src/uscxml/messages/InvokeRequest.cpp
index a39c8c6..26d40ce 100644
--- a/src/uscxml/messages/InvokeRequest.cpp
+++ b/src/uscxml/messages/InvokeRequest.cpp
@@ -60,6 +60,7 @@ std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq) {
if (invokeReq.src.size() > 0)
os<< indent << " src: " << invokeReq.src << std::endl;
+#if 0
if (invokeReq.namelist.size() > 0) {
os << indent << " namelist: " << std::endl;
InvokeRequest::namelist_t::const_iterator namelistIter = invokeReq.namelist.begin();
@@ -80,6 +81,7 @@ std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq) {
if (invokeReq.content.size() > 0)
os << indent << " content: " << invokeReq.content << std::endl;
+#endif
_dataIndentation++;
os << (Event)invokeReq;
diff --git a/src/uscxml/messages/SendRequest.cpp b/src/uscxml/messages/SendRequest.cpp
index a8fbe13..497182c 100644
--- a/src/uscxml/messages/SendRequest.cpp
+++ b/src/uscxml/messages/SendRequest.cpp
@@ -103,7 +103,7 @@ std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) {
if (sendReq.delayMs > 0)
os<< indent << " delay: " << sendReq.delayMs << std::endl;
-
+#if 0
if (sendReq.namelist.size() > 0) {
os << indent << " namelist: " << std::endl;
SendRequest::namelist_t::const_iterator namelistIter = sendReq.namelist.begin();
@@ -124,7 +124,7 @@ std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) {
if (sendReq.content.size() > 0)
os << indent << " content: " << sendReq.content << std::endl;
-
+#endif
_dataIndentation++;
os << (Event)sendReq;
_dataIndentation--;
diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h
index 57d4b14..f142a60 100644
--- a/src/uscxml/plugins/DataModel.h
+++ b/src/uscxml/plugins/DataModel.h
@@ -86,10 +86,6 @@ public:
return "";
}
- static void throwErrorExecution(const std::string& cause);
- static void throwErrorPlatform(const std::string& cause);
-
- // we need it public for various static functions
protected:
InterpreterImpl* _interpreter;
};
diff --git a/src/uscxml/plugins/EventHandler.h b/src/uscxml/plugins/EventHandler.h
index d30feb9..7b38575 100644
--- a/src/uscxml/plugins/EventHandler.h
+++ b/src/uscxml/plugins/EventHandler.h
@@ -62,9 +62,9 @@ public:
virtual void send(const SendRequest& req) = 0;
virtual void runOnMainThread() {};
- void returnEvent(Event& event);
+ void returnEvent(Event& event, bool external = false);
void returnErrorExecution(const std::string&);
- void returnErrorPlatform(const std::string&);
+ void returnErrorCommunication(const std::string&);
protected:
InterpreterImpl* _interpreter;
diff --git a/src/uscxml/plugins/Invoker.h b/src/uscxml/plugins/Invoker.h
index c967331..4a142e4 100644
--- a/src/uscxml/plugins/Invoker.h
+++ b/src/uscxml/plugins/Invoker.h
@@ -33,6 +33,7 @@ class USCXML_API InvokerImpl : public EventHandlerImpl {
public:
virtual ~InvokerImpl() {}
virtual void invoke(const InvokeRequest& req) = 0;
+ virtual void uninvoke() {}
virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) = 0;
};
@@ -65,6 +66,10 @@ public:
_impl->invoke(req);
}
+ virtual void uninvoke() {
+ _impl->uninvoke();
+ }
+
protected:
boost::shared_ptr<InvokerImpl> _impl;
};
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index b2fce62..6dc8c26 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -452,12 +452,7 @@ uint32_t JSCDataModel::getLength(const std::string& expr) {
result = evalAsValue("(" + expr + ").length");
JSType type = JSValueGetType(_ctx, result);
if (type == kJSTypeNull || type == kJSTypeUndefined) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
-
- throw(exceptionEvent);
+ ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
}
JSValueRef exception = NULL;
@@ -549,20 +544,20 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
} else if (HAS_ATTR(assignElem, "location")) {
key = ATTR(assignElem, "location");
}
- if (key.length() == 0)
- throw Event("error.execution", Event::PLATFORM);
-
+ if (key.length() == 0) {
+ ERROR_EXECUTION_THROW("Assign element has neither id nor location");
+ }
// flags on attribute are ignored?
if (key.compare("_sessionid") == 0) // test 322
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _sessionId");
if (key.compare("_name") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _name");
if (key.compare("_ioprocessors") == 0) // test 326
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _ioprocessors");
if (key.compare("_invokers") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _invokers");
if (key.compare("_event") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _event");
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
@@ -666,13 +661,7 @@ void JSCDataModel::handleException(JSValueRef exception) {
JSStringRelease(exceptionStringRef);
std::string exceptionMsg(buffer);
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(exceptionMsg, Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
-
- throw(exceptionEvent);
-
+ ERROR_EXECUTION_THROW(exceptionMsg);
}
JSValueRef JSCDataModel::jsPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
index 98d2dda..45d7a5c 100644
--- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
@@ -65,7 +65,10 @@ void NULLDataModel::setEvent(const Event& event) {
}
Data NULLDataModel::getStringAsData(const std::string& content) {
- Data data;
+ Data data = Data::fromJSON(content);
+ if (data.empty()) {
+ data = Data(content, Data::VERBATIM);
+ }
return data;
}
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
index ad0c42b..8f5e588 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
@@ -37,10 +37,7 @@ extern "C" {
}
#define RETHROW_PLEX_AS_EVENT \
catch (PlException plex) { \
- Event e; \
- e.name = "error.execution"; \
- e.data.compound["cause"] = (char*)plex; \
- throw e; \
+ ERROR_EXECUTION_THROW((char*)plex); \
} \
#define PL_MODULE \
@@ -733,10 +730,7 @@ std::string SWIDataModel::evalAsString(const std::string& expr) {
if (term.type() == PL_ATOM || term.type() == PL_CHARS || term.type() == PL_STRING) {
return std::string(term);
} else {
- Event e;
- e.name = "error.execution";
- e.data.compound["cause"] = (char*)plex;
- throw e;
+ ERROR_EXECUTION_THROW((char*)plex);
}
}
}
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
index 8bfc39d..4300512 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
@@ -100,11 +100,11 @@ bool PromelaDataModel::validate(const std::string& location, const std::string&
uint32_t PromelaDataModel::getLength(const std::string& expr) {
if (!isDeclared(expr)) {
- throwErrorExecution("Variable " + expr + " was not declared");
+ ERROR_EXECUTION_THROW("Variable '" + expr + "' was not declared");
}
if (!_variables[expr].hasKey("size")) {
- throwErrorExecution("Variable " + expr + " is no array");
+ ERROR_EXECUTION_THROW("Variable '" + expr + "' is no array");
}
return strTo<int>(_variables[expr]["size"].atom);
@@ -216,7 +216,7 @@ void PromelaDataModel::evaluateDecl(void* ast) {
_variables.compound[name->value] = variable;
} else {
- throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
+ ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
}
}
assert(opIter == node->operands.end());
@@ -227,7 +227,7 @@ void PromelaDataModel::evaluateDecl(void* ast) {
evaluateDecl(*declIter);
}
} else {
- throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
+ ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
}
}
@@ -269,7 +269,7 @@ int PromelaDataModel::evaluateExpr(void* ast) {
case PML_OR:
return evaluateExpr(*opIter++) != 0 || evaluateExpr(*opIter++) != 0;
default:
- throwErrorExecution("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
+ ERROR_EXECUTION_THROW("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
}
return 0;
}
@@ -291,7 +291,7 @@ void PromelaDataModel::evaluateStmnt(void* ast) {
break;
}
default:
- throwErrorExecution("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
+ ERROR_EXECUTION_THROW("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
}
}
@@ -306,15 +306,15 @@ void PromelaDataModel::setVariable(void* ast, int value) {
int index = evaluateExpr(expr);
if (_variables.compound.find(name->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + name->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
}
if (!_variables[name->value].hasKey("size")) {
- throwErrorExecution("Variable " + name->value + " is no array");
+ ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
}
if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
- throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
}
_variables.compound[name->value].compound["value"][index] = Data(value, Data::VERBATIM);
@@ -339,10 +339,10 @@ int PromelaDataModel::getVariable(void* ast) {
switch(node->type) {
case PML_NAME:
if (_variables.compound.find(node->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + node->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + node->value + " was declared");
}
if (_variables[node->value].compound.find("size") != _variables[node->value].compound.end()) {
- throwErrorExecution("Type error: Variable " + node->value + " is an array");
+ ERROR_EXECUTION_THROW("Type error: Variable " + node->value + " is an array");
}
return strTo<int>(_variables[node->value]["value"].atom);
case PML_VAR_ARRAY: {
@@ -351,20 +351,20 @@ int PromelaDataModel::getVariable(void* ast) {
int index = evaluateExpr(expr);
if (_variables.compound.find(name->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + name->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
}
if (!_variables[name->value].hasKey("size")) {
- throwErrorExecution("Variable " + name->value + " is no array");
+ ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
}
if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
- throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
}
return strTo<int>(_variables.compound[name->value].compound["value"][index].atom);
}
default:
- throwErrorExecution("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
+ ERROR_EXECUTION_THROW("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
}
return 0;
}
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
index cd3bbaf..d12b7fc 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
@@ -19,6 +19,7 @@
#include "PromelaParser.h"
#include "parser/promela.tab.hpp"
+#include "uscxml/messages/Event.h"
#include <iostream>
@@ -35,10 +36,7 @@ int promela_lex_destroy (void*);
void promela_error (uscxml::PromelaParser* ctx, void* yyscanner, const char* err) {
// mark as pending exception as we cannot throw from constructor and have the destructor called
- uscxml::Event excEvent;
- excEvent.data.compound["exception"] = uscxml::Data(err, uscxml::Data::VERBATIM);
- excEvent.name = "error.execution";
- excEvent.eventType = uscxml::Event::PLATFORM;
+ ERROR_EXECUTION(excEvent, err);
ctx->pendingException = excEvent;
}
@@ -53,12 +51,7 @@ PromelaParser::PromelaParser(const std::string& expr, Type expectedType) {
if (type != expectedType) {
std::stringstream ss;
ss << "Promela syntax type mismatch: Expected " << typeToDesc(expectedType) << " but got " << typeToDesc(type);
-
- uscxml::Event excEvent;
- excEvent.data.compound["exception"] = uscxml::Data(ss.str(), uscxml::Data::VERBATIM);
- excEvent.name = "error.execution";
- excEvent.eventType = uscxml::Event::PLATFORM;
- throw excEvent;
+ ERROR_EXECUTION_THROW(ss.str());
}
}
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
index 4d9854b..5800f98 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
@@ -296,9 +296,7 @@ uint32_t XPathDataModel::getLength(const std::string& expr) {
return result.asNodeSet().size();
break;
default:
- Event exceptionEvent("error.execution", Event::PLATFORM);
- exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);
- throw(exceptionEvent);
+ ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
}
return 0;
}
@@ -326,7 +324,7 @@ void XPathDataModel::setForeach(const std::string& item,
if (!isDeclared(item)) {
if (!isValidIdentifier(item))
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Expression '" + item + "' not a valid identifier.");
Element<std::string> container = _doc.createElement("data");
container.setAttribute("id", item);
container.appendChild(arrayResult.asNodeSet()[iteration].cloneNode(true));
@@ -400,9 +398,9 @@ bool XPathDataModel::evalAsBool(const Arabica::DOM::Node<std::string>& node, con
try {
result = _xpath.evaluate_expr(expr, _doc);
} catch(SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
} catch(std::runtime_error e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
return result.asBool();
}
@@ -413,9 +411,9 @@ std::string XPathDataModel::evalAsString(const std::string& expr) {
try {
result = _xpath.evaluate_expr(expr, _doc);
} catch(SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
} catch(std::runtime_error e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
switch (result.type()) {
case STRING:
@@ -440,7 +438,7 @@ std::string XPathDataModel::evalAsString(const std::string& expr) {
break;
}
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY not supported to evaluate as string");
break;
}
return "undefined";
@@ -472,13 +470,13 @@ void XPathDataModel::assign(const Element<std::string>& assignElem,
for (int i = 0; i < key.asNodeSet().size(); i++) {
Node<std::string> node = key.asNodeSet()[i];
if (node == _varResolver.resolveVariable("", "_ioprocessors").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _ioProcessors");
if (node == _varResolver.resolveVariable("", "_sessionid").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _sessionid");
if (node == _varResolver.resolveVariable("", "_name").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _name");
if (node == _varResolver.resolveVariable("", "_event").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _event");
}
} catch (Event e) {}
}
@@ -570,11 +568,11 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
}
case Arabica::XPath::BOOL:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("expr evaluates to type ANY");
}
_datamodel.appendChild(container);
} catch (SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
} else {
LOG(ERROR) << "data element has no content";
@@ -595,7 +593,7 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
switch (key.type()) {
case NODE_SET:
if (key.asNodeSet().size() == 0) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("key for assign is empty nodeset");
}
switch (value.type()) {
case STRING:
@@ -611,14 +609,14 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
assign(key.asNodeSet(), value.asNodeSet(), assignElem);
break;
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported");
}
break;
case STRING:
case Arabica::XPath::BOOL:
case NUMBER:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported")
break;
}
}
@@ -637,7 +635,7 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
case Arabica::XPath::BOOL:
case NUMBER:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported")
}
}
@@ -665,7 +663,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
// addattribute: Add an attribute with the name specified by 'attr'
// and value specified by 'expr' to the node specified by 'location'.
if (!HAS_ATTR(assignElem, "attr"))
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Assign element is missing 'attr'")
element.setAttribute(ATTR(assignElem, "attr"), value);
} else {
/// test 547
@@ -677,7 +675,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
break;
}
default:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Unsupported node type with assign");
break;
}
}
@@ -709,7 +707,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
break;
default:
// std::cout << key[i].getNodeType() << std::endl;
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Unsupported node type for assign");
break;
}
}
@@ -740,7 +738,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
// node specified by 'location', keeping the same parent.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
for (int i = 0; i < value.size(); i++) {
Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
parent.insertBefore(importedNode, element);
@@ -750,7 +748,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
// specified by 'location', keeping the same parent.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
for (int i = value.size(); i; i--) {
Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
Node<std::string> nextSibling = element.getNextSibling();
@@ -764,16 +762,16 @@ void XPathDataModel::assign(const Element<std::string>& key,
// replace: Replace the node specified by 'location' by the value specified by 'expr'.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
if (value.size() != 1)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Value not singular");
Node<std::string> importedNode = (value[0].getOwnerDocument() == _doc ? value[0].cloneNode(true) : _doc.importNode(value[0], true));
parent.replaceChild(importedNode, element);
} else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "delete")) {
// delete: Delete the node specified by 'location'. ('expr' is ignored.).
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
parent.removeChild(element);
} else {
// replacechildren: Replace all the children at 'location' with the value specified by 'expr'.
@@ -791,7 +789,7 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri,
const std::string& name) const {
std::map<std::string, NodeSet<std::string> >::const_iterator n = _variables.find(name);
if(n == _variables.end()) {
- throw Event("error.execution");
+ ERROR_EXECUTION_THROW("No varable named '" + name + "'");
}
#if VERBOSE
std::cout << std::endl << "Getting " << name << ":" << std::endl;
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 5ee7357..bd62467 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -157,7 +157,7 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) {
if (reqEvent.name.length() == 0)
reqEvent.name = "http." + req.data.compound.at("type").atom;
- returnEvent(reqEvent);
+ returnEvent(reqEvent, true);
evhttp_send_reply(req.evhttpReq, 200, "OK", NULL);
return true;
}
@@ -287,7 +287,7 @@ void BasicHTTPIOProcessor::downloadCompleted(const URL& url) {
Event event;
event.data = url;
event.name = "HTTP." + statusPrefix + "." + statusRest;
- returnEvent(event);
+// returnEvent(event);
}
_sendRequests.erase(reqIter);
return;
diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
index becc00a..00b47f4 100644
--- a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
@@ -129,10 +129,10 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
boost::shared_ptr<InterpreterImpl> other = instances[sessionId].lock();
other->receive(reqCopy);
} else {
- LOG(ERROR) << "Can not send to scxml session " << sessionId << " - not known" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to scxml session " + sessionId + " - not known");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
+
}
} else if (iequals(reqCopy.target, "#_parent")) {
/**
@@ -143,8 +143,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
if (_interpreter->_parentQueue != NULL) {
_interpreter->_parentQueue->push(reqCopy);
} else {
- LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to parent, we were not invoked or no parent queue is set");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
}
@@ -167,8 +166,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId;
}
} else {
- LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to invoked component '" + invokeId + "', no such invokeId");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
}
@@ -177,8 +175,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
if (target.isAbsolute()) {
BasicHTTPIOProcessor::send(reqCopy);
} else {
- LOG(ERROR) << "Not sure what to make of the target '" << reqCopy.target << "' - raising error" << std::endl;
- Event error("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION(error, "Not sure what to make of the target '" + reqCopy.target + "' - raising error");
error.sendid = reqCopy.sendid;
// test 159 still fails
// _interpreter->receiveInternal(error);
diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp
index 3bce169..fea97d8 100644
--- a/src/uscxml/transform/ChartToFSM.cpp
+++ b/src/uscxml/transform/ChartToFSM.cpp
@@ -972,9 +972,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t
for (int i = 0; i < transitions.size(); i++) {
if (HAS_ATTR(transitions[i], "eventexpr")) {
- Event e("error.execution", Event::PLATFORM);
- e.data.compound["cause"] = "Cannot flatten document with eventexpr attributes";
- throw e;
+ ERROR_EXECUTION_THROW("Cannot flatten document with eventexpr attributes");
}
if (HAS_ATTR(transitions[i], "event")) {
foundWithEvent = true;
diff --git a/test/src/test-lifecycle.cpp b/test/src/test-lifecycle.cpp
index 4c044c4..c0fb55c 100644
--- a/test/src/test-lifecycle.cpp
+++ b/test/src/test-lifecycle.cpp
@@ -88,8 +88,115 @@ void customTerminate() {
#endif
abort();
}
+
+using namespace uscxml;
+
+enum CallbackType {
+ USCXML_BEFOREPROCESSINGEVENT,
+ USCXML_BEFOREMICROSTEP,
+ USCXML_BEFOREEXITINGSTATE,
+ USCXML_AFTEREXITINGSTATE,
+ USCXML_BEFOREEXECUTINGCONTENT,
+ USCXML_AFTEREXECUTINGCONTENT,
+ USCXML_BEFOREUNINVOKING,
+ USCXML_AFTERUNINVOKING,
+ USCXML_BEFORETAKINGTRANSITION,
+ USCXML_AFTERTAKINGTRANSITION,
+ USCXML_BEFOREENTERINGSTATE,
+ USCXML_AFTERENTERINGSTATE,
+ USCXML_BEFOREINVOKING,
+ USCXML_AFTERINVOKING,
+ USCXML_AFTERMICROSTEP,
+ USCXML_ONSTABLECONFIGURATION,
+ USCXML_BEFORECOMPLETION,
+ USCXML_AFTERCOMPLETION
+};
+
+std::list<CallbackType> callBackSeq;
+
+#define CHECK_CALLBACK_TYPE(type)\
+{\
+ assert(!callBackSeq.empty());\
+ assert(callBackSeq.front() == type);\
+ callBackSeq.pop_front();\
+}
+
+
+class SequenceCheckingMonitor : public InterpreterMonitor {
+ virtual void beforeProcessingEvent(Interpreter interpreter, const Event& event) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREPROCESSINGEVENT);
+ }
+ virtual void beforeMicroStep(Interpreter interpreter) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREMICROSTEP);
+ }
+
+ virtual void beforeExitingState(Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREEXITINGSTATE);
+ }
+ virtual void afterExitingState(Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_AFTEREXITINGSTATE);
+ }
+
+ virtual void beforeExecutingContent(Interpreter interpreter, const Arabica::DOM::Element<std::string>& element) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREEXECUTINGCONTENT);
+ }
+ virtual void afterExecutingContent(Interpreter interpreter, const Arabica::DOM::Element<std::string>& element) {
+ CHECK_CALLBACK_TYPE(USCXML_AFTEREXECUTINGCONTENT);
+ }
+
+ virtual void beforeUninvoking(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string& invokeid) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREUNINVOKING);
+ }
+ virtual void afterUninvoking(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string& invokeid) {
+ CHECK_CALLBACK_TYPE(USCXML_AFTERUNINVOKING);
+ }
+
+ virtual void beforeTakingTransition(Interpreter interpreter, const Arabica::DOM::Element<std::string>& transition, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_BEFORETAKINGTRANSITION);
+ }
+ virtual void afterTakingTransition(Interpreter interpreter, const Arabica::DOM::Element<std::string>& transition, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_AFTERTAKINGTRANSITION);
+ }
+
+ virtual void beforeEnteringState(Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREENTERINGSTATE);
+ }
+ virtual void afterEnteringState(Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) {
+ if (!moreComing)
+ CHECK_CALLBACK_TYPE(USCXML_AFTERENTERINGSTATE);
+ }
+
+ virtual void beforeInvoking(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string& invokeid) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFOREINVOKING);
+ }
+ virtual void afterInvoking(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string& invokeid) {
+ CHECK_CALLBACK_TYPE(USCXML_AFTERINVOKING);
+ }
+
+ virtual void afterMicroStep(Interpreter interpreter) {
+ CHECK_CALLBACK_TYPE(USCXML_AFTERMICROSTEP);
+ }
+
+ virtual void onStableConfiguration(Interpreter interpreter) {
+ CHECK_CALLBACK_TYPE(USCXML_ONSTABLECONFIGURATION);
+ }
+
+ virtual void beforeCompletion(Interpreter interpreter) {
+ CHECK_CALLBACK_TYPE(USCXML_BEFORECOMPLETION);
+ }
+ virtual void afterCompletion(Interpreter interpreter) {
+ CHECK_CALLBACK_TYPE(USCXML_AFTERCOMPLETION);
+ }
+
+};
+
+
int main(int argc, char** argv) {
- using namespace uscxml;
std::set_terminate(customTerminate);
@@ -99,80 +206,213 @@ int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
google::LogToStderr();
- InterpreterState state;
+ SequenceCheckingMonitor* mon = new SequenceCheckingMonitor();
+
int iterations = 1;
while(iterations--) {
if (1) {
// syntactic xml parse error
- const char* xml = "<invalid>";
- Interpreter interpreter = Interpreter::fromXML(xml);
- state = interpreter.getState();
- assert(!interpreter);
- assert(state == uscxml::InterpreterState::USCXML_FAULTED);
- std::cout << interpreter.getState() << std::endl;
+ try {
+ const char* xml = "<invalid";
+ Interpreter interpreter = Interpreter::fromXML(xml);
+ assert(false);
+ } catch (Event& e) {
+ std::cout << e;
+ }
}
if (1) {
// semantic xml parse error
- const char* xml = "<invalid />";
- Interpreter interpreter = Interpreter::fromXML(xml);
- state = interpreter.getState();
- assert(state == uscxml::InterpreterState::USCXML_INSTANTIATED);
+ try {
+ const char* xml = "<invalid />";
+ Interpreter interpreter = Interpreter::fromXML(xml);
+ interpreter.addMonitor(mon);
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ interpreter.step();
+ assert(false);
+ } catch (Event& e) {
+ std::cout << e;
+ }
+ }
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FAULTED);
- std::cout << interpreter.getState() << std::endl;
+ if (1) {
+ // request unknown datamodel
+ try {
+ const char* xml =
+ "<scxml datamodel=\"invalid\">"
+ " <state id=\"start\">"
+ " <transition target=\"done\" />"
+ " </state>"
+ " <final id=\"done\" />"
+ "</scxml>";
+ Interpreter interpreter = Interpreter::fromXML(xml);
+ interpreter.addMonitor(mon);
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ interpreter.step();
+ assert(false);
+ } catch (Event& e) {
+ std::cout << e;
+ }
}
if (1) {
+ // two microsteps
+ const char* xml =
+ "<scxml>"
+ " <state id=\"start\">"
+ " <transition target=\"s2\" />"
+ " </state>"
+ " <state id=\"s2\">"
+ " <transition target=\"done\" />"
+ " </state>"
+ " <final id=\"done\" />"
+ "</scxml>";
+
+ Interpreter interpreter = Interpreter::fromXML(xml);
+ interpreter.addMonitor(mon);
+
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFORECOMPLETION);
+ callBackSeq.push_back(USCXML_AFTERCOMPLETION);
+
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ assert(interpreter.step() == USCXML_MICROSTEPPED);
+ assert(interpreter.step() == USCXML_MICROSTEPPED);
+ assert(interpreter.step() == USCXML_FINISHED);
+ assert(callBackSeq.empty());
+ }
+
+ if (1) {
// single macrostep, multiple runs
const char* xml =
- "<scxml>"
- " <state id=\"start\">"
- " <transition target=\"done\" />"
- " </state>"
- " <final id=\"done\" />"
- "</scxml>";
-
+ "<scxml>"
+ " <state id=\"start\">"
+ " <transition target=\"done\" />"
+ " </state>"
+ " <final id=\"done\" />"
+ "</scxml>";
+
Interpreter interpreter = Interpreter::fromXML(xml);
- assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED);
- interpreter.reset();
- assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED);
- interpreter.reset();
- assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED);
+ interpreter.addMonitor(mon);
+
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFORECOMPLETION);
+ callBackSeq.push_back(USCXML_AFTERCOMPLETION);
+
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ assert(interpreter.step() == USCXML_MICROSTEPPED);
+ assert(interpreter.step() == USCXML_FINISHED);
interpreter.reset();
- assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED);
- }
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFORECOMPLETION);
+ callBackSeq.push_back(USCXML_AFTERCOMPLETION);
+
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ assert(interpreter.step() == USCXML_MICROSTEPPED);
+ assert(interpreter.step() == USCXML_FINISHED);
+ }
+
if (1) {
- // two microsteps
+ // macrostep in between
const char* xml =
- "<scxml>"
- " <state id=\"start\">"
- " <transition target=\"s2\" />"
- " </state>"
- " <state id=\"s2\">"
- " <transition target=\"done\" />"
- " </state>"
- " <final id=\"done\" />"
- "</scxml>";
-
+ "<scxml>"
+ " <state id=\"start\">"
+ " <onentry>"
+ " <send event=\"continue\" delay=\"2s\"/>"
+ " </onentry>"
+ " <transition target=\"s2\" event=\"continue\" />"
+ " </state>"
+ " <state id=\"s2\">"
+ " <transition target=\"done\" />"
+ " </state>"
+ " <final id=\"done\" />"
+ "</scxml>";
+
Interpreter interpreter = Interpreter::fromXML(xml);
-
- assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED);
- assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED);
+ interpreter.addMonitor(mon);
+
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_BEFOREEXECUTINGCONTENT);
+ callBackSeq.push_back(USCXML_AFTEREXECUTINGCONTENT);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_ONSTABLECONFIGURATION);
+
+ callBackSeq.push_back(USCXML_BEFOREPROCESSINGEVENT);
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
+ callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
+ callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
+ callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
+ callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
+ callBackSeq.push_back(USCXML_AFTERMICROSTEP);
+
+ callBackSeq.push_back(USCXML_BEFORECOMPLETION);
+ callBackSeq.push_back(USCXML_AFTERCOMPLETION);
+
+ assert(interpreter.getState() == USCXML_INSTANTIATED);
+ assert(interpreter.step() == USCXML_IDLE);
+ assert(interpreter.step(true) == USCXML_MACROSTEPPED);
+ assert(interpreter.step() == USCXML_MICROSTEPPED);
+ assert(interpreter.step() == USCXML_FINISHED);
}
+
+#if 0
+
if (0) {
// macrostep in between
@@ -271,7 +511,7 @@ int main(int argc, char** argv) {
assert(!(state & InterpreterState::USCXML_THREAD_RUNNING));
}
+#endif
}
-
return EXIT_SUCCESS;
} \ No newline at end of file
diff --git a/test/w3c/confEcma.xsl b/test/w3c/confEcma.xsl
index af3c8d2..ffc922d 100644
--- a/test/w3c/confEcma.xsl
+++ b/test/w3c/confEcma.xsl
@@ -165,6 +165,8 @@
<content xmlns="http://www.w3.org/2005/07/scxml">foo</content>
</xsl:template>
+
+
<!-- this returns something that is guaranteed not to be the ID of the current session -->
<xsl:template match="//@conf:invalidSessionID">
<xsl:attribute name="expr">27</xsl:attribute>
@@ -241,8 +243,14 @@
</xsl:template>
<!-- delayexpr takes the value of the specified variable -->
-<xsl:template match="//@conf:delayExpr">
- <xsl:attribute name="delayexpr">Var<xsl:value-of select="." /></xsl:attribute>
+<xsl:template match="//@conf:delayFromVar">
+ <xsl:attribute name="delayexpr">(Var<xsl:value-of select="." />.slice(0, - 1)) * 50 + 'ms'</xsl:attribute>
+</xsl:template>
+
+<!-- computes a delayexpr based on the value passed in. this lets platforms determine how long to delay timeout
+events which cause the test to fail. The default value provided here is pretty long -->
+<xsl:template match="//@conf:delay">
+ <xsl:attribute name="delayexpr">'<xsl:value-of select=". * 50"/>ms'</xsl:attribute>
</xsl:template>
<!-- the specified variable is used as idlocation -->
@@ -722,4 +730,4 @@ it allows anything after the = -->
<xsl:template match="//@conf:msgIsBody">
<xsl:attribute name="cond">_event.raw.match(/\n\naddress=(.*)$/)</xsl:attribute>
</xsl:template>
-</xsl:stylesheet> \ No newline at end of file
+</xsl:stylesheet>
diff --git a/test/w3c/confXPath.xsl b/test/w3c/confXPath.xsl
index fa67f3b..71286ce 100644
--- a/test/w3c/confXPath.xsl
+++ b/test/w3c/confXPath.xsl
@@ -206,6 +206,7 @@ is of the same type as array123 -->
+
<!-- this returns something that is guaranteed not to be the ID of the current session -->
<xsl:template match="//@conf:invalidSessionID">
<xsl:attribute name="expr">27</xsl:attribute>
@@ -239,10 +240,16 @@ is of the same type as array123 -->
</xsl:template>
<!-- delayexpr takes the value of the specified variable -->
-<xsl:template match="//@conf:delayExpr">
+<xsl:template match="//@conf:delayFromVar">
<xsl:attribute name="delayexpr">$Var<xsl:value-of select="." /></xsl:attribute>
</xsl:template>
+<!-- returns a delayexpr. this lets platforms determine how long to delay timeout
+events which cause the test to fail. The default value provided here is pretty long -->
+<xsl:template match="//@conf:delay">
+ <xsl:attribute name="delayexpr">'<xsl:value-of select="."/>s'</xsl:attribute>
+</xsl:template>
+
<!-- the specified variable is used as idlocation -->
<xsl:template match="//@conf:idlocation">
<xsl:attribute name="idlocation">$Var<xsl:value-of select="." /></xsl:attribute>
diff --git a/test/w3c/ecma/test175.scxml b/test/w3c/ecma/test175.scxml
index 4876821..cda3b5a 100644
--- a/test/w3c/ecma/test175.scxml
+++ b/test/w3c/ecma/test175.scxml
@@ -7,9 +7,9 @@ event1 will be raised first. Succeed if event1 occurs before event2, otherwise
<state id="s0">
<onentry>
- <assign location="Var1" expr="'3s'"/>
- <send delayexpr="Var1" event="event2"/>
- <send delay="1s" event="event1"/>
+ <assign location="Var1" expr="'1s'"/>
+ <send delayexpr="(Var1.slice(0, - 1)) * 50 + 'ms'" event="event2"/>
+ <send delayexpr="'25ms'" event="event1"/>
</onentry>
<transition event="event1" target="s1"/>
diff --git a/test/w3c/ecma/test185.scxml b/test/w3c/ecma/test185.scxml
index cdf8a77..6a83574 100644
--- a/test/w3c/ecma/test185.scxml
+++ b/test/w3c/ecma/test185.scxml
@@ -4,7 +4,7 @@
<state id="s0">
<onentry>
- <send event="event2" delay="2s"/>
+ <send event="event2" delayexpr="'50ms'"/>
<send event="event1"/>
</onentry>
diff --git a/test/w3c/ecma/test186.scxml b/test/w3c/ecma/test186.scxml
index 20f0063..68254d3 100644
--- a/test/w3c/ecma/test186.scxml
+++ b/test/w3c/ecma/test186.scxml
@@ -8,7 +8,7 @@ in the interval.) If var2 ends up == 1, we pass. Otherwise we fail --><scxml
<state id="s0">
<onentry>
- <send event="event1" delay="2s">
+ <send event="event1" delayexpr="'50ms'">
<param name="aParam" expr="Var1"/>
</send>
<assign location="Var1" expr="2"/>
diff --git a/test/w3c/ecma/test187.scxml b/test/w3c/ecma/test187.scxml
index d03c16d..c4f2a6f 100644
--- a/test/w3c/ecma/test187.scxml
+++ b/test/w3c/ecma/test187.scxml
@@ -6,7 +6,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<state id="s0">
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" delayexpr="'50ms'"/>
</onentry>
<invoke type="scxml">
<content>
@@ -14,7 +14,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<scxml initial="sub0" version="1.0" datamodel="ecmascript">
<state id="sub0">
<onentry>
- <send event="childToParent" target="#_parent" delay="1s"/>
+ <send event="childToParent" target="#_parent" delayexpr="'25ms'"/>
</onentry>
<transition target="subFinal"/>
</state>
diff --git a/test/w3c/ecma/test207.scxml b/test/w3c/ecma/test207.scxml
index aa5786a..fe30bf1 100644
--- a/test/w3c/ecma/test207.scxml
+++ b/test/w3c/ecma/test207.scxml
@@ -6,7 +6,7 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" delayexpr="'100ms'"/>
</onentry>
<invoke type="scxml">
<content>
@@ -18,8 +18,8 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<scxml initial="sub0" version="1.0" datamodel="ecmascript">
<state id="sub0">
<onentry>
- <send event="event1" id="foo" delay="3s"/>
- <send event="event2" delay="5s"/>
+ <send event="event1" id="foo" delayexpr="'50ms'"/>
+ <send event="event2" delayexpr="'75ms'"/>
<send target="#_parent" event="childToParent"/>
</onentry>
diff --git a/test/w3c/ecma/test208.scxml b/test/w3c/ecma/test208.scxml
index 6faa9c1..043e537 100644
--- a/test/w3c/ecma/test208.scxml
+++ b/test/w3c/ecma/test208.scxml
@@ -4,8 +4,8 @@ we get event1 or an error first, cancel didn't work and we fail. --><scxml xmln
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" delayexpr="'50ms'"/>
+ <send event="event2" delayexpr="'75ms'"/>
<cancel sendid="foo"/>
</onentry>
diff --git a/test/w3c/ecma/test210.scxml b/test/w3c/ecma/test210.scxml
index e29b65d..f103ecd 100644
--- a/test/w3c/ecma/test210.scxml
+++ b/test/w3c/ecma/test210.scxml
@@ -6,8 +6,8 @@ delayed event1. Thus we get event2 first and pass. If we get event1 or an erro
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" delayexpr="'50ms'"/>
+ <send event="event2" delayexpr="'75ms'"/>
<assign location="Var1" expr="'foo'"/>
<cancel sendidexpr="Var1"/>
</onentry>
diff --git a/test/w3c/ecma/test236.scxml b/test/w3c/ecma/test236.scxml
index 700c6f8..acb1cda 100644
--- a/test/w3c/ecma/test236.scxml
+++ b/test/w3c/ecma/test236.scxml
@@ -5,7 +5,7 @@ events after the done.invoke. Hence timeout indicates success --><scxml xmlns
<state id="s0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" delayexpr="'100ms'"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
diff --git a/test/w3c/ecma/test237.scxml b/test/w3c/ecma/test237.scxml
index b23811d..442b04c 100644
--- a/test/w3c/ecma/test237.scxml
+++ b/test/w3c/ecma/test237.scxml
@@ -6,7 +6,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<state id="s0">
<onentry>
- <send event="timeout1" delay="1s"/>
+ <send event="timeout1" delayexpr="'50ms'"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
@@ -14,7 +14,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<scxml initial="sub0" version="1.0" datamodel="ecmascript">
<state id="sub0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" delayexpr="'100ms'"/>
</onentry>
<transition event="timeout" target="subFinal"/>
</state>
@@ -29,7 +29,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<state id="s1">
<onentry>
- <send event="timeout2" delay="2s"/>
+ <send event="timeout2" delayexpr="'75ms'"/>
</onentry>
<!-- here we should NOT get done.invoke -->
<transition event="done.invoke" target="fail"/>
diff --git a/test/w3c/ecma/test409.scxml b/test/w3c/ecma/test409.scxml
index 9b4f1aa..0fa71a2 100644
--- a/test/w3c/ecma/test409.scxml
+++ b/test/w3c/ecma/test409.scxml
@@ -5,7 +5,7 @@ be raised. Therefore the timeout should fire to indicate success --><scxml xm
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="1s"/>
+ <send event="timeout" delayexpr="'50ms'"/>
</onentry>
<transition event="timeout" target="pass"/>
diff --git a/test/w3c/ecma/test422.scxml b/test/w3c/ecma/test422.scxml
index 803f75f..637ff77 100644
--- a/test/w3c/ecma/test422.scxml
+++ b/test/w3c/ecma/test422.scxml
@@ -10,7 +10,7 @@ in s11. So we should receive invokeS1, invokeS12, but not invokeS12. Furthermor
</datamodel>
<state id="s1" initial="s11">
<onentry>
- <send event="timeout" delay="5s"/>
+ <send event="timeout" delayexpr="'100ms'"/>
</onentry>
<transition event="invokeS1 invokeS12">
<assign location="Var1" expr="Var1 + 1"/>
diff --git a/test/w3c/ecma/test423.scxml b/test/w3c/ecma/test423.scxml
index f6287ab..ab6c84f 100644
--- a/test/w3c/ecma/test423.scxml
+++ b/test/w3c/ecma/test423.scxml
@@ -4,7 +4,7 @@
<state id="s0">
<onentry>
<send event="externalEvent1"/>
- <send event="externalEvent2" delay="1s"/>
+ <send event="externalEvent2" delayexpr="'50ms'"/>
<raise event="internalEvent"/>
</onentry>
<!-- in this state we should process only internalEvent -->
diff --git a/test/w3c/ecma/test553.scxml b/test/w3c/ecma/test553.scxml
index 114c4a2..0beddea 100644
--- a/test/w3c/ecma/test553.scxml
+++ b/test/w3c/ecma/test553.scxml
@@ -5,7 +5,7 @@ of <send>'s args causes an error.. --><scxml xmlns="http://www.w3.org/2005/07/s
<state id="s0">
<onentry>
<!-- timeout event -->
- <send event="timeout" delay="3s"/>
+ <send event="timeout" delayexpr="'50ms'"/>
<!-- include a non-existing var in the namelist -->
<send event="event1" namelist="Var2"/>
</onentry>
diff --git a/test/w3c/ecma/test554.scxml b/test/w3c/ecma/test554.scxml
index b328ae9..960f5ac 100644
--- a/test/w3c/ecma/test554.scxml
+++ b/test/w3c/ecma/test554.scxml
@@ -5,7 +5,7 @@ before the timer goes off. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xm
<state id="s0">
<onentry>
- <send event="timer" delay="2s"/>
+ <send event="timer" delayexpr="'50ms'"/>
</onentry>
<!-- namelist references an undeclared variable -->
diff --git a/test/w3c/ecma/test579.scxml b/test/w3c/ecma/test579.scxml
index f89b1a9..c315f82 100644
--- a/test/w3c/ecma/test579.scxml
+++ b/test/w3c/ecma/test579.scxml
@@ -14,7 +14,7 @@ parent state has been visited and exited, the default history content must not b
</transition>
</initial>
<onentry>
- <send delay="2s" event="timeout"/>
+ <send delayexpr="'50ms'" event="timeout"/>
<raise event="event1"/>
</onentry>
<onexit>
diff --git a/test/w3c/txml/test175.txml b/test/w3c/txml/test175.txml
index aba7ac4..0c5065d 100644
--- a/test/w3c/txml/test175.txml
+++ b/test/w3c/txml/test175.txml
@@ -10,9 +10,9 @@ event1 will be raised first. Succeed if event1 occurs before event2, otherwise
<state id="s0">
<onentry>
- <assign conf:location="1" conf:quoteExpr="3s"/>
- <send conf:delayExpr="1" event="event2"/>
- <send delay="1s" event="event1"/>
+ <assign conf:location="1" conf:quoteExpr="1s"/>
+ <send conf:delayFromVar="1" event="event2"/>
+ <send conf:delay=".5" event="event1"/>
</onentry>
<transition event="event1" target="s1"/>
diff --git a/test/w3c/txml/test185.txml b/test/w3c/txml/test185.txml
index c036cbf..f9663c5 100644
--- a/test/w3c/txml/test185.txml
+++ b/test/w3c/txml/test185.txml
@@ -7,7 +7,7 @@
<state id="s0">
<onentry>
- <send event="event2" delay="2s"/>
+ <send event="event2" conf:delay="1"/>
<send event="event1"/>
</onentry>
diff --git a/test/w3c/txml/test186.txml b/test/w3c/txml/test186.txml
index e91c290..ef903f8 100644
--- a/test/w3c/txml/test186.txml
+++ b/test/w3c/txml/test186.txml
@@ -11,7 +11,7 @@ in the interval.) If var2 ends up == 1, we pass. Otherwise we fail -->
<state id="s0">
<onentry>
- <send event="event1" delay="2s">
+ <send event="event1" conf:delay="1">
<param name="aParam" conf:varExpr="1"/>
</send>
<assign conf:location="1" conf:expr="2"/>
diff --git a/test/w3c/txml/test187.txml b/test/w3c/txml/test187.txml
index 994a489..a39b6a3 100644
--- a/test/w3c/txml/test187.txml
+++ b/test/w3c/txml/test187.txml
@@ -9,7 +9,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<state id="s0" >
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" conf:delay="1"/>
</onentry>
<invoke type="scxml" >
<content>
@@ -17,7 +17,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<scxml initial="sub0" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance">
<state id="sub0">
<onentry>
- <send event="childToParent" target="#_parent" delay="1s"/>
+ <send event="childToParent" target="#_parent" conf:delay=".5"/>
</onentry>
<transition target="subFinal"/>
</state>
diff --git a/test/w3c/txml/test207.txml b/test/w3c/txml/test207.txml
index 6893dcf..df37f54 100644
--- a/test/w3c/txml/test207.txml
+++ b/test/w3c/txml/test207.txml
@@ -10,7 +10,7 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" conf:delay="2"/>
</onentry>
<invoke type="scxml">
<content>
@@ -22,8 +22,8 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<scxml initial="sub0" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance">
<state id="sub0">
<onentry>
- <send event="event1" id="foo" delay="3s"/>
- <send event="event2" delay="5s"/>
+ <send event="event1" id="foo" conf:delay="1"/>
+ <send event="event2" conf:delay="1.5"/>
<send target="#_parent" event="childToParent"/>
</onentry>
diff --git a/test/w3c/txml/test208.txml b/test/w3c/txml/test208.txml
index 5a86e6d..cce0316 100644
--- a/test/w3c/txml/test208.txml
+++ b/test/w3c/txml/test208.txml
@@ -8,8 +8,8 @@ we get event1 or an error first, cancel didn't work and we fail. -->
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" conf:delay="1"/>
+ <send event="event2" conf:delay="1.5"/>
<cancel sendid="foo"/>
</onentry>
diff --git a/test/w3c/txml/test210.txml b/test/w3c/txml/test210.txml
index 402ed36..24fdce0 100644
--- a/test/w3c/txml/test210.txml
+++ b/test/w3c/txml/test210.txml
@@ -10,8 +10,8 @@ delayed event1. Thus we get event2 first and pass. If we get event1 or an erro
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" conf:delay="1"/>
+ <send event="event2" conf:delay="1.5"/>
<assign conf:location="1" conf:quoteExpr="foo"/>
<cancel conf:sendIDExpr="1"/>
</onentry>
diff --git a/test/w3c/txml/test236.txml b/test/w3c/txml/test236.txml
index 5d18c2f..34e76ab 100644
--- a/test/w3c/txml/test236.txml
+++ b/test/w3c/txml/test236.txml
@@ -9,7 +9,7 @@ events after the done.invoke. Hence timeout indicates success -->
<state id="s0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" conf:delay="2"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
diff --git a/test/w3c/txml/test237.txml b/test/w3c/txml/test237.txml
index c6097bc..5923705 100644
--- a/test/w3c/txml/test237.txml
+++ b/test/w3c/txml/test237.txml
@@ -10,7 +10,7 @@ the time timeout2 fires, success -->
<state id="s0">
<onentry>
- <send event="timeout1" delay="1s"/>
+ <send event="timeout1" conf:delay="1"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
@@ -18,7 +18,7 @@ the time timeout2 fires, success -->
<scxml initial="sub0" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance">
<state id="sub0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" conf:delay="2"/>
</onentry>
<transition event="timeout" target="subFinal"/>
</state>
@@ -33,7 +33,7 @@ the time timeout2 fires, success -->
<state id="s1">
<onentry>
- <send event="timeout2" delay="2s"/>
+ <send event="timeout2" conf:delay="1.5"/>
</onentry>
<!-- here we should NOT get done.invoke -->
<transition event="done.invoke" conf:targetfail=""/>
diff --git a/test/w3c/txml/test409.txml b/test/w3c/txml/test409.txml
index abc92ee..020f097 100644
--- a/test/w3c/txml/test409.txml
+++ b/test/w3c/txml/test409.txml
@@ -9,7 +9,7 @@ be raised. Therefore the timeout should fire to indicate success -->
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="1s"/>
+ <send event="timeout" conf:delay="1"/>
</onentry>
<transition event="timeout" conf:targetpass=""/>
diff --git a/test/w3c/txml/test422.txml b/test/w3c/txml/test422.txml
index 2e830d9..0349bd0 100644
--- a/test/w3c/txml/test422.txml
+++ b/test/w3c/txml/test422.txml
@@ -13,7 +13,7 @@ in s11. So we should receive invokeS1, invokeS12, but not invokeS12. Furthermor
</datamodel>
<state id="s1" initial="s11">
<onentry>
- <send event="timeout" delay="5s"/>
+ <send event="timeout" conf:delay="2"/>
</onentry>
<transition event="invokeS1 invokeS12">
<conf:incrementID id="1"/>
diff --git a/test/w3c/txml/test423.txml b/test/w3c/txml/test423.txml
index fd64587..0e877cf 100644
--- a/test/w3c/txml/test423.txml
+++ b/test/w3c/txml/test423.txml
@@ -7,7 +7,7 @@
<state id="s0">
<onentry>
<send event="externalEvent1"/>
- <send event="externalEvent2" delay="1s"/>
+ <send event="externalEvent2" conf:delay="1"/>
<raise event="internalEvent"/>
</onentry>
<!-- in this state we should process only internalEvent -->
diff --git a/test/w3c/txml/test553.txml b/test/w3c/txml/test553.txml
index 322d4bb..0c6a622 100644
--- a/test/w3c/txml/test553.txml
+++ b/test/w3c/txml/test553.txml
@@ -9,7 +9,7 @@ of <send>'s args causes an error.. -->
<state id="s0">
<onentry>
<!-- timeout event -->
- <send event="timeout" delay="3s"/>
+ <send event="timeout" conf:delay="1"/>
<!-- include a non-existing var in the namelist -->
<send event="event1" conf:namelist="2"/>
</onentry>
diff --git a/test/w3c/txml/test554.txml b/test/w3c/txml/test554.txml
index d9ad55b..663424f 100644
--- a/test/w3c/txml/test554.txml
+++ b/test/w3c/txml/test554.txml
@@ -9,7 +9,7 @@ before the timer goes off. -->
<state id="s0">
<onentry>
- <send event="timer" delay="2s"/>
+ <send event="timer" conf:delay="1"/>
</onentry>
<!-- namelist references an undeclared variable -->
diff --git a/test/w3c/txml/test579.txml b/test/w3c/txml/test579.txml
index 7c48c37..9b1ef2a 100644
--- a/test/w3c/txml/test579.txml
+++ b/test/w3c/txml/test579.txml
@@ -18,7 +18,7 @@ parent state has been visited and exited, the default history content must not b
</transition>
</initial>
<onentry>
- <send delay="2s" event="timeout"/>
+ <send conf:delay="1" event="timeout"/>
<raise event="event1"/>
</onentry>
<onexit>
diff --git a/test/w3c/update-txml.sh b/test/w3c/update-txml.sh
index b733c6b..09a9602 100755
--- a/test/w3c/update-txml.sh
+++ b/test/w3c/update-txml.sh
@@ -9,4 +9,9 @@ wget -rl1 -Atxml,txt,xsl http://www.w3.org/Voice/2013/scxml-irp/
find ./www.w3.org -name "*.txml" -exec cp {} ./txml \;
find ./www.w3.org -name "*.txt" -exec cp {} ./txml \;
find ./www.w3.org -name "*.xsl" -exec cp {} . \;
-rm -rf www.w3.org \ No newline at end of file
+rm -rf www.w3.org
+
+sed -ie "s/<xsl:attribute name=\"delayexpr\">Var<xsl:value-of select=\".\" \/><\/xsl:attribute>/<xsl:attribute name=\"delayexpr\">(Var<xsl:value-of select=\".\" \/>.slice(0, - 1)) * 50 + 'ms'<\/xsl:attribute>/" confEcma.xsl
+sed -ie "s/<xsl:attribute name=\"delayexpr\">'<xsl:value-of select=\".\"\/>s'<\/xsl:attribute>/<xsl:attribute name=\"delayexpr\">'<xsl:value-of select=\". * 50\"\/>ms'<\/xsl:attribute>/" confEcma.xsl
+
+rm confEcma.xsle \ No newline at end of file
diff --git a/test/w3c/xpath/test175.scxml b/test/w3c/xpath/test175.scxml
index 8dfd670..67fa473 100644
--- a/test/w3c/xpath/test175.scxml
+++ b/test/w3c/xpath/test175.scxml
@@ -7,9 +7,9 @@ event1 will be raised first. Succeed if event1 occurs before event2, otherwise
<state id="s0">
<onentry>
- <assign location="$Var1" expr="'3s'"/>
+ <assign location="$Var1" expr="'1s'"/>
<send delayexpr="$Var1" event="event2"/>
- <send delay="1s" event="event1"/>
+ <send delayexpr="'.5s'" event="event1"/>
</onentry>
<transition event="event1" target="s1"/>
diff --git a/test/w3c/xpath/test185.scxml b/test/w3c/xpath/test185.scxml
index c6b4b48..387086d 100644
--- a/test/w3c/xpath/test185.scxml
+++ b/test/w3c/xpath/test185.scxml
@@ -4,7 +4,7 @@
<state id="s0">
<onentry>
- <send event="event2" delay="2s"/>
+ <send event="event2" delayexpr="'1s'"/>
<send event="event1"/>
</onentry>
diff --git a/test/w3c/xpath/test186.scxml b/test/w3c/xpath/test186.scxml
index 8353bf2..8121a17 100644
--- a/test/w3c/xpath/test186.scxml
+++ b/test/w3c/xpath/test186.scxml
@@ -8,7 +8,7 @@ in the interval.) If var2 ends up == 1, we pass. Otherwise we fail --><scxml
<state id="s0">
<onentry>
- <send event="event1" delay="2s">
+ <send event="event1" delayexpr="'1s'">
<param name="aParam" expr="$Var1/text()"/>
</send>
<assign location="$Var1" expr="2"/>
diff --git a/test/w3c/xpath/test187.scxml b/test/w3c/xpath/test187.scxml
index 12cbb8b..5cbb817 100644
--- a/test/w3c/xpath/test187.scxml
+++ b/test/w3c/xpath/test187.scxml
@@ -6,7 +6,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<state id="s0">
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" delayexpr="'1s'"/>
</onentry>
<invoke type="scxml">
<content>
@@ -14,7 +14,7 @@ parent session, should not receive childToParent. If it does, we fail. Otherwis
<scxml initial="sub0" version="1.0" datamodel="xpath">
<state id="sub0">
<onentry>
- <send event="childToParent" target="#_parent" delay="1s"/>
+ <send event="childToParent" target="#_parent" delayexpr="'.5s'"/>
</onentry>
<transition target="subFinal"/>
</state>
diff --git a/test/w3c/xpath/test207.scxml b/test/w3c/xpath/test207.scxml
index e74ec8f..b99e511 100644
--- a/test/w3c/xpath/test207.scxml
+++ b/test/w3c/xpath/test207.scxml
@@ -6,7 +6,7 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="10s"/>
+ <send event="timeout" delayexpr="'2s'"/>
</onentry>
<invoke type="scxml">
<content>
@@ -18,8 +18,8 @@ raised in another session, but the spec doesn't define any way to refer to an ev
<scxml initial="sub0" version="1.0" datamodel="xpath">
<state id="sub0">
<onentry>
- <send event="event1" id="foo" delay="3s"/>
- <send event="event2" delay="5s"/>
+ <send event="event1" id="foo" delayexpr="'1s'"/>
+ <send event="event2" delayexpr="'1.5s'"/>
<send target="#_parent" event="childToParent"/>
</onentry>
diff --git a/test/w3c/xpath/test208.scxml b/test/w3c/xpath/test208.scxml
index e768e7c..4aa9ebe 100644
--- a/test/w3c/xpath/test208.scxml
+++ b/test/w3c/xpath/test208.scxml
@@ -4,8 +4,8 @@ we get event1 or an error first, cancel didn't work and we fail. --><scxml xmln
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" delayexpr="'1s'"/>
+ <send event="event2" delayexpr="'1.5s'"/>
<cancel sendid="foo"/>
</onentry>
diff --git a/test/w3c/xpath/test210.scxml b/test/w3c/xpath/test210.scxml
index 5ec8f23..17dfc95 100644
--- a/test/w3c/xpath/test210.scxml
+++ b/test/w3c/xpath/test210.scxml
@@ -6,8 +6,8 @@ delayed event1. Thus we get event2 first and pass. If we get event1 or an erro
<state id="s0">
<onentry>
- <send id="foo" event="event1" delay="1s"/>
- <send event="event2" delay="5s"/>
+ <send id="foo" event="event1" delayexpr="'1s'"/>
+ <send event="event2" delayexpr="'1.5s'"/>
<assign location="$Var1" expr="'foo'"/>
<cancel sendidexpr="$Var1"/>
</onentry>
diff --git a/test/w3c/xpath/test236.scxml b/test/w3c/xpath/test236.scxml
index 2c2d41a..0964f71 100644
--- a/test/w3c/xpath/test236.scxml
+++ b/test/w3c/xpath/test236.scxml
@@ -5,7 +5,7 @@ events after the done.invoke. Hence timeout indicates success --><scxml xmlns
<state id="s0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" delayexpr="'2s'"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
diff --git a/test/w3c/xpath/test237.scxml b/test/w3c/xpath/test237.scxml
index 19c2480..a81e36a 100644
--- a/test/w3c/xpath/test237.scxml
+++ b/test/w3c/xpath/test237.scxml
@@ -6,7 +6,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<state id="s0">
<onentry>
- <send event="timeout1" delay="1s"/>
+ <send event="timeout1" delayexpr="'1s'"/>
</onentry>
<invoke type="http://www.w3.org/TR/scxml/">
<content>
@@ -14,7 +14,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<scxml initial="sub0" version="1.0" datamodel="xpath">
<state id="sub0">
<onentry>
- <send event="timeout" delay="2s"/>
+ <send event="timeout" delayexpr="'2s'"/>
</onentry>
<transition event="timeout" target="subFinal"/>
</state>
@@ -29,7 +29,7 @@ the time timeout2 fires, success --><scxml xmlns="http://www.w3.org/2005/07/sc
<state id="s1">
<onentry>
- <send event="timeout2" delay="2s"/>
+ <send event="timeout2" delayexpr="'1.5s'"/>
</onentry>
<!-- here we should NOT get done.invoke -->
<transition event="done.invoke" target="fail"/>
diff --git a/test/w3c/xpath/test409.scxml b/test/w3c/xpath/test409.scxml
index 2d5a63d..e321d46 100644
--- a/test/w3c/xpath/test409.scxml
+++ b/test/w3c/xpath/test409.scxml
@@ -5,7 +5,7 @@ be raised. Therefore the timeout should fire to indicate success --><scxml xm
<state id="s0" initial="s01">
<onentry>
- <send event="timeout" delay="1s"/>
+ <send event="timeout" delayexpr="'1s'"/>
</onentry>
<transition event="timeout" target="pass"/>
diff --git a/test/w3c/xpath/test422.scxml b/test/w3c/xpath/test422.scxml
index f62098d..4ef15ce 100644
--- a/test/w3c/xpath/test422.scxml
+++ b/test/w3c/xpath/test422.scxml
@@ -10,7 +10,7 @@ in s11. So we should receive invokeS1, invokeS12, but not invokeS12. Furthermor
</datamodel>
<state id="s1" initial="s11">
<onentry>
- <send event="timeout" delay="5s"/>
+ <send event="timeout" delayexpr="'2s'"/>
</onentry>
<transition event="invokeS1 invokeS12">
<assign location="$Var1" expr="$Var1 + 1"/>
diff --git a/test/w3c/xpath/test423.scxml b/test/w3c/xpath/test423.scxml
index 7726963..f3bf8c8 100644
--- a/test/w3c/xpath/test423.scxml
+++ b/test/w3c/xpath/test423.scxml
@@ -4,7 +4,7 @@
<state id="s0">
<onentry>
<send event="externalEvent1"/>
- <send event="externalEvent2" delay="1s"/>
+ <send event="externalEvent2" delayexpr="'1s'"/>
<raise event="internalEvent"/>
</onentry>
<!-- in this state we should process only internalEvent -->
diff --git a/test/w3c/xpath/test553.scxml b/test/w3c/xpath/test553.scxml
index eb6f24b..00bd1e8 100644
--- a/test/w3c/xpath/test553.scxml
+++ b/test/w3c/xpath/test553.scxml
@@ -5,7 +5,7 @@ of <send>'s args causes an error.. --><scxml xmlns="http://www.w3.org/2005/07/s
<state id="s0">
<onentry>
<!-- timeout event -->
- <send event="timeout" delay="3s"/>
+ <send event="timeout" delayexpr="'1s'"/>
<!-- include a non-existing var in the namelist -->
<send event="event1" namelist="$Var2"/>
</onentry>
diff --git a/test/w3c/xpath/test554.scxml b/test/w3c/xpath/test554.scxml
index 64274aa..1a2b58a 100644
--- a/test/w3c/xpath/test554.scxml
+++ b/test/w3c/xpath/test554.scxml
@@ -5,7 +5,7 @@ before the timer goes off. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xm
<state id="s0">
<onentry>
- <send event="timer" delay="2s"/>
+ <send event="timer" delayexpr="'1s'"/>
</onentry>
<!-- namelist references an undeclared variable -->
diff --git a/test/w3c/xpath/test579.scxml b/test/w3c/xpath/test579.scxml
index 311c0a9..28cdf28 100644
--- a/test/w3c/xpath/test579.scxml
+++ b/test/w3c/xpath/test579.scxml
@@ -14,7 +14,7 @@ parent state has been visited and exited, the default history content must not b
</transition>
</initial>
<onentry>
- <send delay="2s" event="timeout"/>
+ <send delayexpr="'1s'" event="timeout"/>
<raise event="event1"/>
</onentry>
<onexit>