diff options
author | Stefan Radomski <github@mintwerk.de> | 2014-06-23 23:39:53 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2014-06-23 23:39:53 (GMT) |
commit | 3d3f6a693ac51bca9b77133783a0fb296abd7ff6 (patch) | |
tree | 4580a433d410e91a6f8df9203c20693e7a21128d | |
parent | 95e1c41ea0e5522ae4e48234bd247a3f06ddf8d5 (diff) | |
parent | febde41c4c69d8f38967d5c195328d468834d037 (diff) | |
download | uscxml-3d3f6a693ac51bca9b77133783a0fb296abd7ff6.zip uscxml-3d3f6a693ac51bca9b77133783a0fb296abd7ff6.tar.gz uscxml-3d3f6a693ac51bca9b77133783a0fb296abd7ff6.tar.bz2 |
Merge pull request #40 from sradomski/master
Prepared the SCXML IRP
134 files changed, 3117 insertions, 1051 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 88f6874..e4ac449 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -719,6 +719,18 @@ if (LIBICAL_FOUND) endif() set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG}) +set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SHARED}) +if (NOT DEFINED ENV{LIBJINGLE_ROOT_DIR}) + set(ENV{LIBJINGLE_ROOT_DIR} "/Users/sradomski/Documents/TK/Code/webrtc-work/trunk") +endif() + +find_package(LIBJINGLE) +if (LIBJINGLE_FOUND) + include_directories (${LIBJINGLE_INCLUDE_DIRS}) + list (APPEND USCXML_OPT_LIBS ${LIBJINGLE_LIBRARIES}) +endif() +set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG}) + find_package(Expect) find_package(TCL) if (EXPECT_FOUND AND TCL_FOUND) @@ -1004,9 +1016,7 @@ if (NOT CMAKE_CROSSCOMPILING) add_subdirectory(test) endif() - if (NOT WIN32) - add_subdirectory(src/bindings) - endif() + add_subdirectory(src/bindings) endif() diff --git a/apps/samples/vrml/viewer.html b/apps/samples/vrml/viewer.html index bcddf2d..467681e 100644 --- a/apps/samples/vrml/viewer.html +++ b/apps/samples/vrml/viewer.html @@ -60,33 +60,52 @@ <script type="text/javascript"> require(["dojo/domReady!", "dojo"], function(dom, dojo) { - var viewer1 = new VRMLViewer("scene1", { - pose: { - pitch : 0, - roll : 0, - yaw : 0, - zoom : 1, - x : 0, - y : 0, - z : 0, - autorotate : true - }, - height: 300, - width: 400, - enableMovies: false, - enableDND: false, - enableWebGL: true, - enableSceneshots: false, - enableDraggables: false, - enablePosePublishing: true, - listNavigationStyle: true, - treeNavigationStyle: true, - listDirectory: "res_mp", - imagePath: "res_mp/RES_MP_VAL_074", - imageFormat: "png", - serverURL: "http://femkit.smartvortex.eu:8086/vrml/", + // var viewer1 = new VRMLViewer("scene1", { + // pose: { + // pitch : 0, + // roll : 0, + // yaw : 0, + // zoom : 1, + // x : 0, + // y : 0, + // z : 0, + // autorotate : true + // }, + // height: 300, + // width: 400, + // enableMovies: false, + // enableDND: false, + // enableWebGL: true, + // enableSceneshots: false, + // enableDraggables: false, + // enablePosePublishing: true, + // listNavigationStyle: true, + // treeNavigationStyle: true, + // listDirectory: "10975/57", + // imagePath: "10975/57/latest", + // imageFormat: "png", + // serverURL: "http://femkit.smartvortex.eu:8086/vrml/", + // }); + + var vrmlViewer = new VRMLViewer("scene1", { + resRoot: "/img/tridi/", + enableMovies: false, + enableDND: false, + enableWebGL: true, + enableSceneshots: false, + enableDraggables: false, + listNavigationStyle: true, + treeNavigationStyle: true, + width: 550, + height: 550, + imagePath: "/10975/56/latest", + imageFormat: "png", + listDirectory: "/10975/56", + serverURL: "http://femkit.smartvortex.eu:8086/vrml", }); + // http://femkit.smartvortex.eu:8086/vrml/10975/57/latest.osgjs + // var viewer2 = new VRMLViewer("scene2", { // pose: { // pitch : 0, diff --git a/apps/w3c-mmi/im/MMISessionManager.h b/apps/w3c-mmi/im/MMISessionManager.h index d3b0c48..222bf34 100644 --- a/apps/w3c-mmi/im/MMISessionManager.h +++ b/apps/w3c-mmi/im/MMISessionManager.h @@ -36,9 +36,9 @@ namespace uscxml { // IOProcessorImpl virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter); - virtual std::set<std::string> getNames() { - std::set<std::string> names; - names.insert("mmi.event"); + virtual std::list<std::string> getNames() { + std::list<std::string> names; + names.push_back("mmi.event"); return names; } virtual Data getDataModelVariables(); diff --git a/contrib/cmake/FindLibJingle.cmake b/contrib/cmake/FindLibJingle.cmake new file mode 100644 index 0000000..d8ed094 --- /dev/null +++ b/contrib/cmake/FindLibJingle.cmake @@ -0,0 +1,150 @@ +find_path(LIBJINGLE_INCLUDE_DIR + NAMES + talk/app/webrtc/peerconnectioninterface.h + HINTS + ${LIBJINGLE_ROOT_DIR} + ENV LIBJINGLE_ROOT_DIR + DOC + "libjingle include directory path" +) + +find_path(LIBJINGLE_THIRD_PARTY_INCLUDE_DIR + NAMES + webrtc/common_types.h + HINTS + ${LIBJINGLE_ROOT_DIR} + ENV LIBJINGLE_ROOT_DIR + PATH_SUFFIXES + third_party + DOC + "libjingle/third_party include directory path" +) + +find_path(LIBJINGLE_WEBRTC_INCLUDE_DIR + NAMES + common_types.h + HINTS + ${LIBJINGLE_ROOT_DIR} + ENV LIBJINGLE_ROOT_DIR + PATH_SUFFIXES + third_party/webrtc + webrtc + DOC + "libjingle/third_party/webrtc include directory path" +) + +set(REQUIRED_VARS LIBJINGLE_INCLUDE_DIR LIBJINGLE_THIRD_PARTY_INCLUDE_DIR LIBJINGLE_WEBRTC_INCLUDE_DIR) + +if(WIN32) + set(LIBJINGLE_SYSTEM_LIBS + wininet + dnsapi + version + msimg32 + ws2_32 + usp10 + psapi + dbghelp + winmm + shlwapi + kernel32 + gdi32 + winspool + comdlg32 + advapi32 + shell32 + ole32 + oleaut32 + user32 + uuid + odbc32 + odbccp32 + delayimp + Strmiids + dmoguids + wmcodecdspuuid + amstrmid + msdmo + ) + macro(set_libjingle_libs VARNAME CONFIGURATION) + set(${VARNAME} + ${LIBJINGLE_SYSTEM_LIBS} + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/jsoncpp.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjingle_peerconnection.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjingle.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/expat.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/crnss.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/nss_static.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/crnspr.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/sqlite3.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/icui18n.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/icuuc.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjingle_media.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libyuv.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjpeg.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_capture_module.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/webrtc_utility.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audio_coding_module.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/CNG.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/signal_processing.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/system_wrappers.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/G711.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/G722.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/iLBC.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/iSAC.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/iSACFix.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/PCM16B.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/NetEq.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/resampler.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/vad.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/webrtc_opus.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/opus.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/webrtc_video_coding.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/webrtc_i420.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/common_video.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_coding_utility.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/webrtc_vp8.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libvpx.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libvpx_asm_offsets.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libvpx_asm_offsets_vp9.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libvpx_intrinsics.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/directshow_baseclasses.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_render_module.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_engine_core.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/media_file.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/rtp_rtcp.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/remote_bitrate_estimator.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/paced_sender.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/udp_transport.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/bitrate_controller.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_processing.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/video_processing_sse2.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/voice_engine_core.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audio_conference_mixer.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audio_processing.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audioproc_debug_proto.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/protobuf_lite.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audio_processing_sse2.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/audio_device.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjingle_sound.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libjingle_p2p.lib + ${LIBJINGLE_ROOT_DIR}/build/${CONFIGURATION}/lib/libsrtp.lib + ) + endmacro() + set_libjingle_libs(LIBJINGLE_LIBRARIES_RELEASE Release) + set_libjingle_libs(LIBJINGLE_LIBRARIES_DEBUG Debug) + set_libjingle_libs(LIBJINGLE_LIBRARIES ${CMAKE_BUILD_TYPE}) +endif() + +# handle the QUIETLY and REQUIRED arguments and set SOFIA_SIP_UA_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBJINGLE + REQUIRED_VARS ${REQUIRED_VARS}) + +# Copy the results to the output variables. +if(LIBJINGLE_FOUND) + set(LIBJINGLE_INCLUDE_DIRS ${LIBJINGLE_INCLUDE_DIR} ${LIBJINGLE_THIRD_PARTY_INCLUDE_DIR} ${LIBJINGLE_WEBRTC_INCLUDE_DIR}) +endif() + +mark_as_advanced(${REQUIRED_VARS})
\ No newline at end of file diff --git a/contrib/csharp/embedding/embedding.sln b/contrib/csharp/embedding/embedding.sln new file mode 100644 index 0000000..0f9a49e --- /dev/null +++ b/contrib/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/contrib/csharp/embedding/embedding.suo b/contrib/csharp/embedding/embedding.suo Binary files differnew file mode 100644 index 0000000..f011087 --- /dev/null +++ b/contrib/csharp/embedding/embedding.suo diff --git a/contrib/csharp/embedding/embedding/Program.cs b/contrib/csharp/embedding/embedding/Program.cs new file mode 100644 index 0000000..3899178 --- /dev/null +++ b/contrib/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/contrib/csharp/embedding/embedding/Properties/AssemblyInfo.cs b/contrib/csharp/embedding/embedding/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bd9015e --- /dev/null +++ b/contrib/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/contrib/csharp/embedding/embedding/embedding.csproj b/contrib/csharp/embedding/embedding/embedding.csproj new file mode 100644 index 0000000..9c22f6c --- /dev/null +++ b/contrib/csharp/embedding/embedding/embedding.csproj @@ -0,0 +1,60 @@ +<?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>
+ </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>C:\Users\sradomski\Desktop\build\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/contrib/ctest/CTestCustom.ctest.in b/contrib/ctest/CTestCustom.ctest.in index ec4cb53..84d246b 100644 --- a/contrib/ctest/CTestCustom.ctest.in +++ b/contrib/ctest/CTestCustom.ctest.in @@ -9,90 +9,59 @@ # these are manual or xpath tests generated by the ecma generator set(CTEST_CUSTOM_TESTS_IGNORE - "ecma/test178.scxml" - "ecma/test230.scxml" - "ecma/test250.scxml" - "ecma/test463.scxml" - "ecma/test464.scxml" - "ecma/test465.scxml" - "ecma/test466.scxml" - "ecma/test467.scxml" - "ecma/test468.scxml" - "ecma/test469.scxml" - "ecma/test470.scxml" - "ecma/test473.scxml" - "ecma/test474.scxml" - "ecma/test475.scxml" - "ecma/test476.scxml" - "ecma/test477.scxml" - "ecma/test478.scxml" - "ecma/test479.scxml" - "ecma/test480.scxml" - "ecma/test481.scxml" - "ecma/test482.scxml" - "ecma/test483.scxml" - "ecma/test537.scxml" - "ecma/test539.scxml" - "ecma/test540.scxml" - "ecma/test542.scxml" - "ecma/test543.scxml" - "ecma/test544.scxml" - "ecma/test546.scxml" - "ecma/test547.scxml" - "ecma/test555.scxml" - "ecma/test568.scxml" + "ecma/test178.scxml" # Manual - PASSED + "ecma/test230.scxml" # Manual - PASSED + "ecma/test250.scxml" # Manual - PASSED + "ecma/test307.scxml" # Manual - PASSED + "ecma/test415.scxml" # Manual - PASSED + "ecma/test463.scxml" # XPath hardcoded + "ecma/test464.scxml" # XPath hardcoded + "ecma/test465.scxml" # XPath hardcoded + "ecma/test466.scxml" # XPath hardcoded + "ecma/test467.scxml" # XPath hardcoded + "ecma/test468.scxml" # XPath hardcoded + "ecma/test469.scxml" # XPath hardcoded + "ecma/test470.scxml" # XPath hardcoded + "ecma/test473.scxml" # XPath hardcoded + "ecma/test474.scxml" # XPath hardcoded + "ecma/test475.scxml" # XPath hardcoded + "ecma/test476.scxml" # XPath hardcoded + "ecma/test477.scxml" # XPath hardcoded + "ecma/test478.scxml" # XPath hardcoded + "ecma/test479.scxml" # XPath hardcoded + "ecma/test480.scxml" # XPath hardcoded + "ecma/test481.scxml" # XPath hardcoded + "ecma/test482.scxml" # XPath hardcoded + "ecma/test483.scxml" # XPath hardcoded + "ecma/test537.scxml" # XPath hardcoded + "ecma/test539.scxml" # XPath hardcoded + "ecma/test540.scxml" # XPath hardcoded + "ecma/test542.scxml" # XPath hardcoded + "ecma/test543.scxml" # XPath hardcoded + "ecma/test544.scxml" # XPath hardcoded + "ecma/test545.scxml" # XPath hardcoded + "ecma/test546.scxml" # XPath hardcoded + "ecma/test547.scxml" # XPath hardcoded + "ecma/test555.scxml" # XPath hardcoded + "ecma/test568.scxml" # XPath hardcoded "fsm/ecma/test178.scxml" # manual test "fsm/ecma/test224.scxml" # automatically generated id has the form stateid.platformid "fsm/ecma/test230.scxml" # manual test - # "fsm/ecma/test237.scxml" # test uninvoke - # "fsm/ecma/test240.scxml" # nested data was added in top state - # "fsm/ecma/test241.scxml" # succeeds with edits form above - # "fsm/ecma/test244.scxml" # succeeds with edits form above "fsm/ecma/test250.scxml" # manual test - - # "fsm/ecma/test252.scxml" - # "fsm/ecma/test280.scxml" - # "fsm/ecma/test294.scxml" # donedata hangs - # "fsm/ecma/test298.scxml" # " "fsm/ecma/test307.scxml" # manual test "fsm/ecma/test324.scxml" # _name can be assigned "fsm/ecma/test329.scxml" # system variables can be modified - # "fsm/ecma/test336.scxml" # succeeds with edits form above - # "fsm/ecma/test343.scxml" "fsm/ecma/test346.scxml" # change the value of a system variable - # "fsm/ecma/test349.scxml" # succeeds with edits form above - # "fsm/ecma/test377.scxml" # onexit handler order - # "fsm/ecma/test403b.scxml" - # "fsm/ecma/test403c.scxml" # problems with event preemption - # "fsm/ecma/test404.scxml" - # "fsm/ecma/test405.scxml" "fsm/ecma/test409.scxml" # In predicate "fsm/ecma/test411.scxml" # In predicate "fsm/ecma/test415.scxml" # manual test - # "fsm/ecma/test422.scxml" "fsm/ecma/test436.scxml" # In predicate - # "fsm/ecma/test488.scxml" # ? - # "fsm/ecma/test500.scxml" # succeeds with edits form above - # "fsm/ecma/test501.scxml" # succeeds with edits form above - # "fsm/ecma/test503.scxml" - # "fsm/ecma/test509.scxml" # succeeds with edits form above - # "fsm/ecma/test510.scxml" # succeeds with edits form above - # "fsm/ecma/test513.scxml" # succeeds with edits form above - # "fsm/ecma/test518.scxml" # succeeds with edits form above "fsm/ecma/test519.scxml" # unspecified basichttp format "fsm/ecma/test520.scxml" # unspecified basichttp format - # "fsm/ecma/test522.scxml" # succeeds with edits form above - # "fsm/ecma/test527.scxml" # ? - # "fsm/ecma/test528.scxml" # ? - # "fsm/ecma/test529.scxml" # ? "fsm/ecma/test531.scxml" # unspecified basichttp format - # "fsm/ecma/test532.scxml" # succeeds with edits form above "fsm/ecma/test534.scxml" # unspecified basichttp format - # "fsm/ecma/test542.scxml" # donedata hangs "fsm/ecma/test567.scxml" # unspecified basichttp format - # "fsm/ecma/test569.scxml" # succeeds with edits form above - # "fsm/ecma/test570.scxml" ) diff --git a/src/bindings/CMakeLists.txt b/src/bindings/CMakeLists.txt index b1f2429..667bfb9 100644 --- a/src/bindings/CMakeLists.txt +++ b/src/bindings/CMakeLists.txt @@ -1,9 +1,28 @@ +# if you build swig from sources on windows, this is where it will end up +# see also: http://www.swig.org/Doc2.0/Windows.html#Windows_mingw_msys +if (CMAKE_CROSSCOMPILING) + return() +endif() + +if (WIN32) + if(EXISTS "${PROJECT_BINARY_DIR}/../swig/") + LIST(APPEND CMAKE_PROGRAM_PATH "${PROJECT_BINARY_DIR}/../swig/") + elseif(EXISTS "${PROJECT_BINARY_DIR}/../../swig/") + LIST(APPEND CMAKE_PROGRAM_PATH "${PROJECT_BINARY_DIR}/../../swig/") + endif() + + LIST(APPEND CMAKE_PROGRAM_PATH "C:/Program Files/swig") # swig.exe +endif() +LIST(APPEND CMAKE_PROGRAM_PATH $ENV{SWIG_DIR}) + find_package(SWIG) + if (SWIG_FOUND) if(SWIG_VERSION VERSION_GREATER 2.0.4) MARK_AS_ADVANCED(SWIG_DIR SWIG_EXECUTABLE SWIG_VERSION) INCLUDE(${SWIG_USE_FILE}) add_subdirectory(swig/java) + add_subdirectory(swig/csharp) add_subdirectory(swig/php) else() message(STATUS "SWIG version 2.0.5 is required, found ${SWIG_VERSION} - skipping java wrapper generation") diff --git a/src/bindings/swig/csharp/CMakeLists.txt b/src/bindings/swig/csharp/CMakeLists.txt new file mode 100644 index 0000000..6310778 --- /dev/null +++ b/src/bindings/swig/csharp/CMakeLists.txt @@ -0,0 +1,85 @@ +# generate JNI library and create a jar +# Make from within Eclipse fails miserably with the whole thing + +if (WIN32) + LIST(APPEND CMAKE_PROGRAM_PATH "C:/Program Files (x86)/swig") # swig.exe + #LIST(APPEND CMAKE_PROGRAM_PATH "C:/Windows/Microsoft.NET/Framework/v4.0.30319") # CSharp compiler + LIST(APPEND CMAKE_PROGRAM_PATH "C:/Windows/Microsoft.NET/Framework/v3.5") # CSharp compiler +endif() + +FIND_PROGRAM(DMCS_EXECUTABLE dmcs PATHS $ENV{DMCS_HOME} ENV PATH ) # Mono compiler +FIND_PROGRAM(CSC_EXECUTABLE csc PATHS $ENV{CSC_HOME} ENV PATH ) # CSharp compiler + +if (DMCS_EXECUTABLE OR CSC_EXECUTABLE) + + # unset all library suffixes as swig will hardcode a library without + SET(LIB_POSTFIX ${CMAKE_LIBRARY_POSTFIX}) + + SET(CMAKE_DEBUG_POSTFIX "") + SET(CMAKE_RELEASE_POSTFIX "") + SET(CMAKE_RELWITHDEBINFO_POSTFIX "") + SET(CMAKE_MINSIZEREL_POSTFIX "") + SET(CMAKE_LIBRARY_POSTFIX "") + + if (MSVC) + # MSVC does not include inttypes.h but SWIG needs it + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../msvc) + endif() + + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + + SET(CMAKE_SWIG_FLAGS "") + SET(USCXML_CSHARP_NAMESPACE "org.uscxml") + SET(USCXML_CSHARP_DIR "org/uscxml") + + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + list(APPEND CMAKE_SWIG_FLAGS "-DDEBUG") + endif() + + + # we need ; to produce a space with the package .. weird + SET_SOURCE_FILES_PROPERTIES(uscxml.i PROPERTIES SWIG_FLAGS "-w401;-namespace;${USCXML_CSHARP_NAMESPACE}") + SET_SOURCE_FILES_PROPERTIES(uscxml.i PROPERTIES CPLUSPLUS ON) + SET(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/${USCXML_CSHARP_DIR}") + + set(USCXML_LANGUAGE_BINDINGS "csharp ${USCXML_LANGUAGE_BINDINGS}") + + SWIG_ADD_MODULE(uscxmlNativeCSharp csharp uscxml.i) + set_target_properties(uscxmlNativeCSharp PROPERTIES FOLDER "Bindings") + set_target_properties(uscxmlNativeCSharp + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/csharp${LIB_POSTFIX}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/csharp${LIB_POSTFIX}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/csharp${LIB_POSTFIX}" + ) + + set_target_properties(uscxmlNativeCSharp PROPERTIES COMPILE_FLAGS "-DSWIG") + swig_link_libraries(uscxmlNativeCSharp uscxml) + + # build managed code part + if (CSC_EXECUTABLE) + ADD_CUSTOM_TARGET(csharp + COMMAND ${CSC_EXECUTABLE} + /target:library + /out:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/uscxmlCSharp.dll + *.cs + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src/bindings/swig/csharp/org/uscxml + COMMENT "Creating umundoCSharp.dll for C# ...") + else() + ADD_CUSTOM_TARGET(csharp + COMMAND ${DMCS_EXECUTABLE} + -target:library + /out:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/uscxmlCSharp.dll + *.cs + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src/bindings/swig/csharp/org/uscxml + COMMENT "Creating umundoCSharp.dll for Mono ...") + endif() + + add_dependencies(csharp umundoNativeCSharp) + if (BUILD_TESTS) + add_dependencies(ALL_TESTS csharp) + endif() + set_target_properties(csharp PROPERTIES FOLDER "Bindings") + + set(USCXML_LANGUAGE_BINDINGS ${USCXML_LANGUAGE_BINDINGS} PARENT_SCOPE) +endif()
\ No newline at end of file diff --git a/src/bindings/swig/java/stl_list.i b/src/bindings/swig/csharp/stl_list.i index aabd448..aabd448 100644 --- a/src/bindings/swig/java/stl_list.i +++ b/src/bindings/swig/csharp/stl_list.i diff --git a/src/bindings/swig/java/stl_set.i b/src/bindings/swig/csharp/stl_set.i index d009a7b..d009a7b 100644 --- a/src/bindings/swig/java/stl_set.i +++ b/src/bindings/swig/csharp/stl_set.i diff --git a/src/bindings/swig/csharp/uscxml.i b/src/bindings/swig/csharp/uscxml.i new file mode 100644 index 0000000..07604c4 --- /dev/null +++ b/src/bindings/swig/csharp/uscxml.i @@ -0,0 +1,185 @@ +%module(directors="1", allprotected="1") uscxmlNativeCSharp + +// provide a macro for the header files +#define SWIGIMPORTED 1 + +// import swig typemaps +//%include <inttypes.i> + +%include <stl.i> +%include <std_map.i> +%include <std_string.i> +%include <inttypes.i> +%include "../stl_set.i" +%include "../stl_list.i" + +%include <boost_shared_ptr.i> + +typedef uscxml::Data Data; +typedef uscxml::Event Event; +typedef uscxml::InvokeRequest InvokeRequest; +typedef uscxml::SendRequest SendRequest; + +// disable warning related to unknown base class +#pragma SWIG nowarn=401 +//%ignore boost::enable_shared_from_this; + +%csconst(1); + +# %shared_ptr(uscxml::dom::Element); +# %shared_ptr(uscxml::dom::Executable); + +%rename(equals) operator==; +%rename(isValid) operator bool; +%ignore operator!=; +%ignore operator<; +%ignore operator=; +%ignore operator[]; +%ignore operator std::list<Data>; +%ignore operator std::string; +%ignore operator std::map<std::string,Data>; +%ignore operator<<; + + +//************************************************** +// This ends up in the generated wrapper code +//************************************************** + +%{ + +#include "../../../uscxml/Message.h" +#include "../../../uscxml/Factory.h" +#include "../../../uscxml/Interpreter.h" + +//#include <DOM/Document.hpp> +//#include <DOM/Node.hpp> +//#include <DOM/Element.hpp> +//#include <DOM/Attr.hpp> +//#include <DOM/Text.hpp> + +#include "../wrapped/WrappedInvoker.h" +#include "../wrapped/WrappedDataModel.h" + +using namespace uscxml; +using namespace Arabica::DOM; + +#include "../wrapped/WrappedInvoker.cpp" +#include "../wrapped/WrappedDataModel.cpp" + +%} + +%ignore uscxml::NumAttr; +%ignore uscxml::SCXMLParser; +%ignore uscxml::InterpreterImpl; + +%ignore create(); + +%ignore uscxml::Interpreter::getDelayQueue(); + +%ignore uscxml::WrappedInvoker::create(InterpreterImpl*); + +%ignore uscxml::WrappedDataModel::create(InterpreterImpl*); +%ignore uscxml::WrappedDataModel::init(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); +%ignore uscxml::WrappedDataModel::init(const std::string&, const Data&); +%ignore uscxml::WrappedDataModel::assign(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); +%ignore uscxml::WrappedDataModel::assign(const std::string&, const Data&); +%ignore uscxml::WrappedDataModel::eval(const Arabica::DOM::Element<std::string>&, const std::string&); + +%ignore uscxml::Event::Event(const Arabica::DOM::Node<std::string>&); +%ignore uscxml::Event::getStrippedDOM; +%ignore uscxml::Event::getFirstDOMElement; +%ignore uscxml::Event::getDOM(); +%ignore uscxml::Event::setDOM(const Arabica::DOM::Document<std::string>&); +%ignore uscxml::Event::toDocument(); + +%template(DataList) std::list<uscxml::Data>; +%template(DataMap) std::map<std::string, uscxml::Data>; +%template(StringSet) std::set<std::string>; +%template(StringVector) std::vector<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>; + +%rename Data DataNative; + +%feature("director") uscxml::WrappedInvoker; +%feature("director") uscxml::WrappedDataModel; + +// translate param multimap to Map<String, List<Data> > +%rename(getParamsNative) uscxml::Event::getParams(); +%csmethodmodifiers uscxml::Event::getParams() "private"; + +%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(); + while(paramPairIter != self->getParams().end()) { + pairs.push_back(*paramPairIter); + paramPairIter++; + } + return pairs; + } +}; + +%extend uscxml::Interpreter { + std::vector<std::string> getIOProcessorKeys() { + std::vector<std::string> keys; + std::map<std::string, IOProcessor>::const_iterator iter = self->getIOProcessors().begin(); + while(iter != self->getIOProcessors().end()) { + keys.push_back(iter->first); + iter++; + } + return keys; + } + + std::vector<std::string> getInvokerKeys() { + std::vector<std::string> keys; + std::map<std::string, Invoker>::const_iterator iter = self->getInvokers().begin(); + while(iter != self->getInvokers().end()) { + keys.push_back(iter->first); + iter++; + } + return keys; + } + +}; + +%extend uscxml::Data { + std::vector<std::string> getCompundKeys() { + std::vector<std::string> keys; + std::map<std::string, Data>::const_iterator iter = self->compound.begin(); + while(iter != self->compound.end()) { + keys.push_back(iter->first); + iter++; + } + return keys; + } +}; + + + +//*********************************************** +// Parse the header file to generate wrappers +//*********************************************** + +%include "../../../uscxml/Common.h" +%include "../../../uscxml/Factory.h" +%include "../../../uscxml/Message.h" +%include "../../../uscxml/Interpreter.h" +#include "../../../uscxml/DOMUtils.h" + +# %include <DOM/Document.hpp> +# %include <DOM/Node.hpp> +# %include <DOM/Element.hpp> +# %include <DOM/Attr.hpp> +# %include <DOM/Text.hpp> + +%include "../wrapped/WrappedInvoker.h" +%include "../wrapped/WrappedDataModel.h" + +# %template(XMLDocument) Arabica::DOM::Document<std::string>; +# %template(XMLNode) Arabica::DOM::Node<std::string>; +# %template(XMLElement) Arabica::DOM::Element<std::string>; +# %template(XMLAttr) Arabica::DOM::Attr<std::string>; +# %template(XMLText) Arabica::DOM::Text<std::string>; diff --git a/src/bindings/swig/java/JavaDataModel.cpp b/src/bindings/swig/java/JavaDataModel.cpp deleted file mode 100644 index 896794b..0000000 --- a/src/bindings/swig/java/JavaDataModel.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "JavaDataModel.h" - -namespace uscxml { - -JavaDataModel::JavaDataModel() {} -JavaDataModel::~JavaDataModel() {} - -}
\ No newline at end of file diff --git a/src/bindings/swig/java/JavaInvoker.cpp b/src/bindings/swig/java/JavaInvoker.cpp deleted file mode 100644 index e1c6a31..0000000 --- a/src/bindings/swig/java/JavaInvoker.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "JavaInvoker.h" - -namespace uscxml { - -JavaInvoker::JavaInvoker() {} -JavaInvoker::~JavaInvoker() {} - -}
\ No newline at end of file diff --git a/src/bindings/swig/java/org/uscxml/Data.java b/src/bindings/swig/java/org/uscxml/Data.java index fdd7448..7781f47 100644 --- a/src/bindings/swig/java/org/uscxml/Data.java +++ b/src/bindings/swig/java/org/uscxml/Data.java @@ -80,7 +80,7 @@ public class Data { if (data.type == Type.INTERPRETED) { nativeData.setType(DataNative.Type.INTERPRETED); } else { - nativeData.setType(DataNative.Type.VERBATIM); + nativeData.setType(DataNative.Type.VERBATIM); } } return nativeData; diff --git a/src/bindings/swig/java/uscxml.i b/src/bindings/swig/java/uscxml.i index 5dac9d2..f72084e 100644 --- a/src/bindings/swig/java/uscxml.i +++ b/src/bindings/swig/java/uscxml.i @@ -9,10 +9,10 @@ %include <stl.i> %include <std_map.i> -%include "std_string.i" +%include <std_string.i> %include <inttypes.i> -%include "stl_set.i" -%include "stl_list.i" +%include "../stl_set.i" +%include "../stl_list.i" %include <boost_shared_ptr.i> @@ -59,14 +59,14 @@ typedef uscxml::SendRequest SendRequest; //#include <DOM/Attr.hpp> //#include <DOM/Text.hpp> -#include "JavaInvoker.h" -#include "JavaDataModel.h" +#include "../wrapped/WrappedInvoker.h" +#include "../wrapped/WrappedDataModel.h" using namespace uscxml; using namespace Arabica::DOM; -#include "JavaInvoker.cpp" -#include "JavaDataModel.cpp" +#include "../wrapped/WrappedInvoker.cpp" +#include "../wrapped/WrappedDataModel.cpp" %} @@ -78,14 +78,14 @@ using namespace Arabica::DOM; %ignore uscxml::Interpreter::getDelayQueue(); -%ignore uscxml::JavaInvoker::create(InterpreterImpl*); +%ignore uscxml::WrappedInvoker::create(InterpreterImpl*); -%ignore uscxml::JavaDataModel::create(InterpreterImpl*); -%ignore uscxml::JavaDataModel::init(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); -%ignore uscxml::JavaDataModel::init(const std::string&, const Data&); -%ignore uscxml::JavaDataModel::assign(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); -%ignore uscxml::JavaDataModel::assign(const std::string&, const Data&); -%ignore uscxml::JavaDataModel::eval(const Arabica::DOM::Element<std::string>&, const std::string&); +%ignore uscxml::WrappedDataModel::create(InterpreterImpl*); +%ignore uscxml::WrappedDataModel::init(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); +%ignore uscxml::WrappedDataModel::init(const std::string&, const Data&); +%ignore uscxml::WrappedDataModel::assign(const Arabica::DOM::Element<std::string>&, const Arabica::DOM::Document<std::string>&, const std::string&); +%ignore uscxml::WrappedDataModel::assign(const std::string&, const Data&); +%ignore uscxml::WrappedDataModel::eval(const Arabica::DOM::Element<std::string>&, const std::string&); %ignore uscxml::Event::Event(const Arabica::DOM::Node<std::string>&); %ignore uscxml::Event::getStrippedDOM; @@ -104,16 +104,9 @@ using namespace Arabica::DOM; %template(InvokerMap) std::map<std::string, uscxml::Invoker>; %rename Data DataNative; -# %typemap(jstype) uscxml::Data "Data" -# %typemap(javaout) uscxml::Data { -# return new Data(new DataNative($jnicall, $owner)); -# } -# %typemap(javadirectorin) uscxml::Data "new Data($jniinput)" -# %typemap(javadirectorout) uscxml::Data "new Data($jniinput)" - -%feature("director") uscxml::JavaInvoker; -%feature("director") uscxml::JavaDataModel; +%feature("director") uscxml::WrappedInvoker; +%feature("director") uscxml::WrappedDataModel; // translate param multimap to Map<String, List<Data> > %rename(getParamsNative) uscxml::Event::getParams(); @@ -184,8 +177,8 @@ using namespace Arabica::DOM; # %include <DOM/Attr.hpp> # %include <DOM/Text.hpp> -%include "JavaInvoker.h" -%include "JavaDataModel.h" +%include "../wrapped/WrappedInvoker.h" +%include "../wrapped/WrappedDataModel.h" # %template(XMLDocument) Arabica::DOM::Document<std::string>; # %template(XMLNode) Arabica::DOM::Node<std::string>; diff --git a/src/bindings/swig/msvc/inttypes.h b/src/bindings/swig/msvc/inttypes.h new file mode 100644 index 0000000..eac641e --- /dev/null +++ b/src/bindings/swig/msvc/inttypes.h @@ -0,0 +1,304 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ]
\ No newline at end of file diff --git a/src/bindings/swig/stl_list.i b/src/bindings/swig/stl_list.i new file mode 100644 index 0000000..aabd448 --- /dev/null +++ b/src/bindings/swig/stl_list.i @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * std_list.i + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> + +%{ +#include <list> +#include <stdexcept> +%} + +namespace std { + + template<class T> class list { + public: + typedef size_t size_type; + typedef T value_type; + typedef const value_type& const_reference; + list(); + size_type size() const; + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(add) push_back; + void push_back(const value_type& x); + %extend { + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + int j; + if (i>=0 && i<size) { + std::list<T>::const_iterator p; + p=self->begin(); + for (j=0; j<i; j++) {p++;} + return (*p); + } + else + throw std::out_of_range("list index out of range"); + } + } + }; +} + +%define specialize_std_list(T) +#warning "specialize_std_list - specialization for type T no longer needed" +%enddef + diff --git a/src/bindings/swig/stl_set.i b/src/bindings/swig/stl_set.i new file mode 100644 index 0000000..d009a7b --- /dev/null +++ b/src/bindings/swig/stl_set.i @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* ----------------------------------------------------------------------------- + * std_set.i + * + * SWIG typemaps for std::set + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> + +// ------------------------------------------------------------------------ +// std::set +// ------------------------------------------------------------------------ + +%{ +#include <set> +#include <algorithm> +#include <stdexcept> +%} + +// exported class + +namespace std { + + template<class V> class set { + // add typemaps here + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef V value_type; + set(); + set(const set<V> &); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const V& get(const V& key) throw (std::out_of_range) { + std::set<V>::iterator i = self->find(key); + if (i != self->end()) + return *i; + else + throw std::out_of_range("key not found"); + } + void insert(const V& key) { // Do NOT call this function 'set' ! + self->insert(key); + } + void del(const V& key) throw (std::out_of_range) { + std::set<V>::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const V& key) { + std::set<V>::iterator i = self->find(key); + return i != self->end(); + } + } + }; + +}
\ No newline at end of file diff --git a/src/bindings/swig/wrapped/WrappedDataModel.cpp b/src/bindings/swig/wrapped/WrappedDataModel.cpp new file mode 100644 index 0000000..901d246 --- /dev/null +++ b/src/bindings/swig/wrapped/WrappedDataModel.cpp @@ -0,0 +1,8 @@ +#include "WrappedDataModel.h" + +namespace uscxml { + +WrappedDataModel::WrappedDataModel() {} +WrappedDataModel::~WrappedDataModel() {} + +}
\ No newline at end of file diff --git a/src/bindings/swig/java/JavaDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h index 5da0cda..285b40a 100644 --- a/src/bindings/swig/java/JavaDataModel.h +++ b/src/bindings/swig/wrapped/WrappedDataModel.h @@ -1,5 +1,5 @@ -#ifndef JAVADataModel_H_7U446XJQ -#define JAVADataModel_H_7U446XJQ +#ifndef WRAPPEDDATAMODEL_H_DBAAD6AF +#define WRAPPEDDATAMODEL_H_DBAAD6AF #include "../../../uscxml/Message.h" #include "../../../uscxml/Factory.h" @@ -7,13 +7,13 @@ namespace uscxml { -class JavaDataModel : public DataModelImpl { +class WrappedDataModel : public DataModelImpl { public: - JavaDataModel(); - virtual ~JavaDataModel(); + WrappedDataModel(); + virtual ~WrappedDataModel(); - virtual JavaDataModel* create(const Interpreter& interpreter) { - return new JavaDataModel(); + virtual WrappedDataModel* create(const Interpreter& interpreter) { + return new WrappedDataModel(); } virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter) { @@ -96,8 +96,6 @@ public: init("", location, Data::toJSON(data)); } - // this is assign the function exposed to java - virtual void init(const Arabica::DOM::Element<std::string>& dataElem, const Arabica::DOM::Node<std::string>& node, const std::string& content) { @@ -126,7 +124,6 @@ public: init("", location, Data::toJSON(data)); } - // these functions are exposed to java virtual bool evalAsBool(const std::string& elem, const std::string& content) { return false; } virtual void init(const std::string& dataElem, const std::string& location, const std::string& content) {} virtual void assign(const std::string& assignElem, const std::string& location, const std::string& content) {} @@ -138,4 +135,4 @@ private: } -#endif /* end of include guard: JAVADataModel_H_7U446XJQ */ +#endif /* end of include guard: WRAPPEDDATAMODEL_H_DBAAD6AF */ diff --git a/src/bindings/swig/wrapped/WrappedInvoker.cpp b/src/bindings/swig/wrapped/WrappedInvoker.cpp new file mode 100644 index 0000000..b775878 --- /dev/null +++ b/src/bindings/swig/wrapped/WrappedInvoker.cpp @@ -0,0 +1,8 @@ +#include "WrappedInvoker.h" + +namespace uscxml { + +WrappedInvoker::WrappedInvoker() {} +WrappedInvoker::~WrappedInvoker() {} + +}
\ No newline at end of file diff --git a/src/bindings/swig/java/JavaInvoker.h b/src/bindings/swig/wrapped/WrappedInvoker.h index 8994ab5..61eedac 100644 --- a/src/bindings/swig/java/JavaInvoker.h +++ b/src/bindings/swig/wrapped/WrappedInvoker.h @@ -1,5 +1,5 @@ -#ifndef JAVAINVOKER_H_WDV9B5F6 -#define JAVAINVOKER_H_WDV9B5F6 +#ifndef WRAPPEDINVOKER_H_F9725D47 +#define WRAPPEDINVOKER_H_F9725D47 #include "../../../uscxml/Message.h" #include "../../../uscxml/Factory.h" @@ -7,10 +7,10 @@ namespace uscxml { -class JavaInvoker : public InvokerImpl { +class WrappedInvoker : public InvokerImpl { public: - JavaInvoker(); - virtual ~JavaInvoker(); + WrappedInvoker(); + virtual ~WrappedInvoker(); virtual std::list<std::string> getNames() { return std::list<std::string>(); @@ -24,8 +24,8 @@ public: virtual void send(const SendRequest& req) {} virtual void invoke(const InvokeRequest& req) {} - virtual JavaInvoker* create(Interpreter interpreter) { - return new JavaInvoker(); + virtual WrappedInvoker* create(Interpreter interpreter) { + return new WrappedInvoker(); } virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) { @@ -36,4 +36,4 @@ public: } -#endif /* end of include guard: JAVAINVOKER_H_WDV9B5F6 */ +#endif /* end of include guard: WRAPPEDINVOKER_H_F9725D47 */ diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index c63fc0d..5b7426f 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -24,6 +24,8 @@ #include "uscxml/Interpreter.h" #include <glog/logging.h> +#include "uscxml/plugins/datamodel/null/NULLDataModel.h" + // see http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system #ifdef BUILD_AS_PLUGINS @@ -100,7 +102,6 @@ # include "uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h" # endif -#include "uscxml/plugins/datamodel/null/NULLDataModel.h" #include "uscxml/plugins/datamodel/xpath/XPathDataModel.h" #include "uscxml/plugins/datamodel/promela/PromelaDataModel.h" @@ -142,8 +143,6 @@ std::string Factory::getDefaultPluginPath() { } void Factory::registerPlugins() { -#ifdef BUILD_AS_PLUGINS - // these are part of core { InterpreterHTTPServlet* ioProcessor = new InterpreterHTTPServlet(); registerIOProcessor(ioProcessor); @@ -152,6 +151,13 @@ void Factory::registerPlugins() { InterpreterWebSocketServlet* ioProcessor = new InterpreterWebSocketServlet(); registerIOProcessor(ioProcessor); } + { + NULLDataModel* dataModel = new NULLDataModel(); + registerDataModel(dataModel); + } + +#ifdef BUILD_AS_PLUGINS + // these are part of core if (_pluginPath.length() == 0) { // try to read USCXML_PLUGIN_PATH environment variable @@ -291,14 +297,12 @@ void Factory::registerPlugins() { } #endif -#if 1 #if (defined BUILD_DM_PROMELA) { PromelaDataModel* dataModel = new PromelaDataModel(); registerDataModel(dataModel); } #endif -#endif #ifdef BUILD_DM_XPATH { @@ -323,10 +327,6 @@ void Factory::registerPlugins() { #endif // these are always available - { - NULLDataModel* dataModel = new NULLDataModel(); - registerDataModel(dataModel); - } #if 1 { XHTMLInvoker* invoker = new XHTMLInvoker(); @@ -690,7 +690,7 @@ void EventHandlerImpl::returnEvent(Event& event) { void DataModelImpl::throwErrorExecution(const std::string& cause) { uscxml::Event exc; - exc.data.compound["exception"] = uscxml::Data(cause, uscxml::Data::VERBATIM); + exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); exc.name = "error.execution"; exc.eventType = uscxml::Event::PLATFORM; throw exc; @@ -698,7 +698,7 @@ void DataModelImpl::throwErrorExecution(const std::string& cause) { void DataModelImpl::throwErrorPlatform(const std::string& cause) { uscxml::Event exc; - exc.data.compound["exception"] = uscxml::Data(cause, uscxml::Data::VERBATIM); + exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); exc.name = "error.platform"; exc.eventType = uscxml::Event::PLATFORM; throw exc; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 3d3c181..f3d30de 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -50,6 +50,47 @@ #define VERBOSE 0 +/// valid interpreter state transitions +#define VALID_FROM_INSTANTIATED(newState) ( \ + newState == InterpreterState::USCXML_FAULTED || \ + newState == InterpreterState::USCXML_MICROSTEPPED || \ + newState == InterpreterState::USCXML_DESTROYED\ +) + +#define VALID_FROM_FAULTED(newState) ( \ + newState == InterpreterState::USCXML_DESTROYED\ +) + +#define VALID_FROM_INITIALIZED(newState) ( \ + newState == InterpreterState::USCXML_MICROSTEPPED || \ + newState == InterpreterState::USCXML_FINISHED \ +) + +#define VALID_FROM_MICROSTEPPED(newState) ( \ + newState == InterpreterState::USCXML_DESTROYED || \ + newState == InterpreterState::USCXML_MACROSTEPPED || \ + newState == InterpreterState::USCXML_MICROSTEPPED || \ + newState == InterpreterState::USCXML_FINISHED \ +) + +#define VALID_FROM_MACROSTEPPED(newState) ( \ + newState == InterpreterState::USCXML_DESTROYED || \ + newState == InterpreterState::USCXML_MICROSTEPPED || \ + newState == InterpreterState::USCXML_IDLE || \ + newState == InterpreterState::USCXML_FINISHED \ +) + +#define VALID_FROM_IDLE(newState) ( \ + newState == InterpreterState::USCXML_DESTROYED || \ + newState == InterpreterState::USCXML_MICROSTEPPED \ +) + +#define VALID_FROM_FINISHED(newState) ( \ + newState == InterpreterState::USCXML_DESTROYED || \ + newState == InterpreterState::USCXML_INSTANTIATED \ +) + + /// macro to catch exceptions in executeContent #define CATCH_AND_DISTRIBUTE(msg) \ catch (Event e) {\ @@ -169,7 +210,7 @@ InterpreterOptions InterpreterOptions::fromCmdLine(int argc, char** argv) { } switch(option) { - // cases without short option + // cases without short option case 0: { if (boost::equals(longOptions[optionInd].name, "disable-http")) { currOptions->withHTTP = false; @@ -269,7 +310,7 @@ void NameSpaceInfo::init(const std::map<std::string, std::string>& namespaceInfo nsIter++; } } - + std::map<std::string, boost::weak_ptr<InterpreterImpl> > Interpreter::_instances; tthread::recursive_mutex Interpreter::_instanceMutex; @@ -288,15 +329,16 @@ std::map<std::string, boost::weak_ptr<InterpreterImpl> > Interpreter::getInstanc InterpreterImpl::InterpreterImpl() { + _state.state = InterpreterState::USCXML_INSTANTIATED; + _state.thread = 0; _lastRunOnMainThread = 0; _thread = NULL; _sendQueue = NULL; _parentQueue = NULL; - _running = false; - _destroyed = false; - _done = true; + _topLevelFinalReached = false; _stable = false; _isInitialized = false; + _domIsSetup = false; _httpServlet = NULL; _factory = NULL; _sessionId = UUID::getUUID(); @@ -317,7 +359,7 @@ Interpreter Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom, interpreterImpl->setNameSpaceInfo(nameSpaceInfo); interpreterImpl->_document = dom; - interpreterImpl->init(); +// interpreterImpl->init(); _instances[interpreterImpl->getSessionId()] = interpreterImpl; return interpreter; } @@ -389,20 +431,17 @@ Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& } boost::shared_ptr<INTERPRETER_IMPL> interpreterImpl = boost::shared_ptr<INTERPRETER_IMPL>(new INTERPRETER_IMPL); - Interpreter interpreter; + Interpreter interpreter(interpreterImpl); + _instances[interpreterImpl->getSessionId()] = interpreterImpl; + NameSpacingParser parser; if (parser.parse(source) && parser.getDocument() && parser.getDocument().hasChildNodes()) { interpreterImpl->setNameSpaceInfo(parser.nameSpace); interpreterImpl->_document = parser.getDocument(); -// interpreterImpl->init(); - interpreter = Interpreter(interpreterImpl); - _instances[interpreterImpl->getSessionId()] = interpreterImpl; } else { - if (parser.errorsReported()) { - LOG(ERROR) << parser.errors(); - } +// assert(parser.errorsReported()); + interpreterImpl->setInterpreterState(InterpreterState::USCXML_FAULTED, parser.errors()); } - // interpreter->init(); return interpreter; } @@ -459,20 +498,15 @@ void InterpreterImpl::copyTo(boost::shared_ptr<InterpreterImpl> other) { copyTo(other.get()); } - void InterpreterImpl::setName(const std::string& name) { - if (!_running) { - _name = name; - } else { - LOG(ERROR) << "Cannot change name of running interpreter"; - } + _name = name; } InterpreterImpl::~InterpreterImpl() { { // make sure we are done with setting up with early abort tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - _running = false; + stop(); // unset started bit } // std::cout << "stopped " << this << std::endl; // tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); @@ -488,27 +522,53 @@ InterpreterImpl::~InterpreterImpl() { delete(_thread); } else { // this can happen with a shared_from_this at an interpretermonitor - _destroyed = true; + setInterpreterState(InterpreterState::USCXML_DESTROYED); } } + join(); if (_sendQueue) delete _sendQueue; } void InterpreterImpl::start() { - _done = false; + _state.thread |= InterpreterState::USCXML_THREAD_STARTED; _thread = new tthread::thread(InterpreterImpl::run, this); } void InterpreterImpl::stop() { - _running = false; + _state.thread &= ~InterpreterState::USCXML_THREAD_STARTED; } +void InterpreterImpl::join() { + stop(); + if (_thread != NULL) _thread->join(); +}; + +bool InterpreterImpl::isRunning() { + // return _running || !_topLevelFinalReached; + return _state.thread & InterpreterState::USCXML_THREAD_RUNNING; +} void InterpreterImpl::run(void* instance) { + InterpreterImpl* interpreter = ((InterpreterImpl*)instance); + interpreter->_state.thread |= InterpreterState::USCXML_THREAD_RUNNING; + try { - ((InterpreterImpl*)instance)->interpret(); + InterpreterState state; + while(interpreter->_state.thread & InterpreterState::USCXML_THREAD_STARTED) { + state = interpreter->step(-1); + + switch (state & InterpreterState::USCXML_INTERPRETER_MASK) { + case uscxml::InterpreterState::USCXML_FAULTED: + case uscxml::InterpreterState::USCXML_FINISHED: + case uscxml::InterpreterState::USCXML_DESTROYED: + // return as we finished + goto DONE_THREAD; + default: + break; + } + } } catch (Event e) { LOG(ERROR) << e; } catch(boost::bad_lexical_cast e) { @@ -516,12 +576,73 @@ void InterpreterImpl::run(void* instance) { } catch (...) { LOG(ERROR) << "InterpreterImpl::run catched unknown exception"; } - ((InterpreterImpl*)instance)->_done = true; - ((InterpreterImpl*)instance)->_running = false; +DONE_THREAD: + ((InterpreterImpl*)instance)->_state.thread &= ~InterpreterState::USCXML_THREAD_RUNNING; + ((InterpreterImpl*)instance)->_state.thread &= ~InterpreterState::USCXML_THREAD_STARTED; +} + +InterpreterState InterpreterImpl::getInterpreterState() { + return _state; +} + +void InterpreterImpl::setInterpreterState(InterpreterState::State newState) { + setInterpreterState(newState, Event()); } +void InterpreterImpl::setInterpreterState(InterpreterState::State newState, const std::string& error) { + Event e; + e.name = "error.platform"; + e.data.compound["cause"] = Data(error, Data::VERBATIM); + setInterpreterState(newState, e); +} + +void InterpreterImpl::setInterpreterState(InterpreterState::State newState, const Event& error) { + switch (_state) { + case InterpreterState::USCXML_INSTANTIATED: + if (VALID_FROM_INSTANTIATED(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_FAULTED: + if (VALID_FROM_FAULTED(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_MICROSTEPPED: + if (VALID_FROM_MICROSTEPPED(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_MACROSTEPPED: + if (VALID_FROM_MACROSTEPPED(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_IDLE: + if (VALID_FROM_IDLE(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_FINISHED: + if (VALID_FROM_FINISHED(newState)) + break; + assert(false); + break; + case InterpreterState::USCXML_DESTROYED: + assert(false); + break; + + default: + break; + } + + _state.state = newState; + _state.msg = error; +} + bool InterpreterImpl::runOnMainThread(int fps, bool blocking) { - if (_done) + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); + if (_state == InterpreterState::USCXML_FINISHED || _state == InterpreterState::USCXML_FAULTED || _state == InterpreterState::USCXML_DESTROYED) return false; if (fps > 0) { @@ -553,13 +674,31 @@ bool InterpreterImpl::runOnMainThread(int fps, bool blocking) { return (_thread != NULL); } -void InterpreterImpl::init() { - if (!_document) { - LOG(ERROR) << "Interpreter has no DOM at all!" << std::endl; - _done = true; +void InterpreterImpl::reset() { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); + + _externalQueue.clear(); + _internalQueue.clear(); + _historyValue.clear(); + + _alreadyEntered = NodeSet<std::string>(); + _configuration = NodeSet<std::string>(); + _topLevelFinalReached = false; + _isInitialized = false; + + setInterpreterState(InterpreterState::USCXML_INSTANTIATED); +} + +void InterpreterImpl::setupAndNormalizeDOM() { + if (_domIsSetup) return; - } + if (!_document) { + Event error("error.platform"); + error.data.compound["cause"] = Data("Interpreter has no DOM", Data::VERBATIM); + throw error; + } + // find scxml element NodeList<std::string> scxmls; if (_nsInfo.nsURL.size() == 0) { @@ -567,54 +706,79 @@ void InterpreterImpl::init() { } else { scxmls = _document.getElementsByTagNameNS(_nsInfo.nsURL, "scxml"); } - - if (scxmls.getLength() > 0) { - _scxml = (Arabica::DOM::Element<std::string>)scxmls.item(0); - // setup xpath and check that it works - if (_nsInfo.getNSContext() != NULL) - _xpath.setNamespaceContext(*_nsInfo.getNSContext()); + if (scxmls.getLength() == 0) { + Event error("error.platform"); + error.data.compound["cause"] = Data("Cannot find SCXML element in DOM", Data::VERBATIM); + throw error; + } - if (_name.length() == 0) - _name = (HAS_ATTR(_scxml, "name") ? ATTR(_scxml, "name") : UUID::getUUID()); + _scxml = (Arabica::DOM::Element<std::string>)scxmls.item(0); - // normalize document - normalize(_scxml); + if (_nsInfo.getNSContext() != NULL) + _xpath.setNamespaceContext(*_nsInfo.getNSContext()); - // setup event queue for delayed send - _sendQueue = new DelayedEventQueue(); - _sendQueue->start(); - - // register for dom events to manage cached states - Arabica::DOM::Events::EventTarget<std::string> eventTarget(_scxml); - eventTarget.addEventListener("DOMNodeInserted", _domEventListener, true); - eventTarget.addEventListener("DOMNodeRemoved", _domEventListener, true); - eventTarget.addEventListener("DOMSubtreeModified", _domEventListener, true); + // normalize document + // TODO: Resolve XML includes + + // make sure every state has an id + Arabica::XPath::NodeSet<std::string> states; + states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "state", _scxml).asNodeSet()); + states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "final", _scxml).asNodeSet()); + states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "history", _scxml).asNodeSet()); + for (int i = 0; i < states.size(); i++) { + Arabica::DOM::Element<std::string> stateElem = Arabica::DOM::Element<std::string>(states[i]); + if (!stateElem.hasAttribute("id")) { + stateElem.setAttribute("id", UUID::getUUID()); + } + } + + // make sure every invoke has an idlocation or id + Arabica::XPath::NodeSet<std::string> invokes = _xpath.evaluate("//" + _nsInfo.xpathPrefix + "invoke", _scxml).asNodeSet(); + for (int i = 0; i < invokes.size(); i++) { + Arabica::DOM::Element<std::string> invokeElem = Arabica::DOM::Element<std::string>(invokes[i]); + if (!invokeElem.hasAttribute("id") && !invokeElem.hasAttribute("idlocation")) { + invokeElem.setAttribute("id", UUID::getUUID()); + } + } + + // add an id to the scxml element + if (!_scxml.hasAttribute("id")) { + _scxml.setAttribute("id", UUID::getUUID()); + } - if (_factory == NULL) - _factory = Factory::getInstance(); + // register for dom events to manage cached states + Arabica::DOM::Events::EventTarget<std::string> eventTarget(_scxml); + eventTarget.addEventListener("DOMNodeInserted", _domEventListener, true); + eventTarget.addEventListener("DOMNodeRemoved", _domEventListener, true); + eventTarget.addEventListener("DOMSubtreeModified", _domEventListener, true); - } else { - LOG(ERROR) << "Cannot find SCXML element" << std::endl; - _done = true; - return; - } +} - if (_sessionId.length() == 0) - _sessionId = UUID::getUUID(); +void InterpreterImpl::init() { + // make sure we have a factory if none was set before + if (_factory == NULL) + _factory = Factory::getInstance(); + // setup and normalize DOM + setupAndNormalizeDOM(); + // get our name or generate as UUID + if (_name.length() == 0) + _name = (HAS_ATTR(_scxml, "name") ? ATTR(_scxml, "name") : UUID::getUUID()); + + // setup event queue for delayed send + if (!_sendQueue) { + _sendQueue = new DelayedEventQueue(); + _sendQueue->start(); + } + + // start io processoes setupIOProcessors(); - std::string datamodelName; + // instantiate datamodel if (HAS_ATTR(_scxml, "datamodel")) { - datamodelName = ATTR(_scxml, "datamodel"); - } else if (HAS_ATTR(_scxml, "profile")) {// SCION SCXML uses profile to specify datamodel - datamodelName = ATTR(_scxml, "profile"); - } - - if(datamodelName.length() > 0) { - _dataModel = _factory->createDataModel(datamodelName, this); + _dataModel = _factory->createDataModel(ATTR(_scxml, "datamodel"), this); if (!_dataModel) { Event e; e.data.compound["cause"] = Data("Cannot instantiate datamodel", Data::VERBATIM); @@ -623,10 +787,10 @@ void InterpreterImpl::init() { } else { _dataModel = _factory->createDataModel("null", this); } - + _dataModel.assign("_x.args", _cmdLineOptions); - _running = true; +// _running = true; #if VERBOSE std::cout << "running " << this << std::endl; #endif @@ -706,35 +870,6 @@ void InterpreterImpl::initializeData(const Element<std::string>& data) { } } -void InterpreterImpl::normalize(Arabica::DOM::Element<std::string>& scxml) { - // TODO: Resolve XML includes - - // make sure every state has an id - Arabica::XPath::NodeSet<std::string> states; - states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "state", _scxml).asNodeSet()); - states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "final", _scxml).asNodeSet()); - states.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "history", _scxml).asNodeSet()); - for (int i = 0; i < states.size(); i++) { - Arabica::DOM::Element<std::string> stateElem = Arabica::DOM::Element<std::string>(states[i]); - if (!stateElem.hasAttribute("id")) { - stateElem.setAttribute("id", UUID::getUUID()); - } - } - - // make sure every invoke has an idlocation or id - Arabica::XPath::NodeSet<std::string> invokes = _xpath.evaluate("//" + _nsInfo.xpathPrefix + "invoke", _scxml).asNodeSet(); - for (int i = 0; i < invokes.size(); i++) { - Arabica::DOM::Element<std::string> invokeElem = Arabica::DOM::Element<std::string>(invokes[i]); - if (!invokeElem.hasAttribute("id") && !invokeElem.hasAttribute("idlocation")) { - invokeElem.setAttribute("id", UUID::getUUID()); - } - } - - if (!scxml.hasAttribute("id")) { - scxml.setAttribute("id", UUID::getUUID()); - } -} - void InterpreterImpl::receiveInternal(const Event& event) { #if VERBOSE std::cout << _name << " receiveInternal: " << event.name << std::endl; @@ -1249,24 +1384,12 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) { _invokers[invokeReq.invokeid] = invoker; try { - // --- MONITOR: beforeInvoking ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeInvoking(shared_from_this(), Element<std::string>(element), invokeReq.invokeid); - } - USCXML_MONITOR_CATCH_BLOCK(beforeInvoking) - } + USCXML_MONITOR_CALLBACK3(beforeInvoking, Arabica::DOM::Element<std::string>(element), invokeReq.invokeid); invoker.invoke(invokeReq); LOG(INFO) << "Added invoker " << invokeReq.type << " at " << invokeReq.invokeid; - // --- MONITOR: afterInvoking ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterInvoking(shared_from_this(), Element<std::string>(element), invokeReq.invokeid); - } - USCXML_MONITOR_CATCH_BLOCK(afterInvoking) - } + USCXML_MONITOR_CALLBACK3(afterInvoking, Arabica::DOM::Element<std::string>(element), invokeReq.invokeid) // this is out of draft but so useful to know when an invoker started // Event invSuccess; @@ -1316,23 +1439,11 @@ void InterpreterImpl::cancelInvoke(const Arabica::DOM::Node<std::string>& elemen } } - // --- MONITOR: beforeUninvoking ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeUninvoking(shared_from_this(), Element<std::string>(element), invokeId); - } - USCXML_MONITOR_CATCH_BLOCK(beforeUninvoking) - } + USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId) _invokers.erase(invokeId); - // --- MONITOR: afterUninvoking ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterUninvoking(shared_from_this(), Element<std::string>(element), invokeId); - } - USCXML_MONITOR_CATCH_BLOCK(beforeUninvoking) - } + USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId) } else { LOG(ERROR) << "Cannot cancel invoke for id " << invokeId << ": no such invokation"; @@ -1388,10 +1499,6 @@ bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::s bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Node<std::string>& conditional) { if (HAS_ATTR(conditional, "cond") && ATTR(conditional, "cond").length() > 0) { - if (!_dataModel) { - LOG(ERROR) << "Cannot check a condition without a datamodel"; - return false; - } try { return _dataModel.evalAsBool(ATTR_NODE(conditional, "cond"), ATTR(conditional, "cond")); } catch (Event e) { @@ -1445,13 +1552,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont return; } - // --- MONITOR: beforeExecutingContent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeExecutingContent(shared_from_this(), Element<std::string>(content)); - } - USCXML_MONITOR_CATCH_BLOCK(beforeExecutingContent) - } + USCXML_MONITOR_CALLBACK2(beforeExecutingContent, Element<std::string>(content)) if (false) { } else if (iequals(TAGNAME(content), _nsInfo.xmlNSPrefix + "raise")) { @@ -1712,14 +1813,32 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont execContent.exitElement(content); } - // --- MONITOR: afterExecutingContent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterExecutingContent(shared_from_this(), Element<std::string>(content)); + USCXML_MONITOR_CALLBACK2(afterExecutingContent, Element<std::string>(content)) + +} + +void InterpreterImpl::finalizeAndAutoForwardCurrentEvent() { + 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; + } } - USCXML_MONITOR_CATCH_BLOCK(afterExecutingContent) } - } void InterpreterImpl::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) { @@ -2497,10 +2616,38 @@ void InterpreterImpl::DOMEventListener::handleEvent(Arabica::DOM::Events::Event< } } -void InterpreterImpl::dump() { - if (!_document) - return; - std::cout << _document; +std::ostream& operator<< (std::ostream& os, const InterpreterState& interpreterState) { + os << "[" << InterpreterState::stateToString(interpreterState.state) << "]:" << std::endl; + os << interpreterState.msg; + return os; +} + +std::string InterpreterState::stateToString(int32_t state) { + std::stringstream ss; + + switch(state & USCXML_INTERPRETER_MASK) { + case USCXML_INSTANTIATED: ss << "INSTANTIATED"; break; + case USCXML_FAULTED: ss << "FAULTED"; break; + case USCXML_MICROSTEPPED: ss << "MICROSTEPPED"; break; + case USCXML_MACROSTEPPED: ss << "MACROSTEPPED"; break; + case USCXML_IDLE: ss << "IDLE"; break; + case USCXML_FINISHED: ss << "FINISHED"; break; + case USCXML_DESTROYED: ss << "DESTROYED"; break; + default: ss << "INVALID"; break; + } + + if (state & USCXML_THREAD_STARTED) { + ss << ", " << "STARTED"; + } else { + ss << ", " << "STOPPED"; + } + if (state & USCXML_THREAD_RUNNING) { + ss << ", " << "RUNNING"; + } else { + ss << ", " << "JOINED"; + } + + return ss.str(); } diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 3a02cb7..81ccdb9 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -48,16 +48,41 @@ #include "uscxml/server/InterpreterServlet.h" -#define USCXML_MONITOR_CATCH_BLOCK(callback)\ -catch (Event e) {\ - LOG(ERROR) << "Syntax error when calling " #callback " on monitors: " << std::endl << e << std::endl;\ -} catch (boost::bad_weak_ptr e) {\ - LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl;\ -} catch (...) {\ - LOG(ERROR) << "An exception occured when calling " #callback " on monitors";\ -}\ -if (_destroyed) {\ - throw boost::bad_weak_ptr();\ +#define USCXML_MONITOR_CATCH(callback) \ +catch (Event e) { \ + LOG(ERROR) << "Syntax error when calling " #callback " on monitors: " << std::endl << e << std::endl; \ +} catch (boost::bad_weak_ptr e) { \ + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; \ +} catch (...) { \ + LOG(ERROR) << "An exception occured when calling " #callback " on monitors"; \ +} \ +if (_state == InterpreterState::USCXML_DESTROYED) { \ + throw boost::bad_weak_ptr(); \ +} \ + + +#define USCXML_MONITOR_CALLBACK(callback)\ +for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { \ + try { \ + (*monIter)->callback(shared_from_this()); \ + } \ + USCXML_MONITOR_CATCH(callback) \ +} + +#define USCXML_MONITOR_CALLBACK2(callback, arg1)\ +for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { \ + try { \ + (*monIter)->callback(shared_from_this(), arg1); \ + } \ + USCXML_MONITOR_CATCH(callback) \ +} + +#define USCXML_MONITOR_CALLBACK3(callback, arg1, arg2)\ +for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { \ + try { \ + (*monIter)->callback(shared_from_this(), arg1, arg2); \ + } \ + USCXML_MONITOR_CATCH(callback) \ } namespace uscxml { @@ -172,6 +197,12 @@ public: attribute.setPrefix(nsToPrefix[nsURL]); } + std::string getXMLPrefixForNS(const std::string& ns) const { + if (nsToPrefix.find(ns) != nsToPrefix.end() && nsToPrefix.at(ns).size()) + return nsToPrefix.at(ns) + ":"; + return ""; + } + const Arabica::XPath::StandardNamespaceContext<std::string>* getNSContext() { return nsContext; } @@ -188,16 +219,56 @@ private: void init(const std::map<std::string, std::string>& nsInfo); }; -// values larger than 0 indicate that you ought to step again -enum InterpreterState { - FINISHED = 0, // machine reached a final configuration - INIT_FAILED = -1, // could not initialize interpreter - INTERRUPTED = -2, // machine was interrupted - NOTHING_TODO = 4, // when non-blocking returns nothing to do - PROCESSED = 8, // an event was processed - INITIALIZED = 16 // initial stable configuration was assumed -}; +struct USCXML_API InterpreterState { + // see: http://stackoverflow.com/questions/18591924/how-to-use-bitmask + enum State { + USCXML_DESTROYED = 0x0001, // + USCXML_INSTANTIATED = 0x0002, // nothing really, just instantiated + USCXML_MICROSTEPPED = 0x0004, // + USCXML_MACROSTEPPED = 0x0008, // + USCXML_IDLE = 0x0010, // + USCXML_FAULTED = 0x0020, // something went very wrong + USCXML_FINISHED = 0x0040, // machine reached a final configuration + }; + + enum ThreadState { + USCXML_THREAD_RUNNING = 0x0100, // + USCXML_THREAD_STARTED = 0x0200, // + }; + + enum BitMask { + USCXML_THREAD_MASK = 0xff00, + USCXML_INTERPRETER_MASK = 0x00ff, + }; + + bool operator==(const InterpreterState& other) const { + return state == other.state && msg == other.msg; + } + bool operator!=(const InterpreterState& other) const { + return !(*this == other); + } + + operator int() { + return (int)(state | thread); + } + + Event getMessage() { + return msg; + } + + static std::string stateToString(int32_t state); + + friend USCXML_API std::ostream& operator<< (std::ostream& os, const InterpreterState& interpreterState); + friend USCXML_API class InterpreterImpl; +protected: + int32_t thread; + State state; + Event msg; +}; + +USCXML_API std::ostream& operator<< (std::ostream& os, const InterpreterState& interpreterState); + class USCXML_API InterpreterImpl : public boost::enable_shared_from_this<InterpreterImpl> { public: @@ -213,20 +284,18 @@ public: void copyTo(InterpreterImpl* other); void copyTo(boost::shared_ptr<InterpreterImpl> other); - void start(); - void stop(); - static void run(void*); - void join() { - if (_thread != NULL) _thread->join(); - }; - bool isRunning() { - return _running || !_done; - } + // TODO: Look into that pure virtual issue and make these abstract! + virtual InterpreterState interpret() { return _state; } ///< Start interpreter blockingly + virtual InterpreterState step(int waitForMS = 0) { return _state; }; ///< Perform a single step - /// This one ought to be pure, but SWIG will generate gibberish if it is - virtual void interpret() = 0; - virtual InterpreterState step(bool blocking = false) = 0; + void start(); ///< Start interpretation in a thread + void stop(); ///< Stop interpreter thread + void reset(); ///< Reset state machine + void join(); + bool isRunning(); + InterpreterState getInterpreterState(); + void addMonitor(InterpreterMonitor* monitor) { _monitors.insert(monitor); } @@ -261,9 +330,11 @@ public: DataModel getDataModel() { return _dataModel; } + void setParentQueue(uscxml::concurrency::BlockingQueue<SendRequest>* parentQueue) { _parentQueue = parentQueue; } + void setFactory(Factory* factory) { _factory = factory; } @@ -275,12 +346,6 @@ public: return _xpath.evaluate(xpathExpr, _scxml).asNodeSet(); } - std::string getXMLPrefixForNS(const std::string& ns) const { - if (_nsInfo.nsToPrefix.find(ns) != _nsInfo.nsToPrefix.end() && _nsInfo.nsToPrefix.at(ns).size()) - return _nsInfo.nsToPrefix.at(ns) + ":"; - return ""; - } - void setNameSpaceInfo(const NameSpaceInfo& nsInfo) { _nsInfo = nsInfo; _xpath.setNamespaceContext(*_nsInfo.getNSContext()); @@ -314,17 +379,13 @@ public: return basicConfig; } - void setConfiguration(const std::vector<std::string>& states) { + void setInitalConfiguration(const std::vector<std::string>& states) { _userDefinedStartConfiguration = states; } void setInvokeRequest(const InvokeRequest& req) { _invokeReq = req; } - Arabica::DOM::Node<std::string> getState(const std::string& stateId); - Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds); - Arabica::XPath::NodeSet<std::string> getAllStates(); - virtual Arabica::DOM::Document<std::string> getDocument() const { return _document; } @@ -357,7 +418,6 @@ public: static bool isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set); - void dump(); bool hasLegalConfiguration(); bool isLegalConfiguration(const Arabica::XPath::NodeSet<std::string>&); bool isLegalConfiguration(const std::vector<std::string>&); @@ -372,13 +432,13 @@ public: static bool isParallel(const Arabica::DOM::Node<std::string>& state); static bool isCompound(const Arabica::DOM::Node<std::string>& state); static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2); - - static std::list<std::string> tokenizeIdRefs(const std::string& idRefs); - static std::string spaceNormalize(const std::string& text); - static bool nameMatch(const std::string& transitionEvent, const std::string& event); - bool isInEmbeddedDocument(const Arabica::DOM::Node<std::string>& node); bool isInitial(const Arabica::DOM::Node<std::string>& state); + + Arabica::DOM::Node<std::string> getState(const std::string& stateId); + Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds); + Arabica::XPath::NodeSet<std::string> getAllStates(); + Arabica::XPath::NodeSet<std::string> getInitialStates(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()); static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state); static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::XPath::NodeSet<std::string>& state); @@ -392,11 +452,17 @@ public: static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagName, const Arabica::XPath::NodeSet<std::string>& nodeSet, bool recurse = false); static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::DOM::Node<std::string>& node, bool recurse = false); static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::XPath::NodeSet<std::string>& nodeSet, bool recurse = false); + + static std::list<std::string> tokenizeIdRefs(const std::string& idRefs); + static std::string spaceNormalize(const std::string& text); + static bool nameMatch(const std::string& transitionEvent, const std::string& event); Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states); virtual Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2); protected: + static void run(void*); // static method for thread to run + class DOMEventListener : public Arabica::DOM::Events::EventListener<std::string> { public: void handleEvent(Arabica::DOM::Events::Event<std::string>& event); @@ -405,17 +471,23 @@ protected: InterpreterImpl(); void init(); + void setupAndNormalizeDOM(); + virtual void setupIOProcessors(); - void normalize(Arabica::DOM::Element<std::string>& scxml); void initializeData(const Arabica::DOM::Element<std::string>& data); - virtual void setupIOProcessors(); + void finalizeAndAutoForwardCurrentEvent(); + void setInterpreterState(InterpreterState::State newState, const std::string& error); + void setInterpreterState(InterpreterState::State newState, const Event& error); + void setInterpreterState(InterpreterState::State newState); + bool _stable; tthread::thread* _thread; tthread::recursive_mutex _mutex; tthread::condition_variable _condVar; tthread::recursive_mutex _pluginMutex; + InterpreterState _state; URL _baseURI; URL _sourceURI; Arabica::DOM::Document<std::string> _document; @@ -423,10 +495,10 @@ protected: Arabica::XPath::XPath<std::string> _xpath; NameSpaceInfo _nsInfo; - bool _running; - bool _done; - bool _destroyed; // see comment in destructor + bool _topLevelFinalReached; bool _isInitialized; + bool _domIsSetup; + InterpreterImpl::Binding _binding; Arabica::XPath::NodeSet<std::string> _configuration; Arabica::XPath::NodeSet<std::string> _alreadyEntered; @@ -450,6 +522,13 @@ protected: InterpreterWebSocketServlet* _wsServlet; std::set<InterpreterMonitor*> _monitors; + long _lastRunOnMainThread; + std::string _name; + std::string _sessionId; + unsigned int _capabilities; + + Data _cmdLineOptions; + virtual void executeContent(const Arabica::DOM::Node<std::string>& content, bool rethrow = false); virtual void executeContent(const Arabica::DOM::NodeList<std::string>& content, bool rethrow = false); virtual void executeContent(const Arabica::XPath::NodeSet<std::string>& content, bool rethrow = false); @@ -475,13 +554,6 @@ protected: bool isInFinalState(const Arabica::DOM::Node<std::string>& state); bool parentIsScxmlState(const Arabica::DOM::Node<std::string>& state); - long _lastRunOnMainThread; - std::string _name; - std::string _sessionId; - unsigned int _capabilities; - - Data _cmdLineOptions; - IOProcessor getIOProcessor(const std::string& type); std::map<std::string, IOProcessor> _ioProcessors; @@ -489,7 +561,7 @@ protected: std::map<std::string, Invoker> _invokers; std::map<Arabica::DOM::Node<std::string>, ExecutableContent> _executableContent; - /// TODO: We need to remember to adapt them when the DOM is operated upon + /// TODO: We need to adapt them when the DOM is operated upon std::map<std::string, Arabica::DOM::Node<std::string> > _cachedStates; std::map<std::string, URL> _cachedURLs; @@ -504,7 +576,6 @@ public: const NameSpaceInfo& nameSpaceInfo); static Interpreter fromXML(const std::string& xml); static Interpreter fromURI(const std::string& uri); - static Interpreter fromInputSource(Arabica::SAX::InputSource<std::string>& source); static Interpreter fromClone(const Interpreter& other); Interpreter() : _impl() {} // the empty, invalid interpreter @@ -513,7 +584,9 @@ public: virtual ~Interpreter() {}; operator bool() const { - return _impl; + return (_impl && + _impl->_state != InterpreterState::USCXML_FAULTED && + _impl->_state != InterpreterState::USCXML_DESTROYED); } bool operator< (const Interpreter& other) const { return _impl < other._impl; @@ -529,15 +602,19 @@ public: return *this; } + void reset() { + return _impl->reset(); + } + void start() { return _impl->start(); } void stop() { return _impl->stop(); } - void join() { - return _impl->join(); - }; +// void join() { +// return _impl->join(); +// }; bool isRunning() { return _impl->isRunning(); } @@ -546,10 +623,20 @@ public: _impl->interpret(); }; - InterpreterState step(bool blocking = false) { - return _impl->step(blocking); + InterpreterState step(int waitForMS = 0) { + return _impl->step(waitForMS); + }; + + InterpreterState step(bool blocking) { + if (blocking) + return _impl->step(-1); + return _impl->step(0); }; + InterpreterState getState() { + return _impl->getInterpreterState(); + } + void addMonitor(InterpreterMonitor* monitor) { return _impl->addMonitor(monitor); } @@ -568,10 +655,6 @@ public: return _impl->getBaseURI(); } - std::string getXMLPrefixForNS(const std::string& ns) const { - return _impl->getXMLPrefixForNS(ns); - } - void setNameSpaceInfo(const NameSpaceInfo& nsInfo) { _impl->setNameSpaceInfo(nsInfo); } @@ -629,22 +712,19 @@ public: return _impl->getBasicConfiguration(); } - void setConfiguration(const std::vector<std::string>& states) { - return _impl->setConfiguration(states); - } - void setInvokeRequest(const InvokeRequest& req) { - return _impl->setInvokeRequest(req); + void setInitalConfiguration(const std::vector<std::string>& states) { + return _impl->setInitalConfiguration(states); } - Arabica::DOM::Node<std::string> getState(const std::string& stateId) { - return _impl->getState(stateId); - } - Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds) { - return _impl->getStates(stateIds); - } - Arabica::XPath::NodeSet<std::string> getAllStates() { - return _impl->getAllStates(); - } +// Arabica::DOM::Node<std::string> getState(const std::string& stateId) { +// return _impl->getState(stateId); +// } +// Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds) { +// return _impl->getStates(stateIds); +// } +// Arabica::XPath::NodeSet<std::string> getAllStates() { +// return _impl->getAllStates(); +// } Arabica::DOM::Document<std::string> getDocument() const { return _impl->getDocument(); @@ -680,13 +760,6 @@ public: return _impl->runOnMainThread(fps, blocking); } - static bool isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set) { - return InterpreterImpl::isMember(node, set); - } - - void dump() { - return _impl->dump(); - } bool hasLegalConfiguration() { return _impl->hasLegalConfiguration(); } @@ -699,98 +772,6 @@ public: return _impl->isLegalConfiguration(config); } -#if 0 - static bool isState(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isState(state); - } - static bool isPseudoState(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isPseudoState(state); - } - static bool isTransitionTarget(const Arabica::DOM::Node<std::string>& elem) { - return InterpreterImpl::isTransitionTarget(elem); - } - static bool isTargetless(const Arabica::DOM::Node<std::string>& transition) { - return InterpreterImpl::isTargetless(transition); - } - static bool isAtomic(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isAtomic(state); - } - static bool isFinal(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isFinal(state); - } - static bool isHistory(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isHistory(state); - } - static bool isParallel(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isParallel(state); - } - static bool isCompound(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::isCompound(state); - } - static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { - return InterpreterImpl::isDescendant(s1, s2); - } - - static std::list<std::string> tokenizeIdRefs(const std::string& idRefs) { - return InterpreterImpl::tokenizeIdRefs(idRefs); - } - static bool nameMatch(const std::string& transitionEvent, const std::string& event) { - return InterpreterImpl::nameMatch(transitionEvent, event); - } - - static std::string spaceNormalize(const std::string& text) { - return InterpreterImpl::spaceNormalize(text); - } - - bool isInitial(const Arabica::DOM::Node<std::string>& state) { - return _impl->isInitial(state); - } - Arabica::XPath::NodeSet<std::string> getInitialStates(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()) { - return _impl->getInitialStates(state); - } - static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state) { - return InterpreterImpl::getChildStates(state); - } - static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::XPath::NodeSet<std::string>& state) { - return InterpreterImpl::getChildStates(state); - } - static Arabica::DOM::Node<std::string> getParentState(const Arabica::DOM::Node<std::string>& element) { - return InterpreterImpl::getParentState(element); - } - static Arabica::DOM::Node<std::string> getAncestorElement(const Arabica::DOM::Node<std::string>& node, const std::string tagName) { - return InterpreterImpl::getAncestorElement(node, tagName); - } - Arabica::XPath::NodeSet<std::string> getTargetStates(const Arabica::DOM::Node<std::string>& transition) { - return _impl->getTargetStates(transition); - } - Arabica::XPath::NodeSet<std::string> getTargetStates(const Arabica::XPath::NodeSet<std::string>& transitions) { - return _impl->getTargetStates(transitions); - } - Arabica::DOM::Node<std::string> getSourceState(const Arabica::DOM::Node<std::string>& transition) { - return _impl->getSourceState(transition); - } - - static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagname, const Arabica::DOM::Node<std::string>& node, bool recurse = false) { - return InterpreterImpl::filterChildElements(tagname, node, recurse); - } - static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagName, const Arabica::XPath::NodeSet<std::string>& nodeSet, bool recurse = false) { - return InterpreterImpl::filterChildElements(tagName, nodeSet, recurse); - } - static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::DOM::Node<std::string>& node, bool recurse = false) { - return InterpreterImpl::filterChildType(type, node, recurse); - } - static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::XPath::NodeSet<std::string>& nodeSet, bool recurse = false) { - return InterpreterImpl::filterChildType(type, nodeSet, recurse); - } - - Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states) { - return _impl->findLCCA(states); - } - Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { - return _impl->getProperAncestors(s1, s2); - } -#endif - boost::shared_ptr<InterpreterImpl> getImpl() const { return _impl; } @@ -798,6 +779,13 @@ public: static std::map<std::string, boost::weak_ptr<InterpreterImpl> > getInstances(); protected: + + void setInvokeRequest(const InvokeRequest& req) { + return _impl->setInvokeRequest(req); + } + + static Interpreter fromInputSource(Arabica::SAX::InputSource<std::string>& source); + boost::shared_ptr<InterpreterImpl> _impl; static std::map<std::string, boost::weak_ptr<InterpreterImpl> > _instances; static tthread::recursive_mutex _instanceMutex; diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index 0a0eed0..1ac3573 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -673,6 +673,29 @@ 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.params.size() > 0) { + std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin(); + os << indent << " params:" << std::endl; + _dataIndentation++; + while(paramIter != event.params.end()) { + os << indent << " " << paramIter->first << ": "; + os << indent << paramIter->second << std::endl; + paramIter++; + } + _dataIndentation--; + } + if (event.namelist.size() > 0) { + std::map<std::string, Data>::const_iterator namelistIter = event.namelist.begin(); + os << indent << " namelist:" << std::endl; + _dataIndentation++; + while(namelistIter != event.namelist.end()) { + os << indent << " " << namelistIter->first << ": "; + os << indent << namelistIter->second << std::endl; + namelistIter++; + } + _dataIndentation--; + + } _dataIndentation++; os << indent << " data: " << event.data << std::endl; _dataIndentation--; diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 27b2ac5..44d9207 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -279,6 +279,16 @@ public: return this < &other; } + bool operator==(const Event& other) const { + return (this->name == other.name && + this->sendid == other.sendid && + this->invokeid == other.invokeid && + this->data == other.data); + } + bool operator!=(const Event& other) const { + return !(*this == other); + } + std::string getName() { return name; } diff --git a/src/uscxml/concurrency/tinythread.h b/src/uscxml/concurrency/tinythread.h index 0490e4d..a47b46a 100644 --- a/src/uscxml/concurrency/tinythread.h +++ b/src/uscxml/concurrency/tinythread.h @@ -428,6 +428,31 @@ public: #endif } + template <class _mutexT> + inline void wait_for(_mutexT &aMutex, unsigned int ms) { +#if defined(_TTHREAD_WIN32_) + // Increment number of waiters + EnterCriticalSection(&mWaitersCountLock); + ++ mWaitersCount; + LeaveCriticalSection(&mWaitersCountLock); + + // Release the mutex while waiting for the condition (will decrease + // the number of waiters when done)... + aMutex.unlock(); + _wait(ms); + aMutex.lock(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + + struct timespec ts; + ts.tv_sec = tv.tv_sec + (ms / 1000); + ts.tv_nsec = (tv.tv_usec * 1000); // convert tv microseconds to nanoseconds + ts.tv_nsec += (ms % 1000) * 1000000; // add millisecond part of wait time + pthread_cond_timedwait(&mHandle, &aMutex.mHandle, &ts); +#endif + } + /// Notify one thread that is waiting for the condition. /// If at least one thread is blocked waiting for this condition variable, /// one will be woken up. diff --git a/src/uscxml/debug/Breakpoint.cpp b/src/uscxml/debug/Breakpoint.cpp index 54f5d75..e66e0fb 100644 --- a/src/uscxml/debug/Breakpoint.cpp +++ b/src/uscxml/debug/Breakpoint.cpp @@ -238,7 +238,7 @@ bool Breakpoint::matches(Interpreter interpreter, const Breakpoint& other) const } catch (...) { return false; } - return Interpreter::isMember(other.element, nodes); + return InterpreterImpl::isMember(other.element, nodes); } if(transSourceId.length() > 0 && transSourceId != other.transSourceId) { diff --git a/src/uscxml/debug/SCXMLDotWriter.cpp b/src/uscxml/debug/SCXMLDotWriter.cpp index 93f09ab..2bccb14 100644 --- a/src/uscxml/debug/SCXMLDotWriter.cpp +++ b/src/uscxml/debug/SCXMLDotWriter.cpp @@ -130,13 +130,13 @@ void SCXMLDotWriter::writeStateElement(std::ostream& os, const Arabica::DOM::Ele os << "shape=doublecircle,"; // is the current state in the basic configuration? - if (_interpreter.isMember(elem, _interpreter.getBasicConfiguration())) + if (InterpreterImpl::isMember(elem, _interpreter.getBasicConfiguration())) os << "color=red, penwidth=3,"; // is the current state a target state? #if 0 for (int i = 0; i < _transitions.size(); i++) { - if (_interpreter.isMember(elem, _interpreter.getTargetStates(_transitions[i]))) { + if (InterpreterImpl::isMember(elem, _interpreter.getTargetStates(_transitions[i]))) { os << "color=red, penwidth=3,"; break; } diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 12d6123..5e64e66 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -32,22 +32,18 @@ using namespace Arabica::DOM; // see: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation -void InterpreterDraft6::interpret() { +InterpreterState InterpreterDraft6::interpret() { InterpreterState state; while(true) { - state = step(true); + state = step(-1); - switch (state) { - case uscxml::INIT_FAILED: - case uscxml::FINISHED: - case uscxml::INTERRUPTED: + switch (state & InterpreterState::USCXML_INTERPRETER_MASK) { + case uscxml::InterpreterState::USCXML_FAULTED: + case uscxml::InterpreterState::USCXML_FINISHED: + case uscxml::InterpreterState::USCXML_DESTROYED: // return as we finished - return; - case uscxml::NOTHING_TODO: - // die as this can never happen with a blocking call - assert(false); - case uscxml::INITIALIZED: - case uscxml::PROCESSED: + return state; + default: // process invokers on main thread if(_thread == NULL) { @@ -58,6 +54,7 @@ void InterpreterDraft6::interpret() { break; } } + return state; } // setup / fetch the documents initial transitions @@ -117,74 +114,130 @@ NodeSet<std::string> InterpreterDraft6::getDocumentInitialTransitions() { } return initialTransitions; } - -// a macrostep -InterpreterState InterpreterDraft6::step(bool blocking) { + +InterpreterState InterpreterDraft6::step(int waitForMS = 0) { try { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - monIter_t monIter; + if (_state & InterpreterState::USCXML_FINISHED || + _state & InterpreterState::USCXML_FAULTED || + _state & InterpreterState::USCXML_DESTROYED) { + return _state; + } + NodeSet<std::string> enabledTransitions; // setup document and interpreter - if (!_isInitialized) - init(); - - // if we failed return false - if (!_isInitialized) - return INIT_FAILED; - - // run initial transitions - if (!_stable) { - stabilize(); - // we might only need a single step - if (!_running) - goto EXIT_INTERPRETER; - return INITIALIZED; + if (!_isInitialized) { + init(); // will throw } - if (!_running) - return FINISHED; + if (_configuration.size() == 0) { + // goto initial configuration + NodeSet<std::string> initialTransitions = getDocumentInitialTransitions(); + assert(initialTransitions.size() > 0); + enterStates(initialTransitions); + } + + _stable = false; - // read an external event and react - if (blocking) { + // are there spontaneous transitions? + enabledTransitions = selectEventlessTransitions(); + if (!enabledTransitions.empty()) { + // test 403b + enabledTransitions.to_document_order(); + microstep(enabledTransitions); - // wait until an event becomes available - while(_externalQueue.isEmpty()) { - _condVar.wait(_mutex); - } - } else { - // return immediately if external queue is empty - if (_externalQueue.isEmpty()) - return NOTHING_TODO; + setInterpreterState(InterpreterState::USCXML_MICROSTEPPED); + return _state; } - _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; + // test415 + if (_topLevelFinalReached) + goto EXIT_INTERPRETER; + + // process internal event + if (!_internalQueue.empty()) { + _currEvent = _internalQueue.front(); + _internalQueue.pop_front(); + + USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent) + + if (_dataModel) + _dataModel.setEvent(_currEvent); + enabledTransitions = selectTransitions(_currEvent.name); + + if (!enabledTransitions.empty()) { + // test 403b + enabledTransitions.to_document_order(); + microstep(enabledTransitions); + } + + // test 319 - even if we do not enable transitions, consider it a microstep + setInterpreterState(InterpreterState::USCXML_MICROSTEPPED); + return _state; + } else { - std::cout << "Aborting " << this << std::endl; + _stable = true; } - #endif - _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external + // even if we did nothing - count as microstep + setInterpreterState(InterpreterState::USCXML_MICROSTEPPED); - // when we were blocking on destructor invocation - if (!_running) { + if (_topLevelFinalReached) goto EXIT_INTERPRETER; - return INTERRUPTED; + + setInterpreterState(InterpreterState::USCXML_MACROSTEPPED); + USCXML_MONITOR_CALLBACK(onStableConfiguration) + + // when we reach a stable configuration, invoke + 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]); + } + } } - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); + _statesToInvoke = NodeSet<std::string>(); + + if (_externalQueue.isEmpty()) { + setInterpreterState(InterpreterState::USCXML_IDLE); + + if (waitForMS < 0) { + // wait blockingly for an event forever + while(_externalQueue.isEmpty()) { + _condVar.wait(_mutex); + } + } + + if (waitForMS > 0) { + // wait given number of milliseconds max + uint64_t now = tthread::chrono::system_clock::now(); + uint64_t then = now + waitForMS; + while(_externalQueue.isEmpty() && now < then) { + _condVar.wait_for(_mutex, then - now); + now = tthread::chrono::system_clock::now(); + } + } + + if (_externalQueue.isEmpty()) { + return _state; } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) + + setInterpreterState(InterpreterState::USCXML_MACROSTEPPED); } - if (iequals(_currEvent.name, "cancel.invoke." + _sessionId)) - return INTERRUPTED; + _currEvent = _externalQueue.pop(); + _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external + + if (_topLevelFinalReached) + goto EXIT_INTERPRETER; + + USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent) + + if (iequals(_currEvent.name, "cancel.invoke." + _sessionId)) { + goto EXIT_INTERPRETER; + } try { _dataModel.setEvent(_currEvent); @@ -192,28 +245,7 @@ InterpreterState InterpreterDraft6::step(bool blocking) { 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; - } - } - } - + finalizeAndAutoForwardCurrentEvent(); // run internal processing until we reach a stable configuration again enabledTransitions = selectTransitions(_currEvent.name); @@ -223,50 +255,42 @@ InterpreterState InterpreterDraft6::step(bool blocking) { microstep(enabledTransitions); } - stabilize(); - return PROCESSED; + if (_topLevelFinalReached) + goto EXIT_INTERPRETER; + return _state; + EXIT_INTERPRETER: - if (!_running) { - // --- MONITOR: beforeCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(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++; - } - } - - // --- MONITOR: afterCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(afterCompletion) + 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++; } - return FINISHED; } - assert(hasLegalConfiguration()); + USCXML_MONITOR_CALLBACK(afterCompletion) + +// assert(hasLegalConfiguration()); _mutex.unlock(); // remove datamodel if(_dataModel) _dataModel = DataModel(); - return PROCESSED; + setInterpreterState(InterpreterState::USCXML_FINISHED); + return _state; + } catch (Event e) { + setInterpreterState(InterpreterState::USCXML_FAULTED, e); + return _state; } catch (boost::bad_weak_ptr e) { LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; - return INTERRUPTED; + setInterpreterState(InterpreterState::USCXML_DESTROYED); + return _state; } // set datamodel to null from this thread @@ -278,7 +302,6 @@ InterpreterState InterpreterDraft6::step(bool blocking) { // process transitions until we are in a stable configuration again void InterpreterDraft6::stabilize() { - monIter_t monIter; NodeSet<std::string> enabledTransitions; _stable = false; @@ -303,13 +326,7 @@ void InterpreterDraft6::stabilize() { std::cout << "Received internal event " << _currEvent.name << std::endl; #endif - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); - } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) - } + USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent) if (_dataModel) _dataModel.setEvent(_currEvent); @@ -323,16 +340,8 @@ void InterpreterDraft6::stabilize() { microstep(enabledTransitions); } } while(!_internalQueue.empty() || !_stable); - - monIter = _monitors.begin(); - - // --- MONITOR: onStableConfiguration ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->onStableConfiguration(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration) - } + + USCXML_MONITOR_CALLBACK(onStableConfiguration) // when we reach a stable configuration, invoke for (unsigned int i = 0; i < _statesToInvoke.size(); i++) { @@ -349,7 +358,6 @@ void InterpreterDraft6::stabilize() { #if 0 void InterpreterDraft6::mainEventLoop() { - monIter_t monIter; while(_running) { NodeSet<std::string> enabledTransitions; @@ -377,13 +385,7 @@ void InterpreterDraft6::mainEventLoop() { std::cout << "Received internal event " << _currEvent.name << std::endl; #endif - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); - } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) - } + USCXML_MONITOR_CALLBACK(beforeProcessingEvent) if (_dataModel) _dataModel.setEvent(_currEvent); @@ -413,15 +415,7 @@ void InterpreterDraft6::mainEventLoop() { // assume that we have a legal configuration as soon as the internal queue is empty assert(hasLegalConfiguration()); - monIter = _monitors.begin(); - - // --- MONITOR: onStableConfiguration ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->onStableConfiguration(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration) - } + USCXML_MONITOR_CALLBACK(onStableConfiguration) _mutex.unlock(); @@ -447,13 +441,7 @@ void InterpreterDraft6::mainEventLoop() { if (!_running) goto EXIT_INTERPRETER; - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); - } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) - } + USCXML_MONITOR_CALLBACK(beforeProcessingEvent) if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId)) break; @@ -495,13 +483,7 @@ void InterpreterDraft6::mainEventLoop() { } EXIT_INTERPRETER: - // --- MONITOR: beforeCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(beforeCompletion) - } + USCXML_MONITOR_CALLBACK(beforeCompletion) exitInterpreter(); if (_sendQueue) { @@ -512,13 +494,7 @@ EXIT_INTERPRETER: } } - // --- MONITOR: afterCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(afterCompletion) - } + USCXML_MONITOR_CALLBACK(afterCompletion) } #endif @@ -760,48 +736,23 @@ void InterpreterDraft6::microstep(const Arabica::XPath::NodeSet<std::string>& en std::cout << std::endl; #endif - // --- MONITOR: beforeMicroStep ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeMicroStep(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(beforeMicroStep) - } + USCXML_MONITOR_CALLBACK(beforeMicroStep) exitStates(enabledTransitions); - monIter_t monIter; for (int i = 0; i < enabledTransitions.size(); i++) { Element<std::string> transition(enabledTransitions[i]); - // --- MONITOR: beforeTakingTransitions ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeTakingTransitions) - } + USCXML_MONITOR_CALLBACK3(beforeTakingTransition, transition, (i + 1 < enabledTransitions.size())) executeContent(transition); - // --- MONITOR: afterTakingTransitions ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterTakingTransitions) - } + USCXML_MONITOR_CALLBACK3(afterTakingTransition, transition, (i + 1 < enabledTransitions.size())) } enterStates(enabledTransitions); - // --- MONITOR: afterMicroStep ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterMicroStep(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(afterMicroStep) - } + USCXML_MONITOR_CALLBACK(afterMicroStep) } @@ -833,7 +784,6 @@ void InterpreterDraft6::exitInterpreter() { void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { NodeSet<std::string> statesToExit; - monIter_t monIter; #if VERBOSE std::cout << _name << ": Enabled exit transitions: " << std::endl; @@ -864,7 +814,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e NodeSet<std::string> tmpStates; tmpStates.push_back(source); tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end()); -#if VERBOSE +#if 1 std::cout << _name << ": tmpStates: "; for (int i = 0; i < tmpStates.size(); i++) { std::cout << ATTR(tmpStates[i], "id") << ", "; @@ -873,7 +823,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e #endif ancestor = findLCCA(tmpStates); } -#if VERBOSE +#if 1 std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl;; #endif for (int j = 0; j < _configuration.size(); j++) { @@ -895,7 +845,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e statesToExit.forward(false); statesToExit.sort(); -#if VERBOSE +#if 0 std::cout << _name << ": States to exit: "; for (int i = 0; i < statesToExit.size(); i++) { std::cout << LOCALNAME(statesToExit[i]) << ":" << ATTR(statesToExit[i], "id") << ", "; @@ -931,13 +881,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e } for (int i = 0; i < statesToExit.size(); i++) { - // --- MONITOR: beforeExitingState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeExitingState) - } + USCXML_MONITOR_CALLBACK3(beforeExitingState, Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())) NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onExit", statesToExit[i]); for (int j = 0; j < onExits.size(); j++) { @@ -945,13 +889,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e executeContent(onExitElem); } - // --- MONITOR: afterExitingState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterExitingState) - } + USCXML_MONITOR_CALLBACK3(afterExitingState, Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())) NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]); for (int j = 0; j < invokes.size(); j++) { @@ -978,7 +916,8 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { NodeSet<std::string> statesToEnter; NodeSet<std::string> statesForDefaultEntry; - monIter_t monIter; + // initialize the temporary table for default content in history states + NodeSet<std::string> defaultHistoryContent; #if VERBOSE std::cout << _name << ": Enabled enter transitions: " << std::endl; @@ -1033,7 +972,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& #endif for (int j = 0; j < tStates.size(); j++) { - addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry); + addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry, defaultHistoryContent); } #if VERBOSE @@ -1068,7 +1007,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& } } if (!someIsDescendant) { - addStatesToEnter(childs[l], statesToEnter, statesForDefaultEntry); + addStatesToEnter(childs[l], statesToEnter, statesForDefaultEntry, defaultHistoryContent); } } } @@ -1099,13 +1038,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& } } - // --- MONITOR: beforeEnteringState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeEnteringState) - } + USCXML_MONITOR_CALLBACK3(beforeEnteringState, stateElem, (i + 1 < statesToEnter.size())) // extension for flattened SCXML documents, we will need an explicit uninvoke element NodeSet<std::string> uninvokes = filterChildElements(_nsInfo.xmlNSPrefix + "uninvoke", statesToEnter[i]); @@ -1134,13 +1067,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& NodeSet<std::string> onEntryElems = filterChildElements(_nsInfo.xmlNSPrefix + "onEntry", stateElem); executeContent(onEntryElems, false); - // --- MONITOR: afterEnteringState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterEnteringState) - } + USCXML_MONITOR_CALLBACK3(afterEnteringState, stateElem, (i + 1 < statesToEnter.size())) if (isMember(stateElem, statesForDefaultEntry)) { // execute initial transition content for compound states @@ -1150,6 +1077,16 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& } } +#if 0 + // not working yet + if (isMember(stateElem, defaultHistoryContent)) { + // execute history transition + Arabica::XPath::NodeSet<std::string> transitions = _xpath.evaluate("" + _nsInfo.xpathPrefix + "history/" + _nsInfo.xpathPrefix + "transition", stateElem).asNodeSet(); + for (int j = 0; j < transitions.size(); j++) { + executeContent(transitions[j]); + } + } +#endif if (isFinal(stateElem)) { internalDoneSend(stateElem); Element<std::string> parent = (Element<std::string>)stateElem.getParentNode(); @@ -1174,15 +1111,15 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& for (int i = 0; i < _configuration.size(); i++) { Element<std::string> stateElem = (Element<std::string>)_configuration[i]; if (isFinal(stateElem) && parentIsScxmlState(stateElem)) { - _running = false; - _done = true; + _topLevelFinalReached = true; } } } void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state, - Arabica::XPath::NodeSet<std::string>& statesToEnter, - Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry) { + Arabica::XPath::NodeSet<std::string>& statesToEnter, + Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry, + Arabica::XPath::NodeSet<std::string>& defaultHistoryContent) { std::string stateId = ((Element<std::string>)state).getAttribute("id"); #if VERBOSE @@ -1201,7 +1138,7 @@ void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state, #endif for (int i = 0; i < historyValue.size(); i++) { - addStatesToEnter(historyValue[i], statesToEnter, statesForDefaultEntry); + addStatesToEnter(historyValue[i], statesToEnter, statesForDefaultEntry, defaultHistoryContent); NodeSet<std::string> ancestors = getProperAncestors(historyValue[i], state); #if VERBOSE @@ -1217,11 +1154,12 @@ void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state, } } } else { + defaultHistoryContent.push_back(getParentState(state)); NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", state); for (int i = 0; i < transitions.size(); i++) { NodeSet<std::string> targets = getTargetStates(transitions[i]); for (int j = 0; j < targets.size(); j++) { - addStatesToEnter(targets[j], statesToEnter, statesForDefaultEntry); + addStatesToEnter(targets[j], statesToEnter, statesForDefaultEntry, defaultHistoryContent); // Modifications from chris nuernberger NodeSet<std::string> ancestors = getProperAncestors(targets[j], state); @@ -1238,7 +1176,7 @@ void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state, NodeSet<std::string> tStates = getInitialStates(state); for (int i = 0; i < tStates.size(); i++) { - addStatesToEnter(tStates[i], statesToEnter, statesForDefaultEntry); + addStatesToEnter(tStates[i], statesToEnter, statesForDefaultEntry, defaultHistoryContent); } // addStatesToEnter(getInitialState(state), statesToEnter, statesForDefaultEntry); @@ -1247,7 +1185,7 @@ void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state, } else if(isParallel(state)) { NodeSet<std::string> childStates = getChildStates(state); for (int i = 0; i < childStates.size(); i++) { - addStatesToEnter(childStates[i], statesToEnter, statesForDefaultEntry); + addStatesToEnter(childStates[i], statesToEnter, statesForDefaultEntry, defaultHistoryContent); } } } diff --git a/src/uscxml/interpreter/InterpreterDraft6.h b/src/uscxml/interpreter/InterpreterDraft6.h index 2ab588e..25b096d 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.h +++ b/src/uscxml/interpreter/InterpreterDraft6.h @@ -26,15 +26,16 @@ namespace uscxml { class USCXML_API InterpreterDraft6 : public InterpreterImpl { protected: - void interpret(); - InterpreterState step(bool blocking); + InterpreterState interpret(); + InterpreterState step(int blocking); void stabilize(); void microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); void enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); void addStatesToEnter(const Arabica::DOM::Node<std::string>& state, Arabica::XPath::NodeSet<std::string>& statesToEnter, - Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry); + Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry, + Arabica::XPath::NodeSet<std::string>& defaultHistoryContent); void exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); void exitInterpreter(); diff --git a/src/uscxml/interpreter/InterpreterRC.cpp b/src/uscxml/interpreter/InterpreterRC.cpp index 10c41d0..d651389 100644 --- a/src/uscxml/interpreter/InterpreterRC.cpp +++ b/src/uscxml/interpreter/InterpreterRC.cpp @@ -45,15 +45,12 @@ procedure interpret(doc): enterStates([doc.initial.transition]) mainEventLoop() */ -void InterpreterRC::interpret() { +InterpreterState InterpreterRC::interpret() { try { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (!_isInitialized) init(); - if (!_scxml) { - return; - } // dump(); // just make sure we have a session id @@ -84,7 +81,6 @@ void InterpreterRC::interpret() { _dataModel.assign("_x.args", _cmdLineOptions); } - _running = true; _binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY); // @TODO: Reread http://www.w3.org/TR/scxml/#DataBinding @@ -184,6 +180,7 @@ void InterpreterRC::interpret() { if(_dataModel) _dataModel = DataModel(); + return _state; } /** @@ -237,7 +234,6 @@ procedure mainEventLoop(): exitInterpreter() */ void InterpreterRC::mainEventLoop() { - monIter_t monIter; while(_running) { NodeSet<std::string> enabledTransitions; @@ -255,13 +251,7 @@ void InterpreterRC::mainEventLoop() { _currEvent = _internalQueue.front(); _internalQueue.pop_front(); - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); - } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) - } + USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent) if (_dataModel) _dataModel.setEvent(_currEvent); @@ -299,16 +289,9 @@ void InterpreterRC::mainEventLoop() { } assert(hasLegalConfiguration()); - monIter = _monitors.begin(); // if (!_sendQueue || _sendQueue->isEmpty()) { - // --- MONITOR: onStableConfiguration ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->onStableConfiguration(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration) - } + USCXML_MONITOR_CALLBACK(onStableConfiguration) // } @@ -334,13 +317,7 @@ void InterpreterRC::mainEventLoop() { if (!_running) goto EXIT_INTERPRETER; - // --- MONITOR: beforeProcessingEvent ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); - } - USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) - } + USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent) if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId)) break; @@ -399,13 +376,7 @@ void InterpreterRC::mainEventLoop() { } EXIT_INTERPRETER: - // --- MONITOR: beforeCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(beforeCompletion) - } + USCXML_MONITOR_CALLBACK(beforeCompletion) exitInterpreter(); if (_sendQueue) { @@ -416,13 +387,7 @@ EXIT_INTERPRETER: } } - // --- MONITOR: afterCompletion ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterCompletion(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(afterCompletion) - } + USCXML_MONITOR_CALLBACK(afterCompletion) } @@ -670,48 +635,23 @@ procedure microstep(enabledTransitions): */ void InterpreterRC::microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { - // --- MONITOR: beforeMicroStep ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeMicroStep(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(beforeMicroStep) - } + USCXML_MONITOR_CALLBACK(beforeMicroStep) exitStates(enabledTransitions); - monIter_t monIter; for (int i = 0; i < enabledTransitions.size(); i++) { Element<std::string> transition(enabledTransitions[i]); - // --- MONITOR: beforeTakingTransitions ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeTakingTransitions) - } + USCXML_MONITOR_CALLBACK3(beforeTakingTransition, transition, (i + 1 < enabledTransitions.size())) executeContent(transition); - // --- MONITOR: afterTakingTransitions ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterTakingTransitions) - } + USCXML_MONITOR_CALLBACK3(afterTakingTransition, transition, (i + 1 < enabledTransitions.size())) } enterStates(enabledTransitions); - // --- MONITOR: afterMicroStep ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterMicroStep(shared_from_this()); - } - USCXML_MONITOR_CATCH_BLOCK(afterMicroStep) - } + USCXML_MONITOR_CALLBACK(afterMicroStep) } @@ -736,7 +676,6 @@ procedure exitStates(enabledTransitions): configuration.delete(s) */ void InterpreterRC::exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { - monIter_t monIter; NodeSet<std::string> statesToExit = computeExitSet(enabledTransitions); // remove statesToExit from _statesToInvoke @@ -772,13 +711,7 @@ void InterpreterRC::exitStates(const Arabica::XPath::NodeSet<std::string>& enabl } for (int i = 0; i < statesToExit.size(); i++) { - // --- MONITOR: beforeExitingState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeExitingState) - } + USCXML_MONITOR_CALLBACK3(beforeExitingState, Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())) NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onExit", statesToExit[i]); for (int j = 0; j < onExits.size(); j++) { @@ -786,13 +719,7 @@ void InterpreterRC::exitStates(const Arabica::XPath::NodeSet<std::string>& enabl executeContent(onExitElem); } - // --- MONITOR: afterExitingState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterExitingState) - } + USCXML_MONITOR_CALLBACK3(afterExitingState, Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())) NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]); for (int j = 0; j < invokes.size(); j++) { @@ -888,7 +815,6 @@ void InterpreterRC::enterStates(const Arabica::XPath::NodeSet<std::string>& enab NodeSet<std::string> statesForDefaultEntry; // initialize the temporary table for default content in history states std::map<std::string, Arabica::DOM::Node<std::string> > defaultHistoryContent; - monIter_t monIter; computeEntrySet(enabledTransitions, statesToEnter, statesForDefaultEntry, defaultHistoryContent); statesToEnter.to_document_order(); @@ -896,13 +822,7 @@ void InterpreterRC::enterStates(const Arabica::XPath::NodeSet<std::string>& enab for (int i = 0; i < statesToEnter.size(); i++) { Element<std::string> s = (Element<std::string>)statesToEnter[i]; - // --- MONITOR: beforeEnteringState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->beforeEnteringState(shared_from_this(), s, (i + 1 < statesToEnter.size())); - } - USCXML_MONITOR_CATCH_BLOCK(beforeEnteringState) - } + USCXML_MONITOR_CALLBACK3(beforeEnteringState, s, i + 1 < statesToEnter.size()) _configuration.push_back(s); _statesToInvoke.push_back(s); @@ -924,13 +844,7 @@ void InterpreterRC::enterStates(const Arabica::XPath::NodeSet<std::string>& enab NodeSet<std::string> onEntryElems = filterChildElements(_nsInfo.xmlNSPrefix + "onEntry", s); executeContent(onEntryElems, false); - // --- MONITOR: afterEnteringState ------------------------------ - for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { - try { - (*monIter)->afterEnteringState(shared_from_this(), s, (i + 1 < statesToEnter.size())); - } - USCXML_MONITOR_CATCH_BLOCK(afterEnteringState) - } + USCXML_MONITOR_CALLBACK3(afterEnteringState, s, i + 1 < statesToEnter.size()) if (isMember(s, statesForDefaultEntry)) { // execute initial transition content for compound states @@ -961,7 +875,7 @@ void InterpreterRC::enterStates(const Arabica::XPath::NodeSet<std::string>& enab internalDoneSend(s); if (parentIsScxmlState(s)) { _running = false; - _done = true; + _topLevelFinalReached = true; } else { Element<std::string> parent = (Element<std::string>)s.getParentNode(); Element<std::string> grandParent = (Element<std::string>)parent.getParentNode(); diff --git a/src/uscxml/interpreter/InterpreterRC.h b/src/uscxml/interpreter/InterpreterRC.h index 0a09c36..2cd2662 100644 --- a/src/uscxml/interpreter/InterpreterRC.h +++ b/src/uscxml/interpreter/InterpreterRC.h @@ -25,7 +25,7 @@ namespace uscxml { class InterpreterRC : public InterpreterImpl { - void interpret(); + InterpreterState interpret(); void mainEventLoop(); void exitInterpreter(); @@ -78,6 +78,8 @@ class InterpreterRC : public InterpreterImpl { Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state); #endif + bool _running; + }; } diff --git a/src/uscxml/plugins/datamodel/CMakeLists.txt b/src/uscxml/plugins/datamodel/CMakeLists.txt index f04cb78..1b2a047 100644 --- a/src/uscxml/plugins/datamodel/CMakeLists.txt +++ b/src/uscxml/plugins/datamodel/CMakeLists.txt @@ -69,25 +69,14 @@ if (BUILD_DM_ECMA) endif() -# NULL datamodel +# NULL datamodel (not useful as plugin) set(USCXML_DATAMODELS "null ${USCXML_DATAMODELS}") file(GLOB NULL_DATAMODEL null/*.cpp null/*.h ) -if (BUILD_AS_PLUGINS) - source_group("" FILES ${NULL_DATAMODEL}) - add_library(datamodel_null SHARED ${NULL_DATAMODEL} "../Plugins.cpp") - target_link_libraries(datamodel_null uscxml) - set_target_properties(datamodel_null PROPERTIES FOLDER "Plugin DataModel") - set_target_properties(datamodel_null PROPERTIES COMPILE_FLAGS "-DPLUMA_EXPORTS") - set_target_properties(datamodel_null PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}/lib") - - -else() - list (APPEND USCXML_FILES ${NULL_DATAMODEL}) -endif() +list (APPEND USCXML_FILES ${NULL_DATAMODEL}) # XPath datamodel diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index a6909b5..72252e4 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -212,6 +212,12 @@ void JSCDataModel::setEvent(const Event& event) { JSValueRef exception = NULL; + if (event.raw.size() == 0) { + std::stringstream ssRaw; + ssRaw << event; + privData->nativeObj->raw = ssRaw.str(); + } + if (event.dom) { JSStringRef propName = JSStringCreateWithUTF8CString("data"); JSObjectSetProperty(_ctx, eventObj, propName, getNodeAsValue(event.dom), 0, &exception); @@ -555,6 +561,8 @@ void JSCDataModel::assign(const Element<std::string>& assignElem, throw Event("error.execution", Event::PLATFORM); if (key.compare("_invokers") == 0) throw Event("error.execution", Event::PLATFORM); + if (key.compare("_event") == 0) + throw Event("error.execution", Event::PLATFORM); if (HAS_ATTR(assignElem, "expr")) { evalAsValue(key + " = " + ATTR(assignElem, "expr")); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 2bdd796..8b222f7 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -228,6 +228,12 @@ void V8DataModel::setEvent(const Event& event) { eventObj->SetInternalField(0, V8DOM::toExternal(privData)); eventObj.MakeWeak(0, V8SCXMLEvent::jsDestructor); + if (event.raw.size() == 0) { + std::stringstream ssRaw; + ssRaw << event; + privData->nativeObj->raw = ssRaw.str(); + } + if (event.dom) { eventObj->Set(v8::String::New("data"), getNodeAsValue(event.dom)); } else if (event.content.length() > 0) { @@ -595,6 +601,17 @@ void V8DataModel::assign(const Element<std::string>& assignElem, if (key.length() == 0) throw Event("error.execution", Event::PLATFORM); + if (key.compare("_sessionid") == 0) // test 322 + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_name") == 0) + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_ioprocessors") == 0) // test 326 + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_invokers") == 0) + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_event") == 0) + throw Event("error.execution", Event::PLATFORM); + if (HAS_ATTR(assignElem, "expr")) { evalAsValue(key + " = " + ATTR(assignElem, "expr")); } else if (node) { diff --git a/src/uscxml/plugins/element/respond/RespondElement.cpp b/src/uscxml/plugins/element/respond/RespondElement.cpp index 4fe0d2e..3eb55ed 100644 --- a/src/uscxml/plugins/element/respond/RespondElement.cpp +++ b/src/uscxml/plugins/element/respond/RespondElement.cpp @@ -78,7 +78,7 @@ void RespondElement::enterElement(const Arabica::DOM::Node<std::string>& node) { httpReply.status = strTo<int>(statusStr);; // extract the content - Arabica::XPath::NodeSet<std::string> contents = InterpreterImpl::filterChildElements(_interpreter->getXMLPrefixForNS(getNamespace()) + "content", node); + Arabica::XPath::NodeSet<std::string> contents = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "content", node); if (contents.size() > 0) { if (HAS_ATTR(contents[0], "expr")) { // -- content is evaluated string from datamodel ------ if (_interpreter->getDataModel()) { @@ -141,7 +141,7 @@ void RespondElement::enterElement(const Arabica::DOM::Node<std::string>& node) { } // process headers - Arabica::XPath::NodeSet<std::string> headers = InterpreterImpl::filterChildElements(_interpreter->getXMLPrefixForNS(getNamespace()) + "header", node); + Arabica::XPath::NodeSet<std::string> headers = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "header", node); for (int i = 0; i < headers.size(); i++) { std::string name; if (HAS_ATTR(headers[i], "name")) { diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt index f12a7a6..3f63ea3 100644 --- a/src/uscxml/plugins/invoker/CMakeLists.txt +++ b/src/uscxml/plugins/invoker/CMakeLists.txt @@ -271,6 +271,30 @@ if (LIBICAL_FOUND) endif() +# webrtc invoker + +if (LIBJINGLE_FOUND) + set(USCXML_INVOKERS "webrtc ${USCXML_INVOKERS}") + file(GLOB_RECURSE WEBRTC_INVOKER + webrtc/*.cpp + webrtc/*.h + ) + if (BUILD_AS_PLUGINS) + source_group("" FILES ${WEBRTC_INVOKER}) + add_library( + invoker_webrtc SHARED + ${WEBRTC_INVOKER} + "../Plugins.cpp") + target_link_libraries(invoker_webrtc uscxml ${LIBJINGLE_LIBRARIES}) + set_target_properties(invoker_webrtc PROPERTIES FOLDER "Plugin Invoker") + set_target_properties(invoker_webrtc PROPERTIES COMPILE_FLAGS "-DPLUMA_EXPORTS") + set_target_properties(invoker_webrtc PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}/lib") + else() + list (APPEND USCXML_FILES ${WEBRTC_INVOKER}) + endif() +endif() + + # location invoker if (CORELOCATION_LIBRARY AND OFF) diff --git a/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h index a783fa1..be50575 100644 --- a/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h +++ b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h @@ -59,8 +59,8 @@ public: virtual std::list<std::string> getNames() { std::list<std::string> names; - names.insert("calendar"); - names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#calendar"); + names.push_back("calendar"); + names.push_back("http://uscxml.tk.informatik.tu-darmstadt.de/#calendar"); return names; } diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp index 0777c62..d91b14c 100644 --- a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp +++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp @@ -1,6 +1,6 @@ /** * @file - * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) * @copyright Simplified BSD * * @cond diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.h b/src/uscxml/plugins/invoker/sample/SampleInvoker.h index 562ebd6..f7bcb24 100644 --- a/src/uscxml/plugins/invoker/sample/SampleInvoker.h +++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.h @@ -1,6 +1,6 @@ /** * @file - * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) * @copyright Simplified BSD * * @cond diff --git a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.h b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.h index 80d2075..88afc1b 100644 --- a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.h +++ b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.h @@ -41,9 +41,9 @@ public: virtual std::list<std::string> getNames() { std::list<std::string> names; - names.insert("vxml"); - names.insert("voicexml"); - names.insert("http://www.w3.org/TR/voicexml21/"); + names.push_back("vxml"); + names.push_back("voicexml"); + names.push_back("http://www.w3.org/TR/voicexml21/"); return names; } diff --git a/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.cpp b/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.cpp new file mode 100644 index 0000000..2d871c8 --- /dev/null +++ b/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.cpp @@ -0,0 +1,64 @@ +/** + * @file + * @author 2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "WebRTCInvoker.h" +#include <glog/logging.h> + +#ifdef BUILD_AS_PLUGINS +#include <Pluma/Connector.hpp> +#endif + +//#include "talk/app/webrtc/peerconnection.h" + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool pluginConnect(pluma::Host& host) { + host.add( new WebRTCInvokerProvider() ); + return true; +} +#endif + +WebRTCInvoker::WebRTCInvoker() { +} + +WebRTCInvoker::~WebRTCInvoker() { +}; + +boost::shared_ptr<InvokerImpl> WebRTCInvoker::create(InterpreterImpl* interpreter) { + boost::shared_ptr<WebRTCInvoker> invoker = boost::shared_ptr<WebRTCInvoker>(new WebRTCInvoker()); + return invoker; +} + +Data WebRTCInvoker::getDataModelVariables() { + Data data; + return data; +} + +void WebRTCInvoker::send(const SendRequest& req) { +} + +void WebRTCInvoker::cancel(const std::string sendId) { +} + +void WebRTCInvoker::invoke(const InvokeRequest& req) { +} + +}
\ No newline at end of file diff --git a/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.h b/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.h new file mode 100644 index 0000000..e4d7775 --- /dev/null +++ b/src/uscxml/plugins/invoker/webrtc/WebRTCInvoker.h @@ -0,0 +1,59 @@ +/** + * @file + * @author 2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef WEBRTCINVOKER_H_1E704623 +#define WEBRTCINVOKER_H_1E704623 + +#include <uscxml/Interpreter.h> + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class WebRTCInvoker : public InvokerImpl { +public: + WebRTCInvoker(); + virtual ~WebRTCInvoker(); + virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter); + + virtual std::list<std::string> getNames() { + std::list<std::string> names; + names.push_back("webrtc"); + names.push_back("http://uscxml.tk.informatik.tu-darmstadt.de/#webrtc"); + return names; + } + + virtual Data getDataModelVariables(); + virtual void send(const SendRequest& req); + virtual void cancel(const std::string sendId); + virtual void invoke(const InvokeRequest& req); + +protected: +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(WebRTCInvoker, InvokerImpl); +#endif + +} + + +#endif /* end of include guard: WEBRTCINVOKER_H_1E704623 */ diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index 7d9fcb8..b6dadc9 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -124,13 +124,27 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { */ // this will call the const subscript operator - if (req.data.at("content").hasKey("_scxmleventname")) { - reqEvent.name = req.data.at("content").at("_scxmleventname").atom; - } - if (req.data.at("content").hasKey("content")) { - reqEvent.content = req.data.at("content").at("content").atom; +// if (req.data.at("content").hasKey("_scxmleventname")) { +// reqEvent.name = req.data.at("content").at("_scxmleventname").atom; +// } +// if (req.data.at("content").hasKey("content")) { +// reqEvent.content = req.data.at("content").at("content").atom; +// } + + if (req.data.hasKey("content")) { + const Data& data = req.data["content"]; + for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin(); + compIter!= data.compound.end(); compIter++) { + if (compIter->first == "_scxmleventname") { + reqEvent.name = compIter->second.atom; + } else if (compIter->first == "content") { + reqEvent.content = compIter->second.atom; + } else { + reqEvent.data[compIter->first] = compIter->second; + } + } } - + // check whether we can parse it as XML if (reqEvent.content.length() > 0) { NameSpacingParser parser = NameSpacingParser::fromXML(reqEvent.content); diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIHTTPIOProcessor.h b/src/uscxml/plugins/ioprocessor/modality/MMIHTTPIOProcessor.h index 54b46c3..00b47c7 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIHTTPIOProcessor.h +++ b/src/uscxml/plugins/ioprocessor/modality/MMIHTTPIOProcessor.h @@ -44,8 +44,8 @@ public: virtual std::list<std::string> getNames() { std::list<std::string> names; - names.insert("mmihttp"); - names.insert("http://www.w3.org/TR/mmi-arch/#HTTPTransport"); + names.push_back("mmihttp"); + names.push_back("http://www.w3.org/TR/mmi-arch/#HTTPTransport"); return names; } diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index 3e7920c..e5c83d7 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -179,7 +179,6 @@ tthread::recursive_mutex HTTPServer::_instanceMutex; HTTPServer* HTTPServer::getInstance(unsigned short port, unsigned short wsPort, SSLConfig* sslConf) { // tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); if (_instance == NULL) { - std::cout << "Instantiating new HTTPServer" << std::endl; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp index 49519dc..581ba85 100644 --- a/src/uscxml/transform/ChartToFSM.cpp +++ b/src/uscxml/transform/ChartToFSM.cpp @@ -26,7 +26,7 @@ #include <math.h> #include <string.h> #include <algorithm> -#undef max
+#undef max #include <limits> namespace uscxml { @@ -101,7 +101,7 @@ Document<std::string> FlatteningInterpreter::getDocument() const { return _flatDoc; } -void FlatteningInterpreter::interpret() { +InterpreterState FlatteningInterpreter::interpret() { init(); setupIOProcessors(); @@ -177,6 +177,7 @@ void FlatteningInterpreter::interpret() { #endif createDocument(); + return _state; } void FlatteningInterpreter::executeContent(const Arabica::DOM::Node<std::string>& content, bool rethrow) { diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h index ef80a6a..07531e2 100644 --- a/src/uscxml/transform/ChartToFSM.h +++ b/src/uscxml/transform/ChartToFSM.h @@ -105,7 +105,7 @@ public: virtual ~FlatteningInterpreter(); Arabica::DOM::Document<std::string> getDocument() const; // overwrite to return flat FSM - void interpret(); + InterpreterState interpret(); protected: // gather executable content per microstep diff --git a/test/src/test-lifecycle.cpp b/test/src/test-lifecycle.cpp index 09341a3..d28d1a5 100644 --- a/test/src/test-lifecycle.cpp +++ b/test/src/test-lifecycle.cpp @@ -99,31 +99,176 @@ int main(int argc, char** argv) { google::InitGoogleLogging(argv[0]); google::LogToStderr(); - - Interpreter interpreter = Interpreter::fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test207.scxml"); InterpreterState state; - do { - state = interpreter.step(true); - switch (state) { - case uscxml::FINISHED: - std::cout << "FINISHED" << std::endl; - break; - case uscxml::INIT_FAILED: - std::cout << "INIT_FAILED" << std::endl; - break; - case uscxml::NOTHING_TODO: - std::cout << "NOTHING_TODO" << std::endl; - break; - case uscxml::INTERRUPTED: - std::cout << "INTERRUPTED" << std::endl; - break; - case uscxml::PROCESSED: - std::cout << "PROCESSED" << std::endl; - break; - default: - break; - } - } while(state != FINISHED); + + 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; + } + + if (1) { + // semantic xml parse error + const char* xml = "<invalid />"; + Interpreter interpreter = Interpreter::fromXML(xml); + state = interpreter.getState(); + assert(state == uscxml::InterpreterState::USCXML_INSTANTIATED); + + assert(interpreter.step() == uscxml::InterpreterState::USCXML_FAULTED); + std::cout << interpreter.getState() << std::endl; + } + + if (1) { + // single macrostep, multiple runs + const char* xml = + "<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.reset(); + assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED); + } + + 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); + + 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); + } + + if (0) { + // macrostep in between + const char* 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); + + assert(interpreter.getState() == uscxml::InterpreterState::USCXML_INSTANTIATED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_IDLE); + assert(interpreter.step(true) == uscxml::InterpreterState::USCXML_MACROSTEPPED); + 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_IDLE); + assert(interpreter.step(true) == uscxml::InterpreterState::USCXML_MACROSTEPPED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED); + } + + if (1) { + // macrostep in between, external event + const char* xml = + "<scxml>" + " <state id=\"start\">" + " <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_IDLE); + interpreter.receive(Event("continue")); + assert(interpreter.step(true) == uscxml::InterpreterState::USCXML_MACROSTEPPED); + 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_IDLE); + interpreter.receive(Event("continue")); + assert(interpreter.step(true) == uscxml::InterpreterState::USCXML_MACROSTEPPED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_MICROSTEPPED); + assert(interpreter.step() == uscxml::InterpreterState::USCXML_FINISHED); + } + + if (1) { + // macrostep in between, external event + const char* xml = + "<scxml>" + " <state id=\"start\">" + " <transition target=\"s2\" event=\"continue\" />" + " </state>" + " <state id=\"s2\">" + " <transition target=\"done\" />" + " </state>" + " <final id=\"done\" />" + "</scxml>"; + + Interpreter interpreter = Interpreter::fromXML(xml); + interpreter.start(); + // assume interpreter is started + assert(interpreter.getState() & InterpreterState::USCXML_THREAD_STARTED); + tthread::this_thread::sleep_for(tthread::chrono::milliseconds(100)); + + // assume it is started and running + std::cout << interpreter.getState() << std::endl; + + assert(interpreter.getState() & InterpreterState::USCXML_THREAD_STARTED); + assert(interpreter.getState() & InterpreterState::USCXML_THREAD_RUNNING); + assert(interpreter.getState() & InterpreterState::USCXML_IDLE); + + interpreter.receive(Event("continue")); + tthread::this_thread::sleep_for(tthread::chrono::milliseconds(200)); + + std::cout << interpreter.getState() << std::endl; + int state = interpreter.getState(); + assert(state & InterpreterState::USCXML_FINISHED); + assert(!(state & InterpreterState::USCXML_THREAD_STARTED)); + assert(!(state & InterpreterState::USCXML_THREAD_RUNNING)); + + } + return EXIT_SUCCESS; }
\ No newline at end of file diff --git a/test/src/test-predicates.cpp b/test/src/test-predicates.cpp index 00be408..3e3c278 100644 --- a/test/src/test-predicates.cpp +++ b/test/src/test-predicates.cpp @@ -15,17 +15,17 @@ int main(int argc, char** argv) { Interpreter interpreter = Interpreter::fromURI(argv[1]); assert(interpreter); - Node<std::string> atomicState = interpreter.getState("atomic"); + Node<std::string> atomicState = interpreter.getImpl()->getState("atomic"); assert(InterpreterImpl::isAtomic(atomicState)); assert(!InterpreterImpl::isParallel(atomicState)); assert(!InterpreterImpl::isCompound(atomicState)); - Node<std::string> compoundState = interpreter.getState("compound"); + Node<std::string> compoundState = interpreter.getImpl()->getState("compound"); assert(!InterpreterImpl::isAtomic(compoundState)); assert(!InterpreterImpl::isParallel(compoundState)); assert(InterpreterImpl::isCompound(compoundState)); - Node<std::string> parallelState = interpreter.getState("parallel"); + Node<std::string> parallelState = interpreter.getImpl()->getState("parallel"); assert(!InterpreterImpl::isAtomic(parallelState)); assert(InterpreterImpl::isParallel(parallelState)); assert(!InterpreterImpl::isCompound(parallelState)); // parallel states are not compound! @@ -34,12 +34,12 @@ int main(int argc, char** argv) { assert(initialState[0] == atomicState); NodeSet<std::string> childs = interpreter.getImpl()->getChildStates(compoundState); - Node<std::string> compoundChild1 = interpreter.getState("compoundChild1"); - Node<std::string> compoundChild2 = interpreter.getState("compoundChild2"); + Node<std::string> compoundChild1 = interpreter.getImpl()->getState("compoundChild1"); + Node<std::string> compoundChild2 = interpreter.getImpl()->getState("compoundChild2"); assert(childs.size() > 0); - assert(Interpreter::isMember(compoundChild1, childs)); - assert(Interpreter::isMember(compoundChild2, childs)); - assert(!Interpreter::isMember(compoundState, childs)); + assert(InterpreterImpl::isMember(compoundChild1, childs)); + assert(InterpreterImpl::isMember(compoundChild2, childs)); + assert(!InterpreterImpl::isMember(compoundState, childs)); assert(InterpreterImpl::isDescendant(compoundChild1, compoundState)); diff --git a/test/w3c/confEcma.xsl b/test/w3c/confEcma.xsl index 61d48c6..96c1708 100644 --- a/test/w3c/confEcma.xsl +++ b/test/w3c/confEcma.xsl @@ -66,6 +66,11 @@ <xsl:attribute name="location">Var<xsl:value-of select="." /></xsl:attribute> </xsl:template> +<!-- names an invalid location for <assign>, etc. --> +<xsl:template match="//@conf:invalidLocation"> + <xsl:attribute name="location">foo.bar.baz </xsl:attribute> +</xsl:template> + <!-- uses system var as location for <assign>, etc. --> <xsl:template match="//@conf:systemVarLocation"> <xsl:attribute name="location"><xsl:value-of select="." /></xsl:attribute> @@ -210,7 +215,7 @@ </xsl:template> <!-- returns the value of a KVP specified by <param> from _event.data --> <xsl:template match="//@conf:eventDataNamelistValue"> - <xsl:attribute name="expr">_event.data.<xsl:value-of select="."/></xsl:attribute> + <xsl:attribute name="expr">_event.data.Var<xsl:value-of select="."/></xsl:attribute> </xsl:template> <!-- returns the location of the scxml event i/o processor --> @@ -412,7 +417,7 @@ is the second argument --> <!-- return true if event.data field matches the specified value --> <xsl:template match="//@conf:eventdataVal"> - <xsl:attribute name="cond">_event.data === '<xsl:value-of select="."/>'</xsl:attribute> + <xsl:attribute name="cond">_event.data == <xsl:value-of select="."/></xsl:attribute> </xsl:template> <xsl:template match="//@conf:emptyEventData"> diff --git a/test/w3c/confXPath.xsl b/test/w3c/confXPath.xsl index 514752a..fa67f3b 100644 --- a/test/w3c/confXPath.xsl +++ b/test/w3c/confXPath.xsl @@ -66,6 +66,11 @@ <xsl:attribute name="location">$Var<xsl:value-of select="." /></xsl:attribute> </xsl:template> +<!-- names an invalid location for <assign>, etc. --> +<xsl:template match="//@conf:invalidLocation"> + <xsl:attribute name="location">foo.bar.baz </xsl:attribute> +</xsl:template> + <!-- uses system var as location for <assign>, etc. --> <xsl:template match="//@conf:systemVarLocation"> <xsl:attribute name="location">$<xsl:value-of select="." /></xsl:attribute> @@ -293,7 +298,7 @@ is of the same type as array123 --> <!-- returns the value of a KVP specified by Namelist from _event.data --> <xsl:template match="//@conf:eventDataNamelistValue"> - <xsl:attribute name="expr">$_event/data/data[@id='<xsl:value-of select="."/>']/data/text()</xsl:attribute> + <xsl:attribute name="expr">$_event/data/data[@id=Var'<xsl:value-of select="."/>']/data/text()</xsl:attribute> </xsl:template> <!-- returns the location of the scxml event i/o processor --> @@ -498,7 +503,7 @@ is the second argument --> <!-- return true if event.data field matches the specified value --> <xsl:template match="//@conf:eventdataVal"> - <xsl:attribute name="cond">$_event/data = '<xsl:value-of select="."/>'</xsl:attribute> + <xsl:attribute name="cond">$_event/data = <xsl:value-of select="."/></xsl:attribute> </xsl:template> <xsl:template match="//@conf:emptyEventData"> diff --git a/test/w3c/ecma/test179.scxml b/test/w3c/ecma/test179.scxml index 170b105..f5c9169 100644 --- a/test/w3c/ecma/test179.scxml +++ b/test/w3c/ecma/test179.scxml @@ -8,7 +8,7 @@ </send> </onentry> - <transition event="event1" cond="_event.data === '123'" target="pass"/> + <transition event="event1" cond="_event.data == 123" target="pass"/> <transition event="*" target="fail"/> </state> diff --git a/test/w3c/ecma/test193.scxml b/test/w3c/ecma/test193.scxml index 441a658..286513d 100644 --- a/test/w3c/ecma/test193.scxml +++ b/test/w3c/ecma/test193.scxml @@ -1,17 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?><!-- we test that omitting target and targetexpr of <send> when using the -basichttp event i/o processor puts error.communication on the internal queue. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +SCXML event i/o processor puts the event on the external queue. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> <state id="s0"> <onentry> - <!-- this should put an error in the internal queue --> - <send event="event1" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> - <send event="fail"/> + <send event="internal"/> + <!-- this should put event1 in the external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send event="timeout" delay="1s"/> </onentry> - <transition event="error.communication" target="pass"/> - <transition event="*" target="fail"/> + <transition event="event1" target="fail"/> + <transition event="internal" target="s1"/> </state> + + <state id="s1"> + <transition event="event1" target="pass"/> + <transition event="timeout" target="fail"/> + + </state> <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> diff --git a/test/w3c/ecma/test233.scxml b/test/w3c/ecma/test233.scxml index 3900d28..1e07c20 100644 --- a/test/w3c/ecma/test233.scxml +++ b/test/w3c/ecma/test233.scxml @@ -26,7 +26,7 @@ the transtitions. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf </finalize> </invoke> - <transition event="childToParent" cond="" target="pass"/> + <transition event="childToParent" cond="Var1==2" target="pass"/> <transition event="*" target="fail"/> </state> diff --git a/test/w3c/ecma/test286.scxml b/test/w3c/ecma/test286.scxml index 596f2ba..1c4c6bd 100644 --- a/test/w3c/ecma/test286.scxml +++ b/test/w3c/ecma/test286.scxml @@ -4,7 +4,7 @@ where no error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns <state id="s0"> <onentry> - <assign location="Var1" expr="1"/> + <assign location="foo.bar.baz " expr="1"/> <raise event="foo"/> </onentry> diff --git a/test/w3c/ecma/test294.scxml b/test/w3c/ecma/test294.scxml index efd26f4..fea1d8c 100644 --- a/test/w3c/ecma/test294.scxml +++ b/test/w3c/ecma/test294.scxml @@ -24,7 +24,7 @@ that content inside donedata sets the full value of the event.data field --><scx <state id="s1" initial="s11"> - <transition event="done.state.s1" cond="_event.data === 'foo'" target="pass"> + <transition event="done.state.s1" cond="_event.data == 'foo'" target="pass"> </transition> <transition event="done.state.s1" target="fail"> diff --git a/test/w3c/ecma/test298.scxml b/test/w3c/ecma/test298.scxml index 6a82a95..38c0e6d 100644 --- a/test/w3c/ecma/test298.scxml +++ b/test/w3c/ecma/test298.scxml @@ -1,9 +1,13 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- refence a non-existent data model location in param in donedata and see that the right error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="ecmascript" initial="s0"> +<?xml version="1.0" encoding="UTF-8"?><!-- reference a non-existent data model location in param in donedata and see that the right error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="ecmascript" initial="s0"> <datamodel> <data id="Var1" expr="0"/> </datamodel> <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delay="1s"/> + </onentry> + <transition event="error.execution" target="pass"/> <transition event="*" target="fail"/> @@ -12,7 +16,7 @@ </state> <final id="s02"> <donedata> - <param name="Var3" location="Var2"/> + <param name="Var3" location="foo.bar.baz "/> </donedata> </final> </state> diff --git a/test/w3c/ecma/test311.scxml b/test/w3c/ecma/test311.scxml index 851f3ad..9398c38 100644 --- a/test/w3c/ecma/test311.scxml +++ b/test/w3c/ecma/test311.scxml @@ -3,7 +3,8 @@ <state id="s0"> <onentry> - <assign location="Var1" expr="1"/> + <send event="timeout" delay="1s"/> + <assign location="foo.bar.baz " expr="1"/> </onentry> <transition event="error.execution" target="pass"/> <transition event=".*" target="fail"/> diff --git a/test/w3c/ecma/test329.scxml b/test/w3c/ecma/test329.scxml index 9a95643..586f15a 100644 --- a/test/w3c/ecma/test329.scxml +++ b/test/w3c/ecma/test329.scxml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?><!-- test that none of the system variables can be modified --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript" name="machineName"> + <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> <datamodel> <data id="Var1"/> <data id="Var2"/> diff --git a/test/w3c/ecma/test330.scxml b/test/w3c/ecma/test330.scxml index 5cbf4bc..5488f96 100644 --- a/test/w3c/ecma/test330.scxml +++ b/test/w3c/ecma/test330.scxml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- check that the required fields are present in both internal and external events --><scxml xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="ecmascript" name="machineName"> +<?xml version="1.0" encoding="UTF-8"?><!-- check that the required fields are present in both internal and external events --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="ecmascript" name="machineName"> <state id="s0"> <onentry> @@ -17,7 +17,7 @@ </state> - <final xmlns="http://www.w3.org/2005/07/scxml" id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final xmlns="http://www.w3.org/2005/07/scxml" id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> </scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test331.scxml b/test/w3c/ecma/test331.scxml index e1271f0..82272ea 100644 --- a/test/w3c/ecma/test331.scxml +++ b/test/w3c/ecma/test331.scxml @@ -24,7 +24,7 @@ <state id="s2"> <onentry> <!-- this will generate an error, which is a platform event --> - <assign location="Var2" expr="1"/> + <assign location="foo.bar.baz " expr="1"/> </onentry> <transition event="error" target="s3"> <assign location="Var1" expr="_event.type"/> @@ -54,7 +54,7 @@ </state> - <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> </scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test350.scxml b/test/w3c/ecma/test350.scxml deleted file mode 100644 index b401ab1..0000000 --- a/test/w3c/ecma/test350.scxml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- test that target value is used to decide what session to deliver the event to. A session should be -able to send an event to itself using its own session ID as the target --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="ecmascript" version="1.0"> -<datamodel> - <data id="Var1" expr="'#_scxml_' + _sessionid"/> - </datamodel> - -<state id="s0"> - - <onentry> - <send delay="5s" event="timeout"/> - <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" targetexpr="Var1" event="s0Event"/> - </onentry> - <transition event="s0Event" target="pass"/> - <transition event="*" target="fail"/> - -</state> - - - <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> - -</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test354.scxml b/test/w3c/ecma/test354.scxml index 3a3c33b..ef55794 100644 --- a/test/w3c/ecma/test354.scxml +++ b/test/w3c/ecma/test354.scxml @@ -40,7 +40,7 @@ and that correct values are used --><scxml xmlns="http://www.w3.org/2005/07/scxm <content>foo</content> </send> </onentry> - <transition event="event2" cond="_event.data === 'foo'" target="pass"/> + <transition event="event2" cond="_event.data == 'foo'" target="pass"/> <transition event="*" target="fail"/> </state> diff --git a/test/w3c/ecma/test401.scxml b/test/w3c/ecma/test401.scxml index 9ce7217..d5f0545 100644 --- a/test/w3c/ecma/test401.scxml +++ b/test/w3c/ecma/test401.scxml @@ -7,7 +7,7 @@ it was raised second --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:co <onentry> <send event="foo"/> <!-- assigning to a non-existent location should raise an error --> - <assign location="Var1" expr="2"/> + <assign location="foo.bar.baz " expr="2"/> </onentry> diff --git a/test/w3c/ecma/test402.scxml b/test/w3c/ecma/test402.scxml index 104483d..969256e 100644 --- a/test/w3c/ecma/test402.scxml +++ b/test/w3c/ecma/test402.scxml @@ -14,7 +14,7 @@ are pulled off the internal queue in order, and that prefix matching works on th <!-- the first internal event. The error will be the second, and event2 will be the third --> <raise event="event1"/> <!-- assigning to a non-existent location should raise an error --> - <assign location="Var1" expr="2"/> + <assign location="foo.bar.baz " expr="2"/> </onentry> <transition event="event1" target="s02"> diff --git a/test/w3c/ecma/test446.scxml b/test/w3c/ecma/test446.scxml new file mode 100644 index 0000000..0fa8698 --- /dev/null +++ b/test/w3c/ecma/test446.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that if the child of <data> is JSON, the processor + assigns it as the value of the var --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> + <datamodel> + <data id="var1">[1, 2, 3]</data> + <data id="var2" src="file:test458.txt"/> + </datamodel> + +<state id="s0"> + <transition cond="var1 instanceof Array" target="s1"/> + <transition target="fail"/> + </state> + +<state id="s1"> + <transition cond="var2 instanceof Array" target="pass"/> + <transition target="fail"/> + </state> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test458.txt b/test/w3c/ecma/test458.txt new file mode 100644 index 0000000..6001c44 --- /dev/null +++ b/test/w3c/ecma/test458.txt @@ -0,0 +1 @@ +[1, 2, 3]
\ No newline at end of file diff --git a/test/w3c/ecma/test459.scxml b/test/w3c/ecma/test459.scxml new file mode 100644 index 0000000..b631c25 --- /dev/null +++ b/test/w3c/ecma/test459.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current +value with the previous value, which is stored in var1. The current value should always be larger. If +it ever isn't, set Var4 to 0, indicating failure. Also check that the final value of the index +is 2 (meaning that the initial value was 0, not 1) --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +<datamodel> + <data id="Var1" expr="0"/> <!-- contains the previous value --> + <data id="Var2"/> <!-- the item which will contain the current value --> + <data id="Var3"/> <!-- the index --> + <data id="Var4" expr="[1,2,3]"/> + <data id="Var5" expr="1"/> <!-- 1 if success, 0 if failure --> + </datamodel> + + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var4" index="Var3"> + <if cond="Var1<Var2"> + <assign location="Var1" expr="Var2"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var5" expr="0"/> + </if> + </foreach> + </onentry> + + <!-- check that var1 has its original value --> + <transition cond="Var4==0 | Var3 != 2" target="fail"/> + <transition target="pass"/> + </state> + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + + + +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test496.scxml b/test/w3c/ecma/test496.scxml new file mode 100644 index 0000000..28c79a5 --- /dev/null +++ b/test/w3c/ecma/test496.scxml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> + + +<state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" target="#_scxml_foo"/> + <raise event="foo"/> + </onentry> + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + + + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test527.scxml b/test/w3c/ecma/test527.scxml index 426cc6c..623495a 100644 --- a/test/w3c/ecma/test527.scxml +++ b/test/w3c/ecma/test527.scxml @@ -3,7 +3,7 @@ <state id="s0" initial="s01"> - <transition event="done.state.s0" cond="_event.data === 'foo'" target="pass"> + <transition event="done.state.s0" cond="_event.data == 'foo'" target="pass"> </transition> <transition event="done.state.s0" target="fail"> diff --git a/test/w3c/ecma/test528.scxml b/test/w3c/ecma/test528.scxml index f0e8911..891215f 100644 --- a/test/w3c/ecma/test528.scxml +++ b/test/w3c/ecma/test528.scxml @@ -6,7 +6,6 @@ <transition event="error.execution" target="s1"/> <transition event="done.state.s0" target="fail"/> - <transition event="done.state.s0" target="fail"/> <state id="s01"> <transition target="s02"/> diff --git a/test/w3c/ecma/test529.scxml b/test/w3c/ecma/test529.scxml index 91dc002..0ef20c4 100644 --- a/test/w3c/ecma/test529.scxml +++ b/test/w3c/ecma/test529.scxml @@ -3,7 +3,7 @@ <state id="s0" initial="s01"> - <transition event="done.state.s0" cond="_event.data === '21'" target="pass"> + <transition event="done.state.s0" cond="_event.data == 21" target="pass"> </transition> <transition event="done.state.s0" target="fail"> diff --git a/test/w3c/ecma/test545.scxml b/test/w3c/ecma/test545.scxml new file mode 100644 index 0000000..1e12770 --- /dev/null +++ b/test/w3c/ecma/test545.scxml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that xml content in send is place as XML under event/data --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" name="scxmltest" initial="s0" version="1.0" datamodel="xpath"> + +<state id="s0"> + <onentry> + <send event="someevent"> + <content><foo xmlns=""><bar>3</bar></foo></content> + </send> + </onentry> + + <transition event="*" cond="$_event/data/foo/bar = 3" target="pass"/> + <transition event="*" target="fail"/> + </state> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test561.scxml b/test/w3c/ecma/test561.scxml index e50e00c..e94a813 100644 --- a/test/w3c/ecma/test561.scxml +++ b/test/w3c/ecma/test561.scxml @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that processor creates an ECMAScript object - _event.data when receiving JSON in an event --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that processor creates an ECMAScript DOM object + _event.data when receiving XML in an event --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> <state id="s0"> diff --git a/test/w3c/ecma/test577.scxml b/test/w3c/ecma/test577.scxml new file mode 100644 index 0000000..d115e88 --- /dev/null +++ b/test/w3c/ecma/test577.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that that <send> without target in basichttp event i/o processor +causes error.communication to get added to internal queue . --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="ecmascript" version="1.0"> + + +<state id="s0"> + <onentry> + <!-- sent by scxml event i/o processor, added to external queue --> + <send event="event1"/> + <!-- should put error.communication on internal queue --> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + + </onentry> + + + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test578.scxml b/test/w3c/ecma/test578.scxml index bdb5e2d..9a25195 100644 --- a/test/w3c/ecma/test578.scxml +++ b/test/w3c/ecma/test578.scxml @@ -5,7 +5,7 @@ <state id="s0"> <onentry> <send event="foo"> - <content>{ productName : "bar", size : 27 }</content> + <content>{ "productName" : "bar", "size" : 27 }</content> </send> </onentry> <transition event="foo" cond="_event.data.productName == 'bar'" target="pass"/> diff --git a/test/w3c/ecma/test579.scxml b/test/w3c/ecma/test579.scxml new file mode 100644 index 0000000..f89b1a9 --- /dev/null +++ b/test/w3c/ecma/test579.scxml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition, +the executable content inside the <initial> transition. However the Processor MUST +execute this content only if there is no stored history. Once the history state's +parent state has been visited and exited, the default history content must not be executed --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="ecmascript"> + + +<state id="s0"> + <datamodel> + <data id="Var1" expr="0"/> + </datamodel> + <initial> + <transition target="sh1"> + <raise event="event2"/> + </transition> + </initial> + <onentry> + <send delay="2s" event="timeout"/> + <raise event="event1"/> + </onentry> + <onexit> + <assign location="Var1" expr="Var1 + 1"/> + </onexit> + <history id="sh1"> + <transition target="s01"> + <raise event="event3"/> + </transition> + </history> + + <state id="s01"> + <transition event="event1" target="s02"/> + <transition event="*" target="fail"/> + </state> + + <state id="s02"> + <transition event="event2" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + + <transition cond="Var1==0" event="event3" target="s0"/> + <transition cond="Var1==1" event="event1" target="s2"/> + <transition event="*" target="fail"/> + </state> +</state> + +<state id="s2"> + <transition event="event2" target="s3"/> + <transition event="*" target="fail"/> + + </state> + +<state id="s3"> + <transition event="event3" target="fail"/> + <transition event="timeout" target="pass"/> + </state> + + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/ecma/test580.scxml b/test/w3c/ecma/test580.scxml new file mode 100644 index 0000000..4c4d522 --- /dev/null +++ b/test/w3c/ecma/test580.scxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that a history state never ends up part of the configuration --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="p1" datamodel="ecmascript"> + <datamodel> + <data id="Var1" expr="0"/> + </datamodel> + +<parallel id="p1"> + <onentry> + <send delay="2s" event="timeout"/> + </onentry> + + + <state id="s0"> + <transition cond="In('sh1')" target="fail"/> + <transition event="timeout" target="fail"/> + </state> + + +<state id="s1"> + <initial> + <transition target="sh1"/> + </initial> + + + <history id="sh1"> + <transition target="s11"/> + </history> + + <state id="s11"> + <transition cond="In('sh1')" target="fail"/> + <transition target="s12"/> + </state> + + <state id="s12"/> + <transition cond="In('sh1')" target="fail"/> + <transition cond="Var1==0" target="sh1"/> + <transition cond="Var1==1" target="pass"/> + <onexit> + <assign location="Var1" expr="Var1 + 1"/> + </onexit> + </state> + + + </parallel> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test159.txml b/test/w3c/txml/test159.txml index b7245c0..f4340b3 100644 --- a/test/w3c/txml/test159.txml +++ b/test/w3c/txml/test159.txml @@ -10,7 +10,7 @@ The send tag will raise an error so var1 should not be incremented. If it is fa <state id="s0"> <onentry> - <send event="thisWillFail" conf:illegaltarget=""/> + <send event="thisWillFail" conf:illegalTarget=""/> <conf:incrementID id="1"/> </onentry> <transition conf:idVal="1=1" conf:targetfail=""/> diff --git a/test/w3c/txml/test193.txml b/test/w3c/txml/test193.txml index ba1598b..24cb2ac 100644 --- a/test/w3c/txml/test193.txml +++ b/test/w3c/txml/test193.txml @@ -1,20 +1,27 @@ <?xml version="1.0"?> <!-- we test that omitting target and targetexpr of <send> when using the -basichttp event i/o processor puts error.communication on the internal queue. --> +SCXML event i/o processor puts the event on the external queue. --> <scxml initial="s0" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> <state id="s0"> <onentry> - <!-- this should put an error in the internal queue --> - <send event="event1" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> - <send event="fail"/> + <send event="internal"/> + <!-- this should put event1 in the external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send event="timeout" delay="1s"/> </onentry> - <transition event="error.communication" conf:targetpass=""/> - <transition event="*" conf:targetfail=""/> + <transition event="event1" conf:targetfail=""/> + <transition event="internal" target="s1"/> </state> + + <state id="s1"> + <transition event="event1" conf:targetpass=""/> + <transition event="timeout" conf:targetfail=""/> + + </state> <conf:pass/> <conf:fail/> diff --git a/test/w3c/txml/test233.txml b/test/w3c/txml/test233.txml index 94b219b..8f186fd 100644 --- a/test/w3c/txml/test233.txml +++ b/test/w3c/txml/test233.txml @@ -30,7 +30,7 @@ the transtitions. --> </finalize> </invoke> - <transition event="childToParent" conf:idVal="1 2" conf:targetpass=""/> + <transition event="childToParent" conf:idVal="1=2" conf:targetpass=""/> <transition event="*" conf:targetfail=""/> </state> diff --git a/test/w3c/txml/test286.txml b/test/w3c/txml/test286.txml index 89b77a9..a58f643 100644 --- a/test/w3c/txml/test286.txml +++ b/test/w3c/txml/test286.txml @@ -9,7 +9,7 @@ where no error is raised --> <state id="s0"> <onentry> - <assign conf:location="1" conf:expr="1"/> + <assign conf:invalidLocation="" conf:expr="1"/> <raise event="foo"/> </onentry> diff --git a/test/w3c/txml/test294.txml b/test/w3c/txml/test294.txml index 507ff3b..c257cec 100644 --- a/test/w3c/txml/test294.txml +++ b/test/w3c/txml/test294.txml @@ -27,7 +27,7 @@ that content inside donedata sets the full value of the event.data field --> <state id="s1" initial="s11"> - <transition event="done.state.s1" conf:eventdataVal="foo" conf:targetpass=""> + <transition event="done.state.s1" conf:eventdataVal="'foo'" conf:targetpass=""> </transition> <transition event="done.state.s1" conf:targetfail=""> diff --git a/test/w3c/txml/test298.txml b/test/w3c/txml/test298.txml index e1af350..2935099 100644 --- a/test/w3c/txml/test298.txml +++ b/test/w3c/txml/test298.txml @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<!-- refence a non-existent data model location in param in donedata and see that the right error is raised --> +<!-- reference a non-existent data model location in param in donedata and see that the right error is raised --> <scxml version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" conf:datamodel="" initial="s0"> <datamodel> @@ -7,6 +7,10 @@ </datamodel> <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delay="1s"/> + </onentry> + <transition event="error.execution" conf:targetpass=""/> <transition event="*" conf:targetfail=""/> @@ -15,7 +19,7 @@ </state> <final id="s02"> <donedata> - <param conf:name="3" conf:location="2"/> + <param conf:name="3" conf:invalidLocation=""/> </donedata> </final> </state> diff --git a/test/w3c/txml/test311.txml b/test/w3c/txml/test311.txml index f6485be..50e506a 100644 --- a/test/w3c/txml/test311.txml +++ b/test/w3c/txml/test311.txml @@ -8,7 +8,8 @@ xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0"> <state id="s0"> <onentry> - <assign conf:location="1" conf:expr="1"/> + <send event="timeout" delay="1s"/> + <assign conf:invalidLocation="" conf:expr="1"/> </onentry> <transition event="error.execution" conf:targetpass=""/> <transition event=".*" conf:targetfail=""/> diff --git a/test/w3c/txml/test330.txml b/test/w3c/txml/test330.txml index 7778fad..ca13451 100644 --- a/test/w3c/txml/test330.txml +++ b/test/w3c/txml/test330.txml @@ -2,7 +2,7 @@ <!-- check that the required fields are present in both internal and external events --> -<scxml initial="s0" conf:datamodel="" name="machineName" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> +<scxml initial="s0" conf:datamodel="" name="machineName" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> <state id="s0"> <onentry> diff --git a/test/w3c/txml/test331.txml b/test/w3c/txml/test331.txml index a273b14..553d2f2 100644 --- a/test/w3c/txml/test331.txml +++ b/test/w3c/txml/test331.txml @@ -26,7 +26,7 @@ <state id="s2"> <onentry> <!-- this will generate an error, which is a platform event --> - <assign conf:location="2" conf:expr="1"/> + <assign conf:invalidLocation="" conf:expr="1"/> </onentry> <transition event="error" target="s3"> <assign conf:location="1" conf:eventType=""/> @@ -56,7 +56,7 @@ </state> - <final xmlns="http://www.w3.org/2005/07/scxml" id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final xmlns="http://www.w3.org/2005/07/scxml" id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + <conf:pass/> + <conf:fail/> </scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test350.txml b/test/w3c/txml/test350.txml index b57e881..1086db7 100644 --- a/test/w3c/txml/test350.txml +++ b/test/w3c/txml/test350.txml @@ -5,12 +5,14 @@ able to send an event to itself using its own session ID as the target --> <scxml initial="s0" conf:datamodel="" version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> <datamodel> - <data conf:id="1" conf:expr="'#_scxml_' + _sessionid"/> - </datamodel> + <data conf:id="1" conf:quoteExpr="#_scxml_"/> + <data conf:id="2" conf:systemVarExpr="_sessionid”/> +</datamodel> <state id="s0"> <onentry> + <conf:concatVars id1="1" id2="2"/> <send delay="5s" event="timeout"/> <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" conf:targetVar="1" event="s0Event"/> </onentry> diff --git a/test/w3c/txml/test354.txml b/test/w3c/txml/test354.txml index d9e643a..0f1f6c5 100644 --- a/test/w3c/txml/test354.txml +++ b/test/w3c/txml/test354.txml @@ -13,12 +13,12 @@ and that correct values are used --> <state id="s0"> <onentry> <send delay="5s" event="timeout"/> - <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="Var1"> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" conf:namelist="1"> <param name="param1" conf:expr="2"/> </send> </onentry> <transition event="event1" target="s1"> - <assign conf:location="2" conf:eventDataNamelistValue="Var1"/> + <assign conf:location="2" conf:eventDataNamelistValue="1"/> <assign conf:location="3" conf:eventDataParamValue="param1"/> </transition> <transition event="*" conf:targetfail=""> @@ -44,7 +44,7 @@ and that correct values are used --> <content>foo</content> </send> </onentry> - <transition event="event2" conf:eventdataVal="foo" conf:targetpass=""/> + <transition event="event2" conf:eventdataVal="'foo'" conf:targetpass=""/> <transition event="*" conf:targetfail=""/> </state> diff --git a/test/w3c/txml/test401.txml b/test/w3c/txml/test401.txml index a42b719..9aaa506 100644 --- a/test/w3c/txml/test401.txml +++ b/test/w3c/txml/test401.txml @@ -11,7 +11,7 @@ it was raised second --> <onentry> <send event="foo"/> <!-- assigning to a non-existent location should raise an error --> - <assign conf:location="1" conf:expr="2"/> + <assign conf:invalidLocation="" conf:expr="2"/> </onentry> diff --git a/test/w3c/txml/test402.txml b/test/w3c/txml/test402.txml index 24e84e1..4e6d485 100644 --- a/test/w3c/txml/test402.txml +++ b/test/w3c/txml/test402.txml @@ -18,7 +18,7 @@ are pulled off the internal queue in order, and that prefix matching works on th <!-- the first internal event. The error will be the second, and event2 will be the third --> <raise event="event1"/> <!-- assigning to a non-existent location should raise an error --> - <assign conf:location="1" conf:expr="2"/> + <assign conf:invalidLocation="" conf:expr="2"/> </onentry> <transition event="event1" target="s02"> diff --git a/test/w3c/txml/test446.txml b/test/w3c/txml/test446.txml new file mode 100644 index 0000000..afdf6a0 --- /dev/null +++ b/test/w3c/txml/test446.txml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + <!-- in the ECMA data model, test that if the child of <data> is JSON, the processor + assigns it as the value of the var --> + + <scxml xmlns="http://www.w3.org/2005/07/scxml" + xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> + <datamodel> + <data id="var1">[1, 2, 3]</data> + <data id="var2" src="file:test458.txt"/> + </datamodel> + +<state id="s0"> + <transition cond="var1 instanceof Array" target="s1"/> + <transition conf:targetfail=""/> + </state> + +<state id="s1"> + <transition cond="var2 instanceof Array" conf:targetpass=""/> + <transition conf:targetfail=""/> + </state> + +<conf:pass/> +<conf:fail/> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test459.txml b/test/w3c/txml/test459.txml new file mode 100644 index 0000000..3cdec7b --- /dev/null +++ b/test/w3c/txml/test459.txml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current +value with the previous value, which is stored in var1. The current value should always be larger. If +it ever isn't, set Var4 to 0, indicating failure. Also check that the final value of the index +is 2 (meaning that the initial value was 0, not 1) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" +xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +<datamodel> + <data id="Var1" expr="0"/> <!-- contains the previous value --> + <data id="Var2"/> <!-- the item which will contain the current value --> + <data id="Var3"/> <!-- the index --> + <data id="Var4" expr="[1,2,3]"/> + <data id="Var5" expr="1"/> <!-- 1 if success, 0 if failure --> + </datamodel> + + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var4" index="Var3"> + <if cond="Var1<Var2"> + <assign location="Var1" expr="Var2"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var5" expr="0"/> + </if> + </foreach> + </onentry> + + <!-- check that var1 has its original value --> + <transition cond="Var4==0 | Var3 != 2" target="fail"/> + <transition target="pass"/> + </state> + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + + + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test496.txml b/test/w3c/txml/test496.txml new file mode 100644 index 0000000..ecd1e15 --- /dev/null +++ b/test/w3c/txml/test496.txml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> + +<scxml initial="s0" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> + + +<state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" conf:unreachableTarget=""/> + <raise event="foo"/> + </onentry> + <transition event="error.communication" conf:targetpass=""/> + <transition event="*" conf:targetfail=""/> + </state> + + + + <conf:pass/> + <conf:fail/> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test527.txml b/test/w3c/txml/test527.txml index 80894a7..f97015d 100644 --- a/test/w3c/txml/test527.txml +++ b/test/w3c/txml/test527.txml @@ -6,7 +6,7 @@ <state id="s0" initial="s01"> - <transition event="done.state.s0" conf:eventdataVal="foo" conf:targetpass=""> + <transition event="done.state.s0" conf:eventdataVal="'foo'" conf:targetpass=""> </transition> <transition event="done.state.s0" conf:targetfail=""> diff --git a/test/w3c/txml/test528.txml b/test/w3c/txml/test528.txml index 271bb1c..ed70c20 100644 --- a/test/w3c/txml/test528.txml +++ b/test/w3c/txml/test528.txml @@ -9,7 +9,6 @@ <transition event="error.execution" target="s1"/> <transition event="done.state.s0" conf:targetfail=""/> - <transition event="done.state.s0" conf:targetfail=""/> <state id="s01"> <transition target="s02"/> diff --git a/test/w3c/txml/test545.txml b/test/w3c/txml/test545.txml new file mode 100644 index 0000000..d95f8f3 --- /dev/null +++ b/test/w3c/txml/test545.txml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + <!-- test that xml content in send is place as XML under event/data --> + + <scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" + xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="xpath"> + +<state id="s0"> + <onentry> + <send event="someevent"> + <content><foo xmlns=""><bar>3</bar></foo></content> + </send> + </onentry> + + <transition event="*" cond="$_event/data/foo/bar = 3" conf:targetpass=""/> + <transition event="*" conf:targetfail=""/> + </state> + +<conf:pass/> +<conf:fail/> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test561.txml b/test/w3c/txml/test561.txml index 4b7ec8e..183cb9d 100644 --- a/test/w3c/txml/test561.txml +++ b/test/w3c/txml/test561.txml @@ -1,6 +1,6 @@ <?xml version="1.0"?> - <!-- in the ECMA data model, test that processor creates an ECMAScript object - _event.data when receiving JSON in an event --> + <!-- in the ECMA data model, test that processor creates an ECMAScript DOM object + _event.data when receiving XML in an event --> <scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> diff --git a/test/w3c/txml/test577.txml b/test/w3c/txml/test577.txml new file mode 100644 index 0000000..adf1531 --- /dev/null +++ b/test/w3c/txml/test577.txml @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<!-- test that that <send> without target in basichttp event i/o processor +causes error.communication to get added to internal queue . --> + +<scxml initial="s0" conf:datamodel="" version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> + + +<state id="s0"> + <onentry> + <!-- sent by scxml event i/o processor, added to external queue --> + <send event="event1"/> + <!-- should put error.communication on internal queue --> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + + </onentry> + + + <transition event="error.communication" conf:targetpass=""/> + <transition event="*" conf:targetfail=""/> + </state> + + <conf:pass/> + <conf:fail/> +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test578.txml b/test/w3c/txml/test578.txml index a4de932..cae3cdd 100644 --- a/test/w3c/txml/test578.txml +++ b/test/w3c/txml/test578.txml @@ -9,7 +9,7 @@ <state id="s0"> <onentry> <send event="foo"> - <content>{ productName : "bar", size : 27 }</content> + <content>{ "productName" : "bar", "size" : 27 }</content> </send> </onentry> <transition event="foo" cond="_event.data.productName == 'bar'" diff --git a/test/w3c/txml/test579.txml b/test/w3c/txml/test579.txml new file mode 100644 index 0000000..7c48c37 --- /dev/null +++ b/test/w3c/txml/test579.txml @@ -0,0 +1,65 @@ +<?xml version="1.0"?> +<!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition, +the executable content inside the <initial> transition. However the Processor MUST +execute this content only if there is no stored history. Once the history state's +parent state has been visited and exited, the default history content must not be executed --> + + +<scxml version="1.0" initial="s0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> + + +<state id="s0"> + <datamodel> + <data conf:id="1" conf:expr="0"/> + </datamodel> + <initial> + <transition target="sh1"> + <raise event="event2"/> + </transition> + </initial> + <onentry> + <send delay="2s" event="timeout"/> + <raise event="event1"/> + </onentry> + <onexit> + <conf:incrementID id="1"/> + </onexit> + <history id="sh1"> + <transition target="s01"> + <raise event="event3"/> + </transition> + </history> + + <state id="s01"> + <transition event="event1" target="s02"/> + <transition event="*" conf:targetfail=""/> + </state> + + <state id="s02"> + <transition event="event2" target="s03"/> + <transition event="*" conf:targetfail=""/> + </state> + <state id="s03"> + + <transition conf:idVal="1==0" event="event3" target="s0"/> + <transition conf:idVal="1==1" event="event1" target="s2"/> + <transition event="*" conf:targetfail=""/> + </state> +</state> + +<state id="s2"> + <transition event="event2" target="s3"/> + <transition event="*" conf:targetfail=""/> + + </state> + +<state id="s3"> + <transition event="event3" conf:targetfail=""/> + <transition event="timeout" conf:targetpass=""/> + </state> + + +<conf:pass/> +<conf:fail/> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/txml/test580.txml b/test/w3c/txml/test580.txml new file mode 100644 index 0000000..4fddd39 --- /dev/null +++ b/test/w3c/txml/test580.txml @@ -0,0 +1,52 @@ +<?xml version="1.0"?> +<!-- test that a history state never ends up part of the configuration --> + + +<scxml version="1.0" initial="p1" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance"> + <datamodel> + <data conf:id="1" conf:expr="0"/> + </datamodel> + +<parallel id="p1"> + <onentry> + <send delay="2s" event="timeout"/> + </onentry> + + + <state id="s0"> + <transition conf:inState="sh1" conf:targetfail=""/> + <transition event="timeout" conf:targetfail=""/> + </state> + + +<state id="s1"> + <initial> + <transition target="sh1"/> + </initial> + + + <history id="sh1"> + <transition target="s11"/> + </history> + + <state id="s11"> + <transition conf:inState="sh1" conf:targetfail=""/> + <transition target="s12"/> + </state> + + <state id="s12"/> + <transition conf:inState="sh1" conf:targetfail=""/> + <transition conf:idVal="1==0" target="sh1"/> + <transition conf:idVal="1==1" conf:targetpass=""/> + <onexit> + <conf:incrementID id="1"/> + </onexit> + </state> + + + </parallel> + +<conf:pass/> +<conf:fail/> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/update-txml.sh b/test/w3c/update-txml.sh index 074318d..b733c6b 100755 --- a/test/w3c/update-txml.sh +++ b/test/w3c/update-txml.sh @@ -1,6 +1,11 @@ #!/bin/bash wget -rl1 -Atxml,txt,xsl http://www.w3.org/Voice/2013/scxml-irp/ +# wget http://www.w3.org/Voice/2013/scxml-irp/545/test545.txml +# wget http://www.w3.org/Voice/2013/scxml-irp/577/test577.txml +# mv test545.txml ./txml +# mv test577.txml ./txml + 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 {} . \; diff --git a/test/w3c/xpath/test159.scxml b/test/w3c/xpath/test159.scxml index 1f2af35..779ed7c 100644 --- a/test/w3c/xpath/test159.scxml +++ b/test/w3c/xpath/test159.scxml @@ -6,7 +6,7 @@ The send tag will raise an error so var1 should not be incremented. If it is fa <state id="s0"> <onentry> - <send event="thisWillFail" conf:illegaltarget=""/> + <send event="thisWillFail" target="baz"/> <assign location="$Var1" expr="$Var1 + 1"/> </onentry> <transition cond="$Var1/text() =1" target="fail"/> diff --git a/test/w3c/xpath/test179.scxml b/test/w3c/xpath/test179.scxml index 1c281b5..42d1533 100644 --- a/test/w3c/xpath/test179.scxml +++ b/test/w3c/xpath/test179.scxml @@ -8,7 +8,7 @@ </send> </onentry> - <transition event="event1" cond="$_event/data = '123'" target="pass"/> + <transition event="event1" cond="$_event/data = 123" target="pass"/> <transition event="*" target="fail"/> </state> diff --git a/test/w3c/xpath/test193.scxml b/test/w3c/xpath/test193.scxml index 58a5c67..54926cf 100644 --- a/test/w3c/xpath/test193.scxml +++ b/test/w3c/xpath/test193.scxml @@ -1,17 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?><!-- we test that omitting target and targetexpr of <send> when using the -basichttp event i/o processor puts error.communication on the internal queue. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="xpath"> +SCXML event i/o processor puts the event on the external queue. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="xpath"> <state id="s0"> <onentry> - <!-- this should put an error in the internal queue --> - <send event="event1" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> - <send event="fail"/> + <send event="internal"/> + <!-- this should put event1 in the external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send event="timeout" delay="1s"/> </onentry> - <transition event="error.communication" target="pass"/> - <transition event="*" target="fail"/> + <transition event="event1" target="fail"/> + <transition event="internal" target="s1"/> </state> + + <state id="s1"> + <transition event="event1" target="pass"/> + <transition event="timeout" target="fail"/> + + </state> <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> diff --git a/test/w3c/xpath/test233.scxml b/test/w3c/xpath/test233.scxml index c4d7eb7..e7b4116 100644 --- a/test/w3c/xpath/test233.scxml +++ b/test/w3c/xpath/test233.scxml @@ -26,7 +26,7 @@ the transtitions. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf </finalize> </invoke> - <transition event="childToParent" cond="" target="pass"/> + <transition event="childToParent" cond="$Var1/text() =2" target="pass"/> <transition event="*" target="fail"/> </state> diff --git a/test/w3c/xpath/test286.scxml b/test/w3c/xpath/test286.scxml index 80c0046..53aad73 100644 --- a/test/w3c/xpath/test286.scxml +++ b/test/w3c/xpath/test286.scxml @@ -4,7 +4,7 @@ where no error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns <state id="s0"> <onentry> - <assign location="$Var1" expr="1"/> + <assign location="foo.bar.baz " expr="1"/> <raise event="foo"/> </onentry> diff --git a/test/w3c/xpath/test298.scxml b/test/w3c/xpath/test298.scxml index ab8a5a9..8525192 100644 --- a/test/w3c/xpath/test298.scxml +++ b/test/w3c/xpath/test298.scxml @@ -1,9 +1,13 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- refence a non-existent data model location in param in donedata and see that the right error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="xpath" initial="s0"> +<?xml version="1.0" encoding="UTF-8"?><!-- reference a non-existent data model location in param in donedata and see that the right error is raised --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="xpath" initial="s0"> <datamodel> <data id="Var1" expr="0"/> </datamodel> <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delay="1s"/> + </onentry> + <transition event="error.execution" target="pass"/> <transition event="*" target="fail"/> @@ -12,7 +16,7 @@ </state> <final id="s02"> <donedata> - <param name="Var3" location="$Var2"/> + <param name="Var3" location="foo.bar.baz "/> </donedata> </final> </state> diff --git a/test/w3c/xpath/test311.scxml b/test/w3c/xpath/test311.scxml index 487793c..1353b3e 100644 --- a/test/w3c/xpath/test311.scxml +++ b/test/w3c/xpath/test311.scxml @@ -3,7 +3,8 @@ <state id="s0"> <onentry> - <assign location="$Var1" expr="1"/> + <send event="timeout" delay="1s"/> + <assign location="foo.bar.baz " expr="1"/> </onentry> <transition event="error.execution" target="pass"/> <transition event=".*" target="fail"/> diff --git a/test/w3c/xpath/test330.scxml b/test/w3c/xpath/test330.scxml index 353c683..c95befd 100644 --- a/test/w3c/xpath/test330.scxml +++ b/test/w3c/xpath/test330.scxml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- check that the required fields are present in both internal and external events --><scxml xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="xpath" name="machineName"> +<?xml version="1.0" encoding="UTF-8"?><!-- check that the required fields are present in both internal and external events --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="xpath" name="machineName"> <state id="s0"> <onentry> @@ -17,7 +17,7 @@ </state> - <final xmlns="http://www.w3.org/2005/07/scxml" id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final xmlns="http://www.w3.org/2005/07/scxml" id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> </scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test331.scxml b/test/w3c/xpath/test331.scxml index aec6d98..e887869 100644 --- a/test/w3c/xpath/test331.scxml +++ b/test/w3c/xpath/test331.scxml @@ -24,7 +24,7 @@ <state id="s2"> <onentry> <!-- this will generate an error, which is a platform event --> - <assign location="$Var2" expr="1"/> + <assign location="foo.bar.baz " expr="1"/> </onentry> <transition event="error" target="s3"> <assign location="$Var1" expr="$_event/type/text()"/> @@ -54,7 +54,7 @@ </state> - <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> </scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test350.scxml b/test/w3c/xpath/test350.scxml deleted file mode 100644 index ce94e9f..0000000 --- a/test/w3c/xpath/test350.scxml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- test that target value is used to decide what session to deliver the event to. A session should be -able to send an event to itself using its own session ID as the target --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="xpath" version="1.0"> -<datamodel> - <data id="Var1" expr="'#_scxml_' + _sessionid"/> - </datamodel> - -<state id="s0"> - - <onentry> - <send delay="5s" event="timeout"/> - <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" targetexpr="$Var1" event="s0Event"/> - </onentry> - <transition event="s0Event" target="pass"/> - <transition event="*" target="fail"/> - -</state> - - - <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> - <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> - -</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test354.scxml b/test/w3c/xpath/test354.scxml index 93d768d..499b568 100644 --- a/test/w3c/xpath/test354.scxml +++ b/test/w3c/xpath/test354.scxml @@ -9,12 +9,12 @@ and that correct values are used --><scxml xmlns="http://www.w3.org/2005/07/scxm <state id="s0"> <onentry> <send delay="5s" event="timeout"/> - <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="Var1"> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="$Var1"> <param name="param1" expr="2"/> </send> </onentry> <transition event="event1" target="s1"> - <assign location="$Var2" expr="$_event/data/data[@id='Var1']/data/text()"/> + <assign location="$Var2" expr="$_event/data/data[@id=Var'1']/data/text()"/> <assign location="$Var3" expr="$_event/data/data[@id='param1']/text()"/> </transition> <transition event="*" target="fail"> diff --git a/test/w3c/xpath/test401.scxml b/test/w3c/xpath/test401.scxml index 7900490..586a049 100644 --- a/test/w3c/xpath/test401.scxml +++ b/test/w3c/xpath/test401.scxml @@ -7,7 +7,7 @@ it was raised second --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:co <onentry> <send event="foo"/> <!-- assigning to a non-existent location should raise an error --> - <assign location="$Var1" expr="2"/> + <assign location="foo.bar.baz " expr="2"/> </onentry> diff --git a/test/w3c/xpath/test402.scxml b/test/w3c/xpath/test402.scxml index 4a822c8..798f992 100644 --- a/test/w3c/xpath/test402.scxml +++ b/test/w3c/xpath/test402.scxml @@ -14,7 +14,7 @@ are pulled off the internal queue in order, and that prefix matching works on th <!-- the first internal event. The error will be the second, and event2 will be the third --> <raise event="event1"/> <!-- assigning to a non-existent location should raise an error --> - <assign location="$Var1" expr="2"/> + <assign location="foo.bar.baz " expr="2"/> </onentry> <transition event="event1" target="s02"> diff --git a/test/w3c/xpath/test446.scxml b/test/w3c/xpath/test446.scxml new file mode 100644 index 0000000..0fa8698 --- /dev/null +++ b/test/w3c/xpath/test446.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that if the child of <data> is JSON, the processor + assigns it as the value of the var --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> + <datamodel> + <data id="var1">[1, 2, 3]</data> + <data id="var2" src="file:test458.txt"/> + </datamodel> + +<state id="s0"> + <transition cond="var1 instanceof Array" target="s1"/> + <transition target="fail"/> + </state> + +<state id="s1"> + <transition cond="var2 instanceof Array" target="pass"/> + <transition target="fail"/> + </state> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test459.scxml b/test/w3c/xpath/test459.scxml new file mode 100644 index 0000000..b631c25 --- /dev/null +++ b/test/w3c/xpath/test459.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current +value with the previous value, which is stored in var1. The current value should always be larger. If +it ever isn't, set Var4 to 0, indicating failure. Also check that the final value of the index +is 2 (meaning that the initial value was 0, not 1) --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +<datamodel> + <data id="Var1" expr="0"/> <!-- contains the previous value --> + <data id="Var2"/> <!-- the item which will contain the current value --> + <data id="Var3"/> <!-- the index --> + <data id="Var4" expr="[1,2,3]"/> + <data id="Var5" expr="1"/> <!-- 1 if success, 0 if failure --> + </datamodel> + + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var4" index="Var3"> + <if cond="Var1<Var2"> + <assign location="Var1" expr="Var2"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var5" expr="0"/> + </if> + </foreach> + </onentry> + + <!-- check that var1 has its original value --> + <transition cond="Var4==0 | Var3 != 2" target="fail"/> + <transition target="pass"/> + </state> + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + + + +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test496.scxml b/test/w3c/xpath/test496.scxml new file mode 100644 index 0000000..a30064f --- /dev/null +++ b/test/w3c/xpath/test496.scxml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="xpath"> + + +<state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" target="#_scxml_foo"/> + <raise event="foo"/> + </onentry> + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + + + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test528.scxml b/test/w3c/xpath/test528.scxml index f8f8416..eda36d2 100644 --- a/test/w3c/xpath/test528.scxml +++ b/test/w3c/xpath/test528.scxml @@ -6,7 +6,6 @@ <transition event="error.execution" target="s1"/> <transition event="done.state.s0" target="fail"/> - <transition event="done.state.s0" target="fail"/> <state id="s01"> <transition target="s02"/> diff --git a/test/w3c/xpath/test529.scxml b/test/w3c/xpath/test529.scxml index 5a78529..d67af4b 100644 --- a/test/w3c/xpath/test529.scxml +++ b/test/w3c/xpath/test529.scxml @@ -3,7 +3,7 @@ <state id="s0" initial="s01"> - <transition event="done.state.s0" cond="$_event/data = '21'" target="pass"> + <transition event="done.state.s0" cond="$_event/data = 21" target="pass"> </transition> <transition event="done.state.s0" target="fail"> diff --git a/test/w3c/xpath/test545.scxml b/test/w3c/xpath/test545.scxml new file mode 100644 index 0000000..1e12770 --- /dev/null +++ b/test/w3c/xpath/test545.scxml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that xml content in send is place as XML under event/data --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" name="scxmltest" initial="s0" version="1.0" datamodel="xpath"> + +<state id="s0"> + <onentry> + <send event="someevent"> + <content><foo xmlns=""><bar>3</bar></foo></content> + </send> + </onentry> + + <transition event="*" cond="$_event/data/foo/bar = 3" target="pass"/> + <transition event="*" target="fail"/> + </state> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test561.scxml b/test/w3c/xpath/test561.scxml index e50e00c..e94a813 100644 --- a/test/w3c/xpath/test561.scxml +++ b/test/w3c/xpath/test561.scxml @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that processor creates an ECMAScript object - _event.data when receiving JSON in an event --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> +<?xml version="1.0" encoding="UTF-8"?><!-- in the ECMA data model, test that processor creates an ECMAScript DOM object + _event.data when receiving XML in an event --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript"> <state id="s0"> diff --git a/test/w3c/xpath/test577.scxml b/test/w3c/xpath/test577.scxml new file mode 100644 index 0000000..7652834 --- /dev/null +++ b/test/w3c/xpath/test577.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that that <send> without target in basichttp event i/o processor +causes error.communication to get added to internal queue . --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="xpath" version="1.0"> + + +<state id="s0"> + <onentry> + <!-- sent by scxml event i/o processor, added to external queue --> + <send event="event1"/> + <!-- should put error.communication on internal queue --> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + + </onentry> + + + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + + <final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> + <final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test578.scxml b/test/w3c/xpath/test578.scxml index bdb5e2d..9a25195 100644 --- a/test/w3c/xpath/test578.scxml +++ b/test/w3c/xpath/test578.scxml @@ -5,7 +5,7 @@ <state id="s0"> <onentry> <send event="foo"> - <content>{ productName : "bar", size : 27 }</content> + <content>{ "productName" : "bar", "size" : 27 }</content> </send> </onentry> <transition event="foo" cond="_event.data.productName == 'bar'" target="pass"/> diff --git a/test/w3c/xpath/test579.scxml b/test/w3c/xpath/test579.scxml new file mode 100644 index 0000000..311c0a9 --- /dev/null +++ b/test/w3c/xpath/test579.scxml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition, +the executable content inside the <initial> transition. However the Processor MUST +execute this content only if there is no stored history. Once the history state's +parent state has been visited and exited, the default history content must not be executed --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="xpath"> + + +<state id="s0"> + <datamodel> + <data id="Var1" expr="0"/> + </datamodel> + <initial> + <transition target="sh1"> + <raise event="event2"/> + </transition> + </initial> + <onentry> + <send delay="2s" event="timeout"/> + <raise event="event1"/> + </onentry> + <onexit> + <assign location="$Var1" expr="$Var1 + 1"/> + </onexit> + <history id="sh1"> + <transition target="s01"> + <raise event="event3"/> + </transition> + </history> + + <state id="s01"> + <transition event="event1" target="s02"/> + <transition event="*" target="fail"/> + </state> + + <state id="s02"> + <transition event="event2" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + + <transition cond="$Var1/text() ==0" event="event3" target="s0"/> + <transition cond="$Var1/text() ==1" event="event1" target="s2"/> + <transition event="*" target="fail"/> + </state> +</state> + +<state id="s2"> + <transition event="event2" target="s3"/> + <transition event="*" target="fail"/> + + </state> + +<state id="s3"> + <transition event="event3" target="fail"/> + <transition event="timeout" target="pass"/> + </state> + + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file diff --git a/test/w3c/xpath/test580.scxml b/test/w3c/xpath/test580.scxml new file mode 100644 index 0000000..272bbce --- /dev/null +++ b/test/w3c/xpath/test580.scxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- test that a history state never ends up part of the configuration --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="p1" datamodel="xpath"> + <datamodel> + <data id="Var1" expr="0"/> + </datamodel> + +<parallel id="p1"> + <onentry> + <send delay="2s" event="timeout"/> + </onentry> + + + <state id="s0"> + <transition cond="In('sh1')" target="fail"/> + <transition event="timeout" target="fail"/> + </state> + + +<state id="s1"> + <initial> + <transition target="sh1"/> + </initial> + + + <history id="sh1"> + <transition target="s11"/> + </history> + + <state id="s11"> + <transition cond="In('sh1')" target="fail"/> + <transition target="s12"/> + </state> + + <state id="s12"/> + <transition cond="In('sh1')" target="fail"/> + <transition cond="$Var1/text() ==0" target="sh1"/> + <transition cond="$Var1/text() ==1" target="pass"/> + <onexit> + <assign location="$Var1" expr="$Var1 + 1"/> + </onexit> + </state> + + + </parallel> + +<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final> +<final id="fail"><onentry><log label="Outcome" expr="'fail'"/></onentry></final> + +</scxml>
\ No newline at end of file |