summaryrefslogtreecommitdiffstats
path: root/embedding
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-06-25 21:05:44 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-06-25 21:05:44 (GMT)
commite3767be4f9c5874d9c996200f2e9705ce31a5976 (patch)
treebe3d06f550286e23eeb3252277c1a2b7d12554ef /embedding
parent758bda908ded461c9d34d274a18454ffba4b7450 (diff)
downloaduscxml-e3767be4f9c5874d9c996200f2e9705ce31a5976.zip
uscxml-e3767be4f9c5874d9c996200f2e9705ce31a5976.tar.gz
uscxml-e3767be4f9c5874d9c996200f2e9705ce31a5976.tar.bz2
Work on bindings
- Introduced exceptions into C# and Java - Moved binding examples to /embedding - Interpreter will now throw exceptions, beware!
Diffstat (limited to 'embedding')
-rw-r--r--embedding/csharp/embedding/embedding.sln20
-rw-r--r--embedding/csharp/embedding/embedding.suobin0 -> 15872 bytes
-rw-r--r--embedding/csharp/embedding/embedding.userprefs12
-rw-r--r--embedding/csharp/embedding/embedding/Program.cs35
-rw-r--r--embedding/csharp/embedding/embedding/Properties/AssemblyInfo.cs36
-rw-r--r--embedding/csharp/embedding/embedding/embedding.csproj66
-rw-r--r--embedding/java/.classpath9
-rw-r--r--embedding/java/.gitignore1
-rw-r--r--embedding/java/.project17
-rw-r--r--embedding/java/lib/js.jarbin0 -> 1134765 bytes
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java110
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java126
-rw-r--r--embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java396
-rw-r--r--embedding/java/src/org/uscxml/tests/TestData.java23
-rw-r--r--embedding/java/src/org/uscxml/tests/datamodel/TestJavaScriptDataModel.java27
-rw-r--r--embedding/java/src/org/uscxml/tests/datamodel/TestW3CECMA.java41
-rw-r--r--embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java81
-rw-r--r--embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java69
-rw-r--r--embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java54
19 files changed, 1123 insertions, 0 deletions
diff --git a/embedding/csharp/embedding/embedding.sln b/embedding/csharp/embedding/embedding.sln
new file mode 100644
index 0000000..0f9a49e
--- /dev/null
+++ b/embedding/csharp/embedding/embedding.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "embedding", "embedding\embedding.csproj", "{75E5EE93-513B-45DA-AD50-64C570AAD0C0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {75E5EE93-513B-45DA-AD50-64C570AAD0C0}.Debug|x86.ActiveCfg = Debug|x86
+ {75E5EE93-513B-45DA-AD50-64C570AAD0C0}.Debug|x86.Build.0 = Debug|x86
+ {75E5EE93-513B-45DA-AD50-64C570AAD0C0}.Release|x86.ActiveCfg = Release|x86
+ {75E5EE93-513B-45DA-AD50-64C570AAD0C0}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/embedding/csharp/embedding/embedding.suo b/embedding/csharp/embedding/embedding.suo
new file mode 100644
index 0000000..f011087
--- /dev/null
+++ b/embedding/csharp/embedding/embedding.suo
Binary files differ
diff --git a/embedding/csharp/embedding/embedding.userprefs b/embedding/csharp/embedding/embedding.userprefs
new file mode 100644
index 0000000..681be08
--- /dev/null
+++ b/embedding/csharp/embedding/embedding.userprefs
@@ -0,0 +1,12 @@
+<Properties>
+ <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug|x86" />
+ <MonoDevelop.Ide.Workbench ActiveDocument="embedding/Program.cs">
+ <Files>
+ <File FileName="embedding/Program.cs" Line="16" Column="40" />
+ </Files>
+ </MonoDevelop.Ide.Workbench>
+ <MonoDevelop.Ide.DebuggingService.Breakpoints>
+ <BreakpointStore />
+ </MonoDevelop.Ide.DebuggingService.Breakpoints>
+ <MonoDevelop.Ide.DebuggingService.PinnedWatches />
+</Properties> \ No newline at end of file
diff --git a/embedding/csharp/embedding/embedding/Program.cs b/embedding/csharp/embedding/embedding/Program.cs
new file mode 100644
index 0000000..3899178
--- /dev/null
+++ b/embedding/csharp/embedding/embedding/Program.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace embedding
+{
+ using org.uscxml;
+
+ class Program
+ {
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+ private static extern void SetDllDirectory(string lpPathName);
+
+ static void Main(string[] args)
+ {
+
+ /*
+ * Make sure this path contains the umundoNativeCSharp.dll!
+ */
+ if (System.Environment.Is64BitProcess)
+ {
+ SetDllDirectory("C:\\Users\\sradomski\\Desktop\\build\\lib\\csharp64");
+ }
+ else
+ {
+ SetDllDirectory("C:\\Users\\sradomski\\Desktop\\build\\lib\\csharp");
+ }
+
+ Interpreter interpreter = Interpreter.fromXML("<scxml><state id=\"foo\"/></scxml>");
+ interpreter.interpret();
+ }
+ }
+}
diff --git a/embedding/csharp/embedding/embedding/Properties/AssemblyInfo.cs b/embedding/csharp/embedding/embedding/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bd9015e
--- /dev/null
+++ b/embedding/csharp/embedding/embedding/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("embedding")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("embedding")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0d270ead-e8cf-4cc1-a2c8-fa123e71812c")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/embedding/csharp/embedding/embedding/embedding.csproj b/embedding/csharp/embedding/embedding/embedding.csproj
new file mode 100644
index 0000000..53e1eed
--- /dev/null
+++ b/embedding/csharp/embedding/embedding/embedding.csproj
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{75E5EE93-513B-45DA-AD50-64C570AAD0C0}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>embedding</RootNamespace>
+ <AssemblyName>embedding</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <EnvironmentVariables>
+ <EnvironmentVariables>
+ <Variable name="DYLD_FALLBACK_LIBRARY_PATH" value="/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/csharp" />
+ <Variable name="MONO_LOG_LEVEL" value="debug" />
+ </EnvironmentVariables>
+ </EnvironmentVariables>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="uscxmlCSharp">
+ <HintPath>..\..\..\..\build\cli\lib\uscxmlCSharp.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.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.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/embedding/java/.classpath b/embedding/java/.classpath
new file mode 100644
index 0000000..fa94b3c
--- /dev/null
+++ b/embedding/java/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/umundo"/>
+ <classpathentry kind="lib" path="lib/js.jar"/>
+ <classpathentry kind="lib" path="/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/uscxml.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/embedding/java/.gitignore b/embedding/java/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/embedding/java/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/embedding/java/.project b/embedding/java/.project
new file mode 100644
index 0000000..9aecdf8
--- /dev/null
+++ b/embedding/java/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>uscxml</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/embedding/java/lib/js.jar b/embedding/java/lib/js.jar
new file mode 100644
index 0000000..6f0dafb
--- /dev/null
+++ b/embedding/java/lib/js.jar
Binary files differ
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java
new file mode 100644
index 0000000..56d7090
--- /dev/null
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAData.java
@@ -0,0 +1,110 @@
+package org.uscxml.datamodel.ecmascript;
+
+import org.mozilla.javascript.Scriptable;
+import org.uscxml.Data;
+
+public class ECMAData implements Scriptable {
+
+ protected Data data;
+ protected Scriptable parent;
+ protected Scriptable prototype;
+
+ public ECMAData(Data data) {
+ this.data = data;
+ }
+
+ @Override
+ public String getClassName() {
+ return "Data";
+ }
+
+ public Object unwrap(Data data) {
+ if (data.atom.length() > 0) {
+ return data.atom;
+ }
+ return new ECMAData(data);
+
+ }
+
+ @Override
+ public Object get(String name, Scriptable start) {
+ if (data.compound.containsKey(name))
+ return unwrap(data.compound.get(name));
+ return NOT_FOUND;
+ }
+
+ @Override
+ public Object get(int index, Scriptable start) {
+ if (data.array.size() > index)
+ return unwrap(data.array.get(index));
+ return NOT_FOUND;
+ }
+
+ @Override
+ public boolean has(String name, Scriptable start) {
+ return data.compound.containsKey(name);
+ }
+
+ @Override
+ public boolean has(int index, Scriptable start) {
+ return data.array.size() > index;
+ }
+
+ @Override
+ public void put(String name, Scriptable start, Object value) {
+ }
+
+ @Override
+ public void put(int index, Scriptable start, Object value) {
+ }
+
+ @Override
+ public void delete(String name) {
+ }
+
+ @Override
+ public void delete(int index) {
+ }
+
+ @Override
+ public Scriptable getPrototype() {
+ return prototype;
+ }
+
+ @Override
+ public void setPrototype(Scriptable prototype) {
+ this.prototype = prototype;
+ }
+
+ @Override
+ public Scriptable getParentScope() {
+ return parent;
+ }
+
+ @Override
+ public void setParentScope(Scriptable parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public Object[] getIds() {
+ return data.compound.keySet().toArray();
+ }
+
+ @Override
+ public Object getDefaultValue(Class<?> hint) {
+ return "[object Data]";
+ }
+
+ @Override
+ public boolean hasInstance(Scriptable instance) {
+ Scriptable proto = instance.getPrototype();
+ while (proto != null) {
+ if (proto.equals(this))
+ return true;
+ proto = proto.getPrototype();
+ }
+ return false;
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java
new file mode 100644
index 0000000..58fff72
--- /dev/null
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAEvent.java
@@ -0,0 +1,126 @@
+package org.uscxml.datamodel.ecmascript;
+
+import java.util.HashMap;
+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 {
+
+ protected Event event;
+ protected Scriptable parent;
+ protected Scriptable prototype;
+
+ protected Map<String, Object> members = new HashMap<String, Object>();
+
+ 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()));
+ }
+
+ members.put("type", event.getEventType().toString());
+ members.put("data", new ECMAData(data));
+ members.put("sendid", event.getSendId());
+ members.put("origin", event.getOrigin());
+ members.put("originType", event.getOriginType());
+ // add others as necessary
+
+ }
+
+ @Override
+ public String getClassName() {
+ return "Event";
+ }
+
+ @Override
+ public Object get(String name, Scriptable start) {
+ if (members.containsKey(name))
+ return members.get(name);
+ return NOT_FOUND;
+ }
+
+ @Override
+ public Object get(int index, Scriptable start) {
+ return NOT_FOUND;
+ }
+
+ @Override
+ public boolean has(String name, Scriptable start) {
+ return (members.containsKey(name));
+ }
+
+ @Override
+ public boolean has(int index, Scriptable start) {
+ return false;
+ }
+
+ @Override
+ public void put(String name, Scriptable start, Object value) {
+ }
+
+ @Override
+ public void put(int index, Scriptable start, Object value) {
+ }
+
+ @Override
+ public void delete(String name) {
+ }
+
+ @Override
+ public void delete(int index) {
+ }
+
+ @Override
+ public Scriptable getPrototype() {
+ return prototype;
+ }
+
+ @Override
+ public void setPrototype(Scriptable prototype) {
+ this.prototype = prototype;
+ }
+
+ @Override
+ public Scriptable getParentScope() {
+ return parent;
+ }
+
+ @Override
+ public void setParentScope(Scriptable parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public Object[] getIds() {
+ return members.keySet().toArray();
+ }
+
+ @Override
+ public Object getDefaultValue(Class<?> hint) {
+ return "[object Event]";
+ }
+
+ @Override
+ public boolean hasInstance(Scriptable instance) {
+ Scriptable proto = instance.getPrototype();
+ while (proto != null) {
+ if (proto.equals(this))
+ return true;
+ proto = proto.getPrototype();
+ }
+
+ return false;
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java
new file mode 100644
index 0000000..dcafcb9
--- /dev/null
+++ b/embedding/java/src/org/uscxml/datamodel/ecmascript/ECMAScriptDataModel.java
@@ -0,0 +1,396 @@
+package org.uscxml.datamodel.ecmascript;
+
+import java.lang.reflect.Method;
+
+import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.FunctionObject;
+import org.mozilla.javascript.NativeJSON;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Undefined;
+import org.uscxml.Data;
+import org.uscxml.DataNative;
+import org.uscxml.Event;
+import org.uscxml.Interpreter;
+import org.uscxml.StringList;
+import org.uscxml.StringVector;
+import org.uscxml.WrappedDataModel;
+
+public class ECMAScriptDataModel extends WrappedDataModel {
+
+ public static boolean debug = true;
+
+ private class NullCallable implements Callable {
+ @Override
+ public Object call(Context context, Scriptable scope,
+ Scriptable holdable, Object[] objects) {
+ return objects[1];
+ }
+ }
+
+ public Context ctx;
+ public Scriptable scope;
+ public Interpreter interpreter;
+
+ public Data getScriptableAsData(Object object) {
+ Data data = new Data();
+
+ Scriptable s;
+ try {
+ s = (Scriptable) object;
+ String className = s.getClassName(); // ECMA class name
+ if (className.toLowerCase().equals("object")) {
+ ScriptableObject obj = (ScriptableObject) Context.toObject(s,
+ scope);
+ for (Object key : obj.getIds()) {
+ data.compound.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;
+ } else if (object instanceof String) {
+ data.atom = (String) object;
+ data.type = Data.Type.VERBATIM;
+ } else if (object instanceof Integer) {
+ data.atom = ((Integer) object).toString();
+ data.type = Data.Type.INTERPRETED;
+ } else {
+ throw new RuntimeException("Unhandled ECMA type "
+ + object.getClass().getName());
+ }
+ }
+
+ return data;
+ }
+
+ public ScriptableObject getDataAsScriptable(Data data) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public static boolean jsIn(String stateName) {
+ return true;
+ }
+
+ @Override
+ public WrappedDataModel create(Interpreter interpreter) {
+ /**
+ * Called when an SCXML interpreter wants an instance of this datamodel
+ * Be careful to instantiate attributes of instance returned and not
+ * *this*
+ */
+
+ ECMAScriptDataModel newDM = new ECMAScriptDataModel();
+ newDM.interpreter = interpreter;
+ newDM.ctx = Context.enter();
+
+ try {
+ newDM.scope = newDM.ctx.initStandardObjects();
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+
+ newDM.scope.put("_name", newDM.scope, interpreter.getName());
+ newDM.scope.put("_sessionid", newDM.scope, interpreter.getSessionId());
+
+ // ioProcessors
+ {
+ 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
+ .getIOProcessors().get(keys.get(i))
+ .getDataModelVariables()));
+ }
+ newDM.scope
+ .put("_ioprocessors", newDM.scope, new ECMAData(ioProcs));
+ }
+
+ // invokers
+ {
+ 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
+ .getInvokers().get(keys.get(i))
+ .getDataModelVariables()));
+ }
+ newDM.scope
+ .put("_ioprocessors", newDM.scope, new ECMAData(invokers));
+ }
+
+ // In predicate (not working as static is required) see:
+ // http://stackoverflow.com/questions/3441947/how-do-i-call-a-method-of-a-java-instance-from-javascript/16479685#16479685
+ try {
+ Class[] parameters = new Class[] { String.class };
+ Method inMethod = ECMAScriptDataModel.class.getMethod("jsIn",
+ parameters);
+ FunctionObject inFunc = new FunctionObject("In", inMethod,
+ newDM.scope);
+ newDM.scope.put("In", newDM.scope, inFunc);
+ } catch (SecurityException e) {
+ System.err.println(e);
+ } catch (NoSuchMethodException e) {
+ System.err.println(e);
+ }
+
+ return newDM;
+ }
+
+ @Override
+ public StringList getNames() {
+ /**
+ * Register with the following names for the datamodel attribute at the
+ * scxml element. <scxml datamodel="one of these">
+ */
+ StringList ss = new StringList();
+ ss.add("ecmascript");
+ return ss;
+ }
+
+ @Override
+ public boolean validate(String location, String schema) {
+ /**
+ * Validate the datamodel. This make more sense for XML datamodels and
+ * is pretty much unused but required as per draft.
+ */
+ return true;
+ }
+
+ @Override
+ public void setEvent(Event event) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " setEvent");
+ }
+
+ /**
+ * Make the current event available as the variable _event in the
+ * datamodel.
+ */
+ ECMAEvent ecmaEvent = new ECMAEvent(event);
+ scope.put("_event", scope, ecmaEvent);
+ }
+
+ @Override
+ public DataNative getStringAsData(String content) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " getStringAsData");
+ }
+
+ /**
+ * Evaluate the string as a value expression and transform it into a
+ * JSON-like Data structure
+ */
+ if (content.length() == 0) {
+ return Data.toNative(new Data());
+ }
+
+ // is it a json expression?
+ try {
+ Object json = NativeJSON.parse(ctx, scope, content,
+ new NullCallable());
+ if (json != NativeJSON.NOT_FOUND) {
+ return Data.toNative(getScriptableAsData(json));
+ }
+ } catch (org.mozilla.javascript.EcmaError e) {
+ System.err.println(e);
+ }
+
+ // is it a function call or variable?
+ Object x = ctx.evaluateString(scope, content, "uscxml", 0, null);
+ if (x == Undefined.instance) {
+ // maybe a literal string?
+ x = ctx.evaluateString(scope, '"' + content + '"', "uscxml", 0,
+ null);
+ }
+ return Data.toNative(getScriptableAsData(x));
+ }
+
+ @Override
+ public long getLength(String expr) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " getLength");
+ }
+
+ /**
+ * Return the length of the expression if it were an array, used by
+ * foreach element.
+ */
+
+ Object x = scope.get(expr, scope);
+ if (x == Undefined.instance) {
+ return 0;
+ }
+
+ Scriptable result = Context.toObject(x, scope);
+ if (result.has("length", result)) {
+ return (long) Context.toNumber(result.get("length", result));
+ }
+ return 0;
+ }
+
+ @Override
+ public void setForeach(String item, String array, String index,
+ long iteration) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " setForeach");
+ }
+
+ /**
+ * Prepare an iteration of the foreach element, by setting the variable
+ * in index to the current iteration and setting the variable in item to
+ * the current item from array.
+ */
+
+ try {
+ // get the array object
+ Scriptable arr = (Scriptable) scope.get(array, scope);
+
+ if (arr.has((int) iteration, arr)) {
+ ctx.evaluateString(scope, item + '=' + array + '[' + iteration
+ + ']', "uscxml", 1, null);
+ if (index.length() > 0) {
+ ctx.evaluateString(scope, index + '=' + iteration,
+ "uscxml", 1, null);
+ }
+ } else {
+ handleException("");
+ }
+
+ } catch (ClassCastException e) {
+ System.err.println(e);
+ }
+ }
+
+ @Override
+ public void eval(String scriptElem, String expr) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " eval");
+ }
+
+ /**
+ * Evaluate the given expression in the datamodel. This is used foremost
+ * with script elements.
+ */
+ ctx.evaluateString(scope, expr, "uscxml", 1, null);
+
+ }
+
+ @Override
+ public String evalAsString(String expr) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " evalAsString: " + expr);
+ }
+
+ /**
+ * Evaluate the expression as a string e.g. for the log element.
+ */
+ if (!ctx.stringIsCompilableUnit(expr)) {
+ handleException("");
+ return "";
+ }
+ try {
+ Object result = ctx.evaluateString(scope, expr, "uscxml", 1, null);
+ return Context.toString(result);
+ } catch (IllegalStateException e) {
+ System.err.println(e);
+ handleException("");
+ } catch (EvaluatorException e) {
+ System.err.println(e);
+ handleException("");
+ }
+ return "";
+ }
+
+ @Override
+ public boolean evalAsBool(String elem, String expr) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " evalAsBool");
+ }
+
+ /**
+ * Evaluate the expression as a boolean for cond attributes in if and
+ * transition elements.
+ */
+ Object result = ctx.evaluateString(scope, expr, "uscxml", 1, null);
+ return Context.toBoolean(result);
+ }
+
+ @Override
+ public boolean isDeclared(String expr) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " isDeclared");
+ }
+
+ /**
+ * The interpreter is supposed to raise an error if we assign to an
+ * undeclared variable. This method is used to check whether a location
+ * from assign is declared.
+ */
+ Object x = scope.get(expr, scope);
+ return x != Scriptable.NOT_FOUND;
+ }
+
+ @Override
+ public void init(String dataElem, String location, String content) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " init");
+ }
+
+ /**
+ * Called when we pass data elements.
+ */
+ if (("null").equals(location))
+ return;
+
+ if (("null").equals(content) || content.length() == 0) {
+ scope.put(location, scope, Context.getUndefinedValue());
+ return;
+ }
+
+ try {
+ Object json = NativeJSON.parse(ctx, scope, content,
+ new NullCallable());
+ if (json != NativeJSON.NOT_FOUND) {
+ scope.put(location, scope, json);
+ } else {
+ scope.put(location, scope, content);
+ }
+ } catch (org.mozilla.javascript.EcmaError e) {
+ scope.put(location, scope, content);
+ }
+ }
+
+ @Override
+ public void assign(String assignElem, String location, String content) {
+ if (debug) {
+ System.out.println(interpreter.getName() + " assign");
+ }
+
+ /**
+ * Called when we evaluate assign elements
+ */
+ if (("null").equals(location))
+ return;
+
+ if (("null").equals(content) || content.length() == 0) {
+ scope.put(location, scope, Context.getUndefinedValue());
+ return;
+ }
+
+ String expr = location + "=" + content;
+ ctx.evaluateString(scope, expr, "uscxml", 1, null);
+ }
+
+ public void handleException(String cause) {
+ Event exceptionEvent = new Event();
+ exceptionEvent.setName("error.execution");
+ exceptionEvent.setEventType(Event.Type.PLATFORM);
+
+ interpreter.receiveInternal(exceptionEvent);
+ }
+}
diff --git a/embedding/java/src/org/uscxml/tests/TestData.java b/embedding/java/src/org/uscxml/tests/TestData.java
new file mode 100644
index 0000000..44f1ce0
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/TestData.java
@@ -0,0 +1,23 @@
+package org.uscxml.tests;
+
+import org.uscxml.Data;
+import org.uscxml.DataNative;
+
+public class TestData {
+
+ public static void main(String[] args) {
+ 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);
+ }
+ {
+ Data data = Data.fromJSON("{ \"foo\": \"bar\", \"faz\": 12 }");
+ DataNative nData2 = Data.toNative(data);
+ Data data2 = new Data(nData2);
+ System.out.println(data2);
+ }
+ }
+}
diff --git a/embedding/java/src/org/uscxml/tests/datamodel/TestJavaScriptDataModel.java b/embedding/java/src/org/uscxml/tests/datamodel/TestJavaScriptDataModel.java
new file mode 100644
index 0000000..7cfa793
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/datamodel/TestJavaScriptDataModel.java
@@ -0,0 +1,27 @@
+package org.uscxml.tests.datamodel;
+
+import org.uscxml.Factory;
+import org.uscxml.Interpreter;
+import org.uscxml.InterpreterException;
+import org.uscxml.datamodel.ecmascript.ECMAScriptDataModel;
+
+public class TestJavaScriptDataModel {
+
+ public static void main(String[] args) throws InterpreterException {
+ // load JNI library from build directory
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
+
+ // register java datamodel at factory
+ ECMAScriptDataModel datamodel = new ECMAScriptDataModel();
+ Factory.getInstance().registerDataModel(datamodel);
+
+ // instantiate interpreter with document from file
+ Interpreter interpreter = Interpreter
+ .fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/uscxml/java/test-ecmascript-datamodel.scxml");
+
+ // wait until interpreter has finished
+ while (true)
+ interpreter.interpret();
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/tests/datamodel/TestW3CECMA.java b/embedding/java/src/org/uscxml/tests/datamodel/TestW3CECMA.java
new file mode 100644
index 0000000..c525fd1
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/datamodel/TestW3CECMA.java
@@ -0,0 +1,41 @@
+package org.uscxml.tests.datamodel;
+
+import java.io.File;
+
+import org.uscxml.Capabilities;
+import org.uscxml.Factory;
+import org.uscxml.Interpreter;
+import org.uscxml.InterpreterException;
+import org.uscxml.InterpreterOptions;
+import org.uscxml.datamodel.ecmascript.ECMAScriptDataModel;
+
+public class TestW3CECMA {
+
+ public static String testDir = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma";
+
+ public static void main(String[] args) throws InterpreterException {
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
+
+ ECMAScriptDataModel datamodel = new ECMAScriptDataModel();
+ Factory.getInstance().registerDataModel(datamodel);
+
+// while(true) {
+// System.out.println("### test235 #####");
+// Interpreter interpreter = Interpreter.fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test144.scxml");
+// interpreter.interpret();
+// }
+
+ File dir = new File(testDir);
+ File[] filesList = dir.listFiles();
+ for (File file : filesList) {
+ if (file.isFile() && file.getName().endsWith(".scxml")) {
+ System.out.println("### " + file.getName() + " #####");
+ Interpreter interpreter = Interpreter.fromURI(file.getAbsolutePath());
+ interpreter.setCapabilities(1);
+ interpreter.interpret();
+ }
+ }
+
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java b/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java
new file mode 100644
index 0000000..dd5e39a
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/execContent/TestCustomExecContent.java
@@ -0,0 +1,81 @@
+package org.uscxml.tests.execContent;
+
+import org.uscxml.Data;
+import org.uscxml.Event;
+import org.uscxml.Factory;
+import org.uscxml.Interpreter;
+import org.uscxml.InterpreterException;
+import org.uscxml.WrappedExecutableContent;
+
+public class TestCustomExecContent extends WrappedExecutableContent {
+
+ static int instanceId = 0;
+ public int id = 0;
+
+ public TestCustomExecContent() {
+ id = instanceId++;
+ }
+
+ @Override
+ public String getLocalName() {
+ return "custom";
+ }
+
+ @Override
+ public String getNamespace() {
+ return "http://www.w3.org/2005/07/scxml";
+ }
+
+
+ @Override
+ public void enterElement(String node) {
+ System.out.println(id + " entering:" + node);
+ }
+
+ @Override
+ public void exitElement(String node) {
+ System.out.println(id + " exiting:" + node);
+ }
+
+ @Override
+ public boolean processChildren() {
+ return false;
+ }
+
+ @Override
+ public WrappedExecutableContent create(Interpreter interpreter) {
+ return new TestCustomExecContent();
+ }
+
+ /**
+ * @param args
+ * @throws InterruptedException
+ * @throws InterpreterException
+ */
+ public static void main(String[] args) throws InterruptedException, InterpreterException {
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib");
+
+ TestCustomExecContent execContent = new TestCustomExecContent();
+ Factory.getInstance().registerExecutableContent(execContent);
+
+ Interpreter interpreter = Interpreter.fromXML(
+ "<scxml>\n" +
+ " <state id=\"s0\">\n" +
+ " <onentry>\n" +
+ " <custom foo=\"bar\">\n" +
+ " <something></something>\n" +
+ " </custom>\n" +
+ " <custom foo=\"bar\">\n" +
+ " <something></something>\n" +
+ " </custom>\n" +
+ " </onentry>\n" +
+ " <transition target=\"exit\" />" +
+ " </state>\n" +
+ " <final id=\"exit\" />" +
+ "</scxml>\n"
+ );
+ interpreter.interpret();
+ Thread.sleep(1000);
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java b/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java
new file mode 100644
index 0000000..9343c65
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java
@@ -0,0 +1,69 @@
+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;
+import org.uscxml.InterpreterException;
+import org.uscxml.InvokeRequest;
+import org.uscxml.StringList;
+import org.uscxml.WrappedInvoker;
+import org.uscxml.SendRequest;
+import org.uscxml.StringSet;
+
+public class TestCustomInvoker extends WrappedInvoker {
+
+ @Override
+ public StringList getNames() {
+ StringList ss = new StringList();
+ ss.add("java");
+ return ss;
+ }
+
+ @Override
+ public DataNative getDataModelVariables() {
+ Data data = new Data();
+ data.array.add(new Data("foo", Data.Type.VERBATIM));
+ return Data.toNative(data);
+ }
+
+ @Override
+ public void send(SendRequest req) {
+ System.out.println("send");
+ }
+
+ @Override
+ public void invoke(InvokeRequest req) {
+ System.out.println("invoke");
+
+ System.out.println(req.getData());
+ System.out.println(req.getXML());
+
+ Event ev = new Event();
+ ev.setName("foo");
+ returnEvent(ev);
+ }
+
+ @Override
+ public WrappedInvoker create(Interpreter interpreter) {
+ return new TestCustomInvoker();
+ }
+
+ /**
+ * @param args
+ * @throws InterpreterException
+ */
+ public static void main(String[] args) throws InterpreterException {
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib");
+
+ TestCustomInvoker invoker = new TestCustomInvoker();
+ 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();
+ }
+
+}
diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java
new file mode 100644
index 0000000..37b31a3
--- /dev/null
+++ b/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java
@@ -0,0 +1,54 @@
+package org.uscxml.tests.ioprocessor;
+
+import org.uscxml.Data;
+import org.uscxml.DataNative;
+import org.uscxml.Factory;
+import org.uscxml.Interpreter;
+import org.uscxml.InterpreterException;
+import org.uscxml.SendRequest;
+import org.uscxml.StringList;
+import org.uscxml.WrappedIOProcessor;
+
+public class TestCustomIOProc extends WrappedIOProcessor {
+
+ @Override
+ public StringList getNames() {
+ StringList ss = new StringList();
+ ss.add("java");
+ return ss;
+ }
+
+ @Override
+ public DataNative getDataModelVariables() {
+ Data data = new Data();
+ data.array.add(new Data("foo", Data.Type.VERBATIM));
+ return Data.toNative(data);
+ }
+
+ @Override
+ public void send(SendRequest req) {
+ System.out.println("send");
+ }
+
+ @Override
+ public WrappedIOProcessor create(Interpreter interpreter) {
+ return new TestCustomIOProc();
+ }
+
+ /**
+ * @param args
+ * @throws InterpreterException
+ */
+ public static void main(String[] args) throws InterpreterException {
+ System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib");
+
+ TestCustomIOProc ioproc = new TestCustomIOProc();
+ 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();
+ }
+
+}