summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md99
-rw-r--r--contrib/ctest/CTestCustom.ctest.in32
-rw-r--r--contrib/dom/idl/SCXMLEvent.idl2
-rw-r--r--src/bindings/swig/java/JavaDataModel.h12
-rw-r--r--src/bindings/swig/php/uscxmlNativePHP.php10
-rw-r--r--src/uscxml/Factory.cpp17
-rw-r--r--src/uscxml/Factory.h24
-rw-r--r--src/uscxml/Interpreter.cpp99
-rw-r--r--src/uscxml/Interpreter.h7
-rw-r--r--src/uscxml/Message.cpp62
-rw-r--r--src/uscxml/Message.h15
-rw-r--r--src/uscxml/URL.cpp4
-rw-r--r--src/uscxml/URL.h4
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp7
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp82
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h6
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp2
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h2
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp2
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/Storage.cpp2
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp53
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h6
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h4
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp2
-rw-r--r--src/uscxml/plugins/datamodel/null/NULLDataModel.h4
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp19
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h4
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp27
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.h4
-rw-r--r--src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp4
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp4
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp12
-rw-r--r--src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp3
-rw-r--r--src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp9
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp10
-rw-r--r--src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp1
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/samples/uscxml/test-markup-passing.scxml54
-rw-r--r--test/samples/uscxml/test-markup.xml6
-rw-r--r--test/samples/uscxml/test-scenegraph.scxml6
-rw-r--r--test/samples/w3c/ecma/test159.scxml4
-rw-r--r--test/samples/w3c/ecma/test191.scxml2
-rw-r--r--test/samples/w3c/ecma/test354.scxml52
-rw-r--r--test/samples/w3c/ecma/test415.scxml12
-rw-r--r--test/samples/w3c/ecma/test483.scxml27
-rw-r--r--test/samples/w3c/ecma/test513.scxml50
-rw-r--r--test/samples/w3c/ecma/test528.scxml3
-rw-r--r--test/samples/w3c/txml/test159.txml2
-rw-r--r--test/samples/w3c/txml/test191.txml2
-rw-r--r--test/samples/w3c/txml/test354.txml56
-rw-r--r--test/samples/w3c/txml/test415.txml15
-rw-r--r--test/samples/w3c/txml/test483.txml31
-rw-r--r--test/samples/w3c/txml/test513.txml54
-rw-r--r--test/samples/w3c/txml/test528.txml3
-rw-r--r--test/samples/w3c/xpath/test159.scxml2
-rw-r--r--test/samples/w3c/xpath/test191.scxml2
-rw-r--r--test/samples/w3c/xpath/test354.scxml52
-rw-r--r--test/samples/w3c/xpath/test415.scxml12
-rw-r--r--test/samples/w3c/xpath/test483.scxml27
-rw-r--r--test/samples/w3c/xpath/test513.scxml50
-rw-r--r--test/samples/w3c/xpath/test528.scxml3
-rw-r--r--test/src/test-arabica-xpath.cpp2
-rw-r--r--test/src/test-datamodel.cpp3
-rw-r--r--test/src/test-w3c.cpp5
64 files changed, 965 insertions, 230 deletions
diff --git a/README.md b/README.md
index 179f4f2..ec7d504 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,12 @@
# uSCXML ReadMe
-uSCXML is a SCXML interpreter written in C/C++. It is mostly feature-complete and
-[standards compliant](https://github.com/tklab-tud/uscxml#test-reports) to a large extend.
-It runs on <b>Linux</b>, <b>Windows</b> and <b>MacOSX</b>, each 32- as well as 64Bits.
-There are still a few rough edges, especially with the plugins and custom extensions.
-
-The latest release will also compile for <b>iOS</b> using the toolchain files in <tt>contrib/cmake/</tt>
-it features the (still experimental) JavaScriptCore ecmascript datamodel and no prolog datamodel. I will
-work on the Android version as soon as I have some time at my hands.
+uSCXML is a SCXML interpreter written in C/C++. It is mostly feature-complete and to a large extend
+[standards compliant](https://github.com/tklab-tud/uscxml#test-reports).
+It runs on <b>Linux</b>, <b>Windows</b> and <b>MacOSX</b>, each 32- as well as 64Bits as well as <b>iOS</b>.
+There are still a few rough edges though, especially with the plugins and custom extensions.
* <b>Datamodels</b>
- * Full [ECMAScript datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/ecmascript) using Google's v8 and JavaScriptCore (JSC is somewhat experimental)
+ * Full [ECMAScript datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/ecmascript) using Google's v8 (and JavaScriptCore on MacOSX and iOS)
* Full [NULL datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/null) with required <tt>In</tt> predicate
* Early [Prolog datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/prolog/swi) using SWI prolog
* Rudimentary support for [XPath datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/xpath)
@@ -35,13 +31,19 @@ work on the Android version as soon as I have some time at my hands.
* We continuously run the [W3C IRP tests](http://www.w3.org/Voice/2013/scxml-irp/) for SCXML.
* Have a look at the [result](http://uscxml.tk.informatik.tu-darmstadt.de/cdash/index.php?project=uscxml) for the various platforms.
- * The manual tests are [excluded](https://github.com/tklab-tud/uscxml/blob/master/contrib/ctest/CTestCustom.ctest.in).
+ * The manual and XPath specific tests are [excluded](https://github.com/tklab-tud/uscxml/blob/master/contrib/ctest/CTestCustom.ctest.in).
uSCXML still fails the following ecmascript tests:
<table>
<tr><th>Test#</th><th>Status</th><th>Description</th><th>Comment</th></tr>
<tr>
+ <td><tt><a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test159.scxml">159</a></tt></td>
+ <td><tt>Failed</tt></td>
+ <td>"If the processing of an element of executable content causes an error to be raised, the processor MUST NOT process the remaining elements of the block."</td>
+ <td>uSCXML continues processing the rest of the block as if there was no error.</td>
+ </tr>
+ <tr>
<td><tt><a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test301.scxml">301</a></tt></td>
<td><tt>Failed</tt></td>
<td>"the processor should reject this document because it can't download the script"</td>
@@ -60,6 +62,18 @@ uSCXML still fails the following ecmascript tests:
<td>"test that any attempt to change the value of a system variable causes error.execution to be raised"</td>
<td>Same issue as above: we allow writing to <tt>_event</tt>.</td>
</tr>
+ <tr>
+ <td>
+ <tt>
+ <a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test519.scxml">519</a>
+ <a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test520.scxml">520</a>
+ <a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test531.scxml">531</a>
+ <a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test534.scxml">534</a>
+ </tt></td>
+ <td><tt>Failed</tt></td>
+ <td></td>
+ <td>Tests contain non-standard ECMAScript.</td>
+ </tr>
</table>
## License
@@ -72,3 +86,68 @@ upon](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md#build-dep
We do not yet feature installers. Please download the source and have a look at the [build
instructions](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md).
+
+## Usage
+
+In order to use the interpreter, you need to <tt>#include "uscxml/Interpreter.h"</tt> and instantiate
+objects of <tt>uscxml::Interpreter</tt>.
+
+### Blocking Interpretation with SCXML from URL
+ Interpreter scxml = Interpreter::fromURL("http://www.example.com/fancy.scxml");
+ scxml.start(); // non-blocking
+
+There are some cases, i.e. with graphical invokers, where the main thread is <emph>required</emph> in order
+to react to UI events. You will have to deligate control flow from the main thread into the interpreter
+every now and then:
+
+ interpreter.runOnMainThread(25);
+
+This will perform a single iteration on the invoked components with a maximum of 25 frames per seconds
+or return immediately. You will have to call this method every now and then if you are using e.g. the
+<tt>scenegraph</tt> invoker.
+
+### Non-Blocking Interpretation with inline SCXML
+ Interpreter scxml = Interpreter::fromXML("<scxml><final id="exit"/></scxml>");
+ scxml.interpret(); // blocking
+
+### Callbacks for an Interpreter
+
+You can register an <tt>InterpreterMonitor</tt> prior to start in order to receive
+control-flow upon various events in the Interpreter.
+
+ class StatusMonitor : public uscxml::InterpreterMonitor {
+ void onStableConfiguration(Interpreter) {}
+ void beforeCompletion(Interpreter) {}
+ void afterCompletion(Interpreter) {}
+ void beforeMicroStep(Interpreter) {}
+ void beforeTakingTransitions(Interpreter, const Arabica::XPath::NodeSet<std::string>&) {}
+ void beforeEnteringStates(Interpreter, const Arabica::XPath::NodeSet<std::string>&) {}
+ void afterEnteringStates(Interpreter) {}
+ void beforeExitingStates(Interpreter, const Arabica::XPath::NodeSet<std::string>&) {}
+ void afterExitingStates(Interpreter) {}
+ };
+
+ StatusMonitor statMon;
+ Interpreter scxml = Interpreter::fromXML("<scxml><final id="exit"/></scxml>");
+ scxml.addMonitor(&statMon);
+ scxml.start();
+
+This will cause the interpreter to invoke the callbacks from the monitor whenever the corresponding
+internal phase is reached.
+
+## Extending uSCXML
+
+The uSCXML interpreter can be extended by introducing new
+
+ 1. DataModels as embedded scripting languages (e.g. ECMAScript, Prolog and XPath)
+ 2. Invokers to represent external components that deliver and accept events (e.g. iCal, SceneGraph, DirectoryMonitor)
+ 3. I/O-Processors to provide communication with external systems (e.g. BasicHTTP, SCXML).
+ 4. Elements for Executable Content (e.g. &lt;respond>, &lt;fetch>, &lt;postpone>).
+
+The basic approach to extend the interpreter is the same in all cases:
+
+ 1. Write a class inheriting the abstract base class (e.g. <tt>DataModelImpl</tt>, <tt>InvokerImpl</tt>, <tt>IOProcessorImpl</tt>, <tt>ExecutableContentImpl</tt>).
+ 2. Instantiate your class and register it as a prototype at the <tt>Factory</tt> via one of its static <tt>register*</tt> methods.
+ 1. You can register at the global Factory Singleton via <tt>Factory::register*(prototypeInstance)</tt>
+ 2. Or provide a new Factory instance to selected interpreters as an in-between.
+ 3. Write an interpreter using your new functionality.
diff --git a/contrib/ctest/CTestCustom.ctest.in b/contrib/ctest/CTestCustom.ctest.in
index 098e4e2..e263147 100644
--- a/contrib/ctest/CTestCustom.ctest.in
+++ b/contrib/ctest/CTestCustom.ctest.in
@@ -7,6 +7,7 @@
# grep -ori 'datamodel="null' .
# skip xpath datamodel tests
+# these are manual or xpath tests generated by the ecma generator
set(CTEST_CUSTOM_TESTS_IGNORE
"ecma/test178.scxml"
"ecma/test230.scxml"
@@ -14,6 +15,37 @@ set(CTEST_CUSTOM_TESTS_IGNORE
"ecma/test307.scxml"
"ecma/test313.scxml"
"ecma/test314.scxml"
+ "ecma/test415.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"
+
)
diff --git a/contrib/dom/idl/SCXMLEvent.idl b/contrib/dom/idl/SCXMLEvent.idl
index fbb7661..67f5070 100644
--- a/contrib/dom/idl/SCXMLEvent.idl
+++ b/contrib/dom/idl/SCXMLEvent.idl
@@ -7,7 +7,7 @@
const unsigned short EXTERNAL = 2;
const unsigned short PLATFORM = 3;
- [CustomGetter, EmptyAsNull] readonly attribute DOMString eventType;
+ [CustomGetter, EmptyAsNull] readonly attribute DOMString type;
readonly attribute DOMString name;
[EmptyAsNull] readonly attribute DOMString origin;
[EmptyAsNull] readonly attribute DOMString origintype;
diff --git a/src/bindings/swig/java/JavaDataModel.h b/src/bindings/swig/java/JavaDataModel.h
index 5d76480..ca503d1 100644
--- a/src/bindings/swig/java/JavaDataModel.h
+++ b/src/bindings/swig/java/JavaDataModel.h
@@ -62,7 +62,7 @@ public:
}
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
// convert XML back into strings
std::string location;
@@ -72,9 +72,9 @@ public:
std::ostringstream ssAssign;
ssAssign << assignElem;
std::string tmp;
- if (doc) {
+ if (node) {
std::ostringstream ssContent;
- ssContent << doc;
+ ssContent << node;
tmp = ssContent.str();
} else {
tmp = content;
@@ -89,7 +89,7 @@ public:
// this is assign the function exposed to java
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
// convert XML back into strings
std::string location;
@@ -100,9 +100,9 @@ public:
if (dataElem)
ssData << dataElem;
std::string tmp;
- if (doc) {
+ if (node) {
std::ostringstream ssContent;
- ssContent << doc;
+ ssContent << node;
tmp = ssContent.str();
} else {
tmp = content;
diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php
index 6e4823a..358975a 100644
--- a/src/bindings/swig/php/uscxmlNativePHP.php
+++ b/src/bindings/swig/php/uscxmlNativePHP.php
@@ -2,7 +2,7 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
+ * Version 2.0.9
*
* This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
@@ -423,14 +423,6 @@ class Event {
Event_setDOM($this->_cPtr,$dom);
}
- static function getFirstDOMElement($self_or_dom) {
- return Event_getFirstDOMElement($self_or_dom);
- }
-
- static function getStrippedDOM($self_or_dom) {
- return Event_getStrippedDOM($self_or_dom);
- }
-
function getRaw() {
return Event_getRaw($this->_cPtr);
}
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index bc23e53..1494dff 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -352,7 +352,9 @@ boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, I
if (_invokerAliases.find(type) != _invokerAliases.end()) {
std::string canonicalName = _invokerAliases[type];
if (_invokers.find(canonicalName) != _invokers.end()) {
- return _invokers[canonicalName]->create(interpreter);
+ boost::shared_ptr<InvokerImpl> invoker = _invokers[canonicalName]->create(interpreter);
+ invoker->setInterpreter(interpreter);
+ return invoker;
}
}
@@ -372,7 +374,9 @@ boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& typ
if (_dataModelAliases.find(type) != _dataModelAliases.end()) {
std::string canonicalName = _dataModelAliases[type];
if (_dataModels.find(canonicalName) != _dataModels.end()) {
- return _dataModels[canonicalName]->create(interpreter);
+ boost::shared_ptr<DataModelImpl> dataModel = _dataModels[canonicalName]->create(interpreter);
+ dataModel->setInterpreter(interpreter);
+ return dataModel;
}
}
@@ -391,7 +395,9 @@ boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string&
if (_ioProcessorAliases.find(type) != _ioProcessorAliases.end()) {
std::string canonicalName = _ioProcessorAliases[type];
if (_ioProcessors.find(canonicalName) != _ioProcessors.end()) {
- return _ioProcessors[canonicalName]->create(interpreter);
+ boost::shared_ptr<IOProcessorImpl> ioProc = _ioProcessors[canonicalName]->create(interpreter);
+ ioProc->setInterpreter(interpreter);
+ return ioProc;
}
}
@@ -399,7 +405,7 @@ boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string&
if (_parentFactory) {
return _parentFactory->createIOProcessor(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " Datamodel known";
+ LOG(ERROR) << "No " << type << " IOProcessor known";
}
return boost::shared_ptr<IOProcessorImpl>();
@@ -409,7 +415,8 @@ boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const
// do we have this type in this factory?
std::string actualNameSpace = (nameSpace.length() == 0 ? "http://www.w3.org/2005/07/scxml" : nameSpace);
if (_executableContent.find(std::make_pair(localName, actualNameSpace)) != _executableContent.end()) {
- return _executableContent[std::make_pair(localName, actualNameSpace)]->create(interpreter);
+ boost::shared_ptr<ExecutableContentImpl> execContent = _executableContent[std::make_pair(localName, actualNameSpace)]->create(interpreter);
+ execContent->setInterpreter(interpreter);
}
// lookup in parent factory
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index 0432f34..b815712 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -52,7 +52,9 @@ public:
}
virtual std::string getLocalName() = 0; ///< The name of the element.
- virtual std::string getNamespace() = 0; ///< The namespace of the element.
+ virtual std::string getNamespace() {
+ return "http://www.w3.org/2005/07/scxml"; ///< The namespace of the element.
+ }
virtual void enterElement(const Arabica::DOM::Node<std::string>& node) = 0; ///< Invoked when entering the element as part of evaluating executable content.
virtual void exitElement(const Arabica::DOM::Node<std::string>& node) = 0; ///< Invoked when exiting the element as part of evaluating executable content.
virtual bool processChildren() = 0; ///< Whether or not the interpreter should process this elements children.
@@ -283,15 +285,19 @@ public:
virtual bool isDeclared(const std::string& expr) = 0;
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) = 0;
virtual void assign(const std::string& location, const Data& data) = 0;
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) = 0;
virtual void init(const std::string& location, const Data& data) = 0;
+ virtual void setInterpreter(InterpreterImpl* interpreter) {
+ _interpreter = interpreter;
+ }
+
// we need it public for various static functions
InterpreterImpl* _interpreter;
};
@@ -358,18 +364,18 @@ public:
}
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
- return _impl->assign(assignElem, doc, content);
+ return _impl->assign(assignElem, node, content);
}
virtual void assign(const std::string& location, const Data& data) {
return _impl->assign(location, data);
}
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
- return _impl->init(dataElem, doc, content);
+ return _impl->init(dataElem, node, content);
}
virtual void init(const std::string& location, const Data& data) {
return _impl->init(location, data);
@@ -383,6 +389,10 @@ public:
return _impl->replaceExpressions(content);
}
+ virtual void setInterpreter(InterpreterImpl* interpreter) {
+ _impl->setInterpreter(interpreter);
+ }
+
protected:
boost::shared_ptr<DataModelImpl> _impl;
};
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 6b17d94..4015026 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -174,7 +174,7 @@ void InterpreterImpl::setNameSpaceInfo(const std::map<std::string, std::string>
if (boost::iequals(uri, "http://www.w3.org/2005/07/scxml")) {
_nsURL = uri;
if (prefix.size() == 0) {
- LOG(INFO) << "Mapped default namespace to 'scxml:'";
+// LOG(INFO) << "Mapped default namespace to 'scxml:'";
_xpathPrefix = "scxml:";
_nsContext.addNamespaceDeclaration(uri, "scxml");
_nsToPrefix[uri] = "scxml";
@@ -203,11 +203,12 @@ void InterpreterImpl::setName(const std::string& name) {
InterpreterImpl::~InterpreterImpl() {
_running = false;
- tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+// tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
if (_thread) {
// unblock event queue
Event event;
- _externalQueue.push(event);
+ event.name = "unblock.and.die";
+ receive(event);
_thread->join();
delete(_thread);
}
@@ -327,7 +328,7 @@ void InterpreterImpl::initializeData(const Element<std::string>& data) {
}
try {
- Arabica::DOM::Document<std::string> dom;
+ Arabica::DOM::Node<std::string> dom;
std::string text;
processDOMorText(data, dom, text);
_dataModel.init(data, dom, text);
@@ -401,6 +402,7 @@ void InterpreterImpl::normalize(Arabica::DOM::Element<std::string>& scxml) {
void InterpreterImpl::receiveInternal(const Event& event) {
std::cout << _name << " receiveInternal: " << event.name << std::endl;
_internalQueue.push_back(event);
+// _condVar.notify_all();
}
void InterpreterImpl::receive(const Event& event, bool toFront) {
@@ -410,6 +412,7 @@ void InterpreterImpl::receive(const Event& event, bool toFront) {
} else {
_externalQueue.push(event);
}
+ _condVar.notify_all();
}
void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node<std::string>& state) {
@@ -448,7 +451,7 @@ void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node<std::string>& st
}
void InterpreterImpl::processContentElement(const Arabica::DOM::Node<std::string>& content,
- Arabica::DOM::Document<std::string>& dom,
+ Arabica::DOM::Node<std::string>& dom,
std::string& text,
std::string& expr) {
if (HAS_ATTR(content, "expr")) {
@@ -460,16 +463,16 @@ void InterpreterImpl::processContentElement(const Arabica::DOM::Node<std::string
}
}
-void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& node,
- Arabica::DOM::Document<std::string>& dom,
+void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& element,
+ Arabica::DOM::Node<std::string>& dom,
std::string& text) {
// do we need to download?
- if (HAS_ATTR(node, "src") ||
- (HAS_ATTR(node, "srcexpr") && _dataModel)) {
+ if (HAS_ATTR(element, "src") ||
+ (HAS_ATTR(element, "srcexpr") && _dataModel)) {
std::stringstream srcContent;
- URL sourceURL(HAS_ATTR(node, "srcexpr") ? _dataModel.evalAsString(ATTR(node, "srcexpr")) : ATTR(node, "src"));
+ URL sourceURL(HAS_ATTR(element, "srcexpr") ? _dataModel.evalAsString(ATTR(element, "srcexpr")) : ATTR(element, "src"));
if (!sourceURL.toAbsolute(_baseURI)) {
- LOG(ERROR) << LOCALNAME(node) << " element has relative src or srcexpr URI with no baseURI set.";
+ LOG(ERROR) << LOCALNAME(element) << " element has relative src or srcexpr URI with no baseURI set.";
return;
}
if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end() && false) {
@@ -477,14 +480,14 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
} else {
srcContent << sourceURL;
if (sourceURL.downloadFailed()) {
- LOG(ERROR) << LOCALNAME(node) << " source cannot be downloaded";
+ LOG(ERROR) << LOCALNAME(element) << " source cannot be downloaded";
return;
}
_cachedURLs[sourceURL.asString()] = sourceURL;
}
if (srcContent.str().length() > 0) {
// try to parse as XML
- Arabica::SAX2DOM::Parser<std::string> parser;
+ NameSpacingParser parser;
std::stringstream* ss = new std::stringstream();
(*ss) << srcContent.str();
std::auto_ptr<std::istream> ssPtr(ss);
@@ -494,45 +497,68 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
// parser.setFeature(Arabica::SAX::FeatureNames<std::string>().external_general, true);
if (parser.parse(inputSource) && parser.getDocument()) {
- dom = parser.getDocument();
- //std::cout << dom;
- Node<std::string> content = dom.getDocumentElement();
+ Document<std::string> doc = parser.getDocument();
+ dom = doc.getDocumentElement();
+#if 0
+ Node<std::string> content = doc.getDocumentElement();
assert(content.getNodeType() == Node_base::ELEMENT_NODE);
- Node<std::string> container = dom.createElement("container");
+ Node<std::string> container = doc.createElement("container");
dom.replaceChild(container, content);
container.appendChild(content);
// std::cout << dom << std::endl;
+#endif
return;
} else {
+ if (parser.errorsReported()) {
+ LOG(ERROR) << parser.errors();
+ }
text = srcContent.str();
return;
}
}
}
- if (!node.hasChildNodes())
+ if (!element.hasChildNodes())
return;
- Node<std::string> child = node.getFirstChild();
- while(child) {
- if (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE) {
+ /**
+ * Figure out whether the given element contains text, has one child or many childs
+ */
+ bool hasTextContent = false;
+ bool hasOneChild = false;
+ Node<std::string> theOneChild;
+ bool hasManyChilds = false;
+
+ Node<std::string> child = element.getFirstChild();
+ while (child) {
+// std::cout << child.getNodeType() << std::endl;
+ if (child.getNodeType() == Node_base::TEXT_NODE ||
+ child.getNodeType() == Node_base::CDATA_SECTION_NODE) {
std::string trimmed = child.getNodeValue();
boost::trim(trimmed);
- if (trimmed.length() > 0)
+ if (trimmed.length() > 0) {
+ hasTextContent = true;
+ }
+ } else {
+ if (hasOneChild) {
+ hasManyChilds = true;
+ hasOneChild = false;
break;
- }
- if (child.getNodeType() == Node_base::ELEMENT_NODE) {
- break;
+ }
+ hasOneChild = true;
+ theOneChild = child;
}
child = child.getNextSibling();
}
- if (child && child.getNodeType() == Node_base::ELEMENT_NODE) {
- DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- dom = domFactory.createDocument(child.getNamespaceURI(), "", 0);
- // we need to import the parent - to support xpath test150
- Node<std::string> newNode = dom.importNode(child.getParentNode(), true);
- dom.appendChild(newNode);
- } else if(child && (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE)) {
+
+ if (hasOneChild) {
+ // if we have a single child, it will be the content of the dom
+ dom = theOneChild;
+ } else if (hasManyChilds) {
+ // if we have multiple childs
+ dom = element;
+ } else if(hasTextContent) {
+ child = element.getFirstChild();
while(child) {
if ((child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE)) {
text += child.getNodeValue();
@@ -540,7 +566,7 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
child = child.getNextSibling();
}
} else {
- LOG(ERROR) << LOCALNAME(node) << " has neither text nor element children.";
+ LOG(ERROR) << LOCALNAME(element) << " has neither text nor element children.";
}
}
@@ -1123,7 +1149,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl;
throw Event("error.execution", Event::PLATFORM);
} else {
- Document<std::string> dom;
+ Node<std::string> dom;
std::string text;
processDOMorText(content, dom, text);
_dataModel.assign(Element<std::string>(content), dom, text);
@@ -1188,7 +1214,10 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
}
} else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "send")) {
// --- SEND --------------------------
- send(content);
+ try {
+ send(content);
+ }
+ CATCH_AND_DISTRIBUTE("Error while sending content")
} else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "cancel")) {
// --- CANCEL --------------------------
std::string sendId;
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index f8cf823..d2c9025 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -251,6 +251,7 @@ protected:
bool _stable;
tthread::thread* _thread;
tthread::recursive_mutex _mutex;
+ tthread::condition_variable _condVar;
tthread::recursive_mutex _pluginMutex;
URL _baseURI;
@@ -291,13 +292,13 @@ protected:
void executeContent(const Arabica::XPath::NodeSet<std::string>& content, bool rethrow = false);
void processContentElement(const Arabica::DOM::Node<std::string>& element,
- Arabica::DOM::Document<std::string>& dom,
+ Arabica::DOM::Node<std::string>& dom,
std::string& text,
std::string& expr);
void processParamChilds(const Arabica::DOM::Node<std::string>& element,
std::multimap<std::string, std::string>& params);
- void processDOMorText(const Arabica::DOM::Node<std::string>& node,
- Arabica::DOM::Document<std::string>& dom,
+ void processDOMorText(const Arabica::DOM::Node<std::string>& element,
+ Arabica::DOM::Node<std::string>& dom,
std::string& text);
void send(const Arabica::DOM::Node<std::string>& element);
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index ddb8996..f3f8c27 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -110,37 +110,37 @@ Arabica::DOM::Document<std::string> Data::toDocument() {
return document;
}
-Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const {
- return getFirstDOMElement(dom);
-}
-
-Arabica::DOM::Document<std::string> Event::getStrippedDOM() const {
- return getStrippedDOM(dom);
-}
-
-Arabica::DOM::Node<std::string> Event::getFirstDOMElement(const Arabica::DOM::Document<std::string> dom) {
- Arabica::DOM::Node<std::string> data = dom.getDocumentElement().getFirstChild();
- while (data) {
- if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) {
- std::string trimmed = boost::trim_copy(data.getNodeValue());
- if (trimmed.length() == 0) {
- data = data.getNextSibling();
- continue;
- }
- }
- break;
- }
- return data;
-}
-
-Arabica::DOM::Document<std::string> Event::getStrippedDOM(const Arabica::DOM::Document<std::string> dom) {
- Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- Arabica::DOM::Document<std::string> document = domFactory.createDocument("", "", 0);
- if (dom) {
- document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true));
- }
- return document;
-}
+//Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const {
+// return getFirstDOMElement(dom);
+//}
+//
+//Arabica::DOM::Document<std::string> Event::getStrippedDOM() const {
+// return getStrippedDOM(dom);
+//}
+
+//Arabica::DOM::Node<std::string> Event::getFirstDOMElement(const Arabica::DOM::Document<std::string> dom) {
+// Arabica::DOM::Node<std::string> data = dom.getDocumentElement().getFirstChild();
+// while (data) {
+// if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) {
+// std::string trimmed = boost::trim_copy(data.getNodeValue());
+// if (trimmed.length() == 0) {
+// data = data.getNextSibling();
+// continue;
+// }
+// }
+// break;
+// }
+// return data;
+//}
+//
+//Arabica::DOM::Document<std::string> Event::getStrippedDOM(const Arabica::DOM::Document<std::string> dom) {
+// Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+// Arabica::DOM::Document<std::string> document = domFactory.createDocument("", "", 0);
+// if (dom) {
+// document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true));
+// }
+// return document;
+//}
Arabica::DOM::Document<std::string> Event::toDocument() {
Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index 1e7a7ca..afc536f 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -158,17 +158,18 @@ public:
this->origintype = originType;
}
- Arabica::DOM::Document<std::string> getDOM() {
+ Arabica::DOM::Node<std::string> getDOM() {
return dom;
}
- void setDOM(const Arabica::DOM::Document<std::string>& dom) {
+ void setDOM(const Arabica::DOM::Node<std::string>& dom) {
this->dom = dom;
}
- Arabica::DOM::Node<std::string> getFirstDOMElement() const;
- Arabica::DOM::Document<std::string> getStrippedDOM() const;
- static Arabica::DOM::Node<std::string> getFirstDOMElement(const Arabica::DOM::Document<std::string> dom);
- static Arabica::DOM::Document<std::string> getStrippedDOM(const Arabica::DOM::Document<std::string> dom);
+// Arabica::DOM::Node<std::string> getFirstDOMElement() const;
+// Arabica::DOM::Document<std::string> getStrippedDOM() const;
+//
+// static Arabica::DOM::Node<std::string> getFirstDOMElement(const Arabica::DOM::Document<std::string> dom);
+// static Arabica::DOM::Document<std::string> getStrippedDOM(const Arabica::DOM::Document<std::string> dom);
std::string getRaw() {
return raw;
@@ -239,7 +240,7 @@ protected:
Type eventType;
std::string origin;
std::string origintype;
- Arabica::DOM::Document<std::string> dom;
+ Arabica::DOM::Node<std::string> dom;
std::string sendid;
bool hideSendId;
std::string invokeid;
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index 4d60999..cefe935d 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -103,7 +103,7 @@ URLImpl::~URLImpl() {
curl_easy_cleanup(_handle);
}
-URLImpl::operator Data() {
+URLImpl::operator Data() const {
Data data;
data.compound["url"] = Data(asString(), Data::VERBATIM);
data.compound["host"] = Data(_uri.host(), Data::VERBATIM);
@@ -117,7 +117,7 @@ URLImpl::operator Data() {
data.compound["statusMsg"] = Data(_statusMsg, Data::VERBATIM);
- std::vector<std::string>::iterator pathIter = _pathComponents.begin();
+ std::vector<std::string>::const_iterator pathIter = _pathComponents.begin();
while(pathIter != _pathComponents.end()) {
data.compound["pathComponent"].array.push_back(Data(*pathIter, Data::VERBATIM));
pathIter++;
diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h
index 3acd462..16c29c7 100644
--- a/src/uscxml/URL.h
+++ b/src/uscxml/URL.h
@@ -95,7 +95,7 @@ public:
bool downloadFailed() {
return _hasFailed;
}
- operator Data();
+ operator Data() const;
friend class URLFetcher;
@@ -249,7 +249,7 @@ public:
friend class URLFetcher;
friend std::ostream & operator<<(std::ostream &stream, const URL& p);
- operator Data() {
+ operator Data() const {
return _impl->operator Data();
}
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index 881fa8b..e044fcf 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -9,7 +9,6 @@ using namespace Arabica::DOM;
// see: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation
void InterpreterDraft6::interpret() {
-// _mutex.lock();
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
if (!_isInitialized)
init();
@@ -264,7 +263,11 @@ void InterpreterDraft6::mainEventLoop() {
while(_externalQueue.isEmpty() && _thread == NULL) {
runOnMainThread(200);
}
+ _mutex.lock();
+ while(_externalQueue.isEmpty()) {
+ _condVar.wait(_mutex);
+ }
_currEvent = _externalQueue.pop();
#if VERBOSE
std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
@@ -273,8 +276,6 @@ void InterpreterDraft6::mainEventLoop() {
if (!_running)
goto EXIT_INTERPRETER;
- _mutex.lock();
-
if (_dataModel && boost::iequals(_currEvent.name, "cancel.invoke." + _sessionId))
break;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 712799c..c714735 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -3,6 +3,9 @@
#include "JSCDataModel.h"
#include "JSCDOM.h"
#include "dom/JSCDocument.h"
+#include "dom/JSCElement.h"
+#include "dom/JSCText.h"
+#include "dom/JSCCDATASection.h"
#include "dom/JSCSCXMLEvent.h"
#include "uscxml/Message.h"
@@ -12,6 +15,13 @@
#include <Pluma/Connector.hpp>
#endif
+#define TO_JSC_DOMVALUE(type) \
+struct JSC##type::JSC##type##Private* privData = new JSC##type::JSC##type##Private(); \
+privData->dom = _dom; \
+privData->nativeObj = new type<std::string>(node); \
+JSObjectRef retObj = JSObjectMake(_ctx, JSC##type::getTmpl(), privData);\
+return retObj;
+
namespace uscxml {
using namespace Arabica::XPath;
@@ -96,24 +106,24 @@ boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpret
JSClassRef jsInvokerClassRef = JSClassCreate(&jsInvokersClassDef);
JSObjectRef jsInvoker = JSObjectMake(dm->_ctx, jsInvokerClassRef, dm.get());
JSStringRef invokerName = JSStringCreateWithUTF8CString("_invokers");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(invokerName);
JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef);
JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get());
JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(ioProcName);
JSStringRef nameName = JSStringCreateWithUTF8CString("_name");
JSStringRef name = JSStringCreateWithUTF8CString(dm->_interpreter->getName().c_str());
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(nameName);
JSStringRelease(name);
JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid");
JSStringRef sessionId = JSStringCreateWithUTF8CString(dm->_interpreter->getSessionId().c_str());
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(sessionIdName);
JSStringRelease(sessionId);
@@ -153,7 +163,7 @@ void JSCDataModel::setEvent(const Event& event) {
if (event.dom) {
JSStringRef propName = JSStringCreateWithUTF8CString("data");
- JSObjectSetProperty(_ctx, eventObj, propName, getDocumentAsValue(event.dom), 0, &exception);
+ JSObjectSetProperty(_ctx, eventObj, propName, getNodeAsValue(event.dom), 0, &exception);
JSStringRelease(propName);
if (exception)
handleException(exception);
@@ -342,8 +352,19 @@ bool JSCDataModel::validate(const std::string& location, const std::string& sche
}
uint32_t JSCDataModel::getLength(const std::string& expr) {
-// LOG(ERROR) << "I am not sure whether getLength() works :(";
- JSValueRef result = evalAsValue("(" + expr + ").length");
+ JSValueRef result;
+
+ result = evalAsValue("(" + expr + ").length");
+ JSType type = JSValueGetType(_ctx, result);
+ if (type == kJSTypeNull || type == kJSTypeUndefined) {
+ Event exceptionEvent;
+ exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);
+ exceptionEvent.name = "error.execution";
+ exceptionEvent.eventType = Event::PLATFORM;
+
+ throw(exceptionEvent);
+ }
+
JSValueRef exception = NULL;
double length = JSValueToNumber(_ctx, result, &exception);
if (exception)
@@ -424,7 +445,7 @@ JSValueRef JSCDataModel::evalAsValue(const std::string& expr, bool dontThrow) {
}
void JSCDataModel::assign(const Element<std::string>& assignElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
std::string key;
JSValueRef exception = NULL;
@@ -436,10 +457,20 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
if (key.length() == 0)
throw Event("error.execution", Event::PLATFORM);
+ // flags on attribute are ignored?
+ if (key.compare("_sessionid") == 0)
+ throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_name") == 0)
+ throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_ioprocessors") == 0)
+ throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_invokers") == 0)
+ throw Event("error.execution", Event::PLATFORM);
+
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
- } else if (doc) {
- JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), getDocumentAsValue(doc), 0, &exception);
+ } else if (node) {
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), getNodeAsValue(node), 0, &exception);
if (exception)
handleException(exception);
} else if (content.size() > 0) {
@@ -455,15 +486,24 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
}
}
-JSValueRef JSCDataModel::getDocumentAsValue(const Document<std::string>& doc) {
-
- struct JSCDocument::JSCDocumentPrivate* retPrivData = new JSCDocument::JSCDocumentPrivate();
- retPrivData->dom = _dom;
- retPrivData->nativeObj = new Document<std::string>(doc);
-
- JSObjectRef retObj = JSObjectMake(_ctx, JSCDocument::getTmpl(), retPrivData);
-
- return retObj;
+JSValueRef JSCDataModel::getNodeAsValue(const Node<std::string>& node) {
+ switch (node.getNodeType()) {
+ case Node_base::ELEMENT_NODE: {
+ TO_JSC_DOMVALUE(Element);
+ }
+ case Node_base::TEXT_NODE: {
+ TO_JSC_DOMVALUE(Text);
+ }
+ case Node_base::CDATA_SECTION_NODE: {
+ TO_JSC_DOMVALUE(CDATASection);
+ }
+ case Node_base::DOCUMENT_NODE: {
+ TO_JSC_DOMVALUE(Document);
+ }
+ default: {
+ TO_JSC_DOMVALUE(Node);
+ }
+ }
}
void JSCDataModel::assign(const std::string& location, const Data& data) {
@@ -473,10 +513,10 @@ void JSCDataModel::assign(const std::string& location, const Data& data) {
}
void JSCDataModel::init(const Element<std::string>& dataElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
try {
- assign(dataElem, doc, content);
+ assign(dataElem, node, content);
} catch (Event e) {
// test 277
std::string key;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
index f7360d4..9bb3034 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
@@ -50,12 +50,12 @@ public:
virtual bool isDeclared(const std::string& expr);
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void assign(const std::string& location, const Data& data);
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void init(const std::string& location, const Data& data);
@@ -77,7 +77,7 @@ protected:
static JSValueRef jsInvokerGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
static void jsInvokerListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames);
- JSValueRef getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc);
+ JSValueRef getNodeAsValue(const Arabica::DOM::Node<std::string>& node);
JSValueRef getDataAsValue(const Data& data);
Data getValueAsData(const JSValueRef value);
JSValueRef evalAsValue(const std::string& expr, bool dontThrow = false);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp
index 579012b..de3a93f 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp
@@ -7,7 +7,7 @@ namespace DOM {
JSClassRef JSCSCXMLEvent::Tmpl;
JSStaticValue JSCSCXMLEvent::staticValues[] = {
- { "eventType", eventTypeCustomAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { "type", typeCustomAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "name", nameAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "origin", originAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "origintype", origintypeAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h
index d3a25d5..5ac8ccb 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h
@@ -39,7 +39,7 @@ public:
JSC_DESTRUCTOR(JSCSCXMLEventPrivate);
- static JSValueRef eventTypeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
+ static JSValueRef typeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
static JSValueRef nameAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
static JSValueRef originAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
static JSValueRef origintypeAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp
index 0209467..e197796 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp
@@ -3,7 +3,7 @@
namespace Arabica {
namespace DOM {
-JSValueRef JSCSCXMLEvent::eventTypeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception) {
+JSValueRef JSCSCXMLEvent::typeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception) {
struct JSCSCXMLEventPrivate* privData = (struct JSCSCXMLEventPrivate*)JSObjectGetPrivate(thisObj);
JSStringRef stringRef;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp b/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp
index 9131784..b5bb474 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp
@@ -5,7 +5,7 @@ namespace uscxml {
Storage::Storage(const std::string& filename) {
_filename = filename;
- std::cout << _filename << std::endl;
+// std::cout << _filename << std::endl;
std::fstream file;
file.open(_filename.c_str(), std::ios_base::in);
// read content into data
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index 017b2eb..ea112f1 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -4,6 +4,9 @@
#include "V8DOM.h"
#include "dom/V8Document.h"
#include "dom/V8Node.h"
+#include "dom/V8Element.h"
+#include "dom/V8Text.h"
+#include "dom/V8CDATASection.h"
#include "dom/V8SCXMLEvent.h"
#include "uscxml/Message.h"
@@ -13,6 +16,17 @@
#include <Pluma/Connector.hpp>
#endif
+#define TO_V8_DOMVALUE(type) \
+v8::Handle<v8::Function> retCtor = V8##type::getTmpl()->GetFunction();\
+v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());\
+struct V8##type::V8##type##Private* retPrivData = new V8##type::V8##type##Private();\
+retPrivData->dom = _dom;\
+retPrivData->nativeObj = new type<std::string>(node);\
+retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));\
+retObj.MakeWeak(0, V8##type::jsDestructor);\
+return retObj;
+
+
namespace uscxml {
using namespace Arabica::XPath;
@@ -152,7 +166,7 @@ void V8DataModel::setEvent(const Event& event) {
eventObj.MakeWeak(0, V8SCXMLEvent::jsDestructor);
if (event.dom) {
- eventObj->Set(v8::String::New("data"), getDocumentAsValue(event.dom));
+ eventObj->Set(v8::String::New("data"), getNodeAsValue(event.dom));
} else if (event.content.length() > 0) {
// _event.data is a string or JSON
Data json = Data::fromJSON(event.content);
@@ -268,18 +282,26 @@ Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value, std::set<v8
return data;
}
-v8::Handle<v8::Value> V8DataModel::getDocumentAsValue(const Document<std::string>& doc) {
- v8::Handle<v8::Function> retCtor = V8Document::getTmpl()->GetFunction();
- v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());
-
- struct V8Document::V8DocumentPrivate* retPrivData = new V8Document::V8DocumentPrivate();
- retPrivData->dom = _dom;
- retPrivData->nativeObj = new Document<std::string>(doc);
+v8::Handle<v8::Value> V8DataModel::getNodeAsValue(const Node<std::string>& node) {
- retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
- retObj.MakeWeak(0, V8Document::jsDestructor);
+ switch (node.getNodeType()) {
+ case Node_base::ELEMENT_NODE: {
+ TO_V8_DOMVALUE(Element);
+ }
+ case Node_base::TEXT_NODE: {
+ TO_V8_DOMVALUE(Text);
+ }
+ case Node_base::CDATA_SECTION_NODE: {
+ TO_V8_DOMVALUE(CDATASection);
+ }
+ case Node_base::DOCUMENT_NODE: {
+ TO_V8_DOMVALUE(Document);
+ }
+ default: {
+ TO_V8_DOMVALUE(Node);
+ }
+ }
- return retObj;
}
v8::Handle<v8::Value> V8DataModel::getDataAsValue(const Data& data) {
@@ -459,7 +481,7 @@ double V8DataModel::evalAsNumber(const std::string& expr) {
}
void V8DataModel::assign(const Element<std::string>& assignElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
v8::Locker locker;
v8::HandleScope handleScope;
@@ -477,8 +499,8 @@ void V8DataModel::assign(const Element<std::string>& assignElem,
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
- } else if (doc) {
- global->Set(v8::String::New(key.c_str()), getDocumentAsValue(doc));
+ } else if (node) {
+ global->Set(v8::String::New(key.c_str()), getNodeAsValue(node));
} else if (content.size() > 0) {
try {
evalAsValue(key + " = " + content);
@@ -502,7 +524,7 @@ void V8DataModel::assign(const std::string& location,
}
void V8DataModel::init(const Element<std::string>& dataElem,
- const Document<std::string>& doc,
+ const Node<std::string>& doc,
const std::string& content) {
try {
assign(dataElem, doc, content);
@@ -536,7 +558,6 @@ void V8DataModel::init(const std::string& location,
evalAsValue(location + " = undefined", true);
throw e;
}
-
}
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
index 9d17093..0dffa27 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
@@ -50,13 +50,13 @@ public:
virtual void eval(const Arabica::DOM::Element<std::string>& scriptElem,
const std::string& expr);
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void assign(const std::string& location,
const Data& data);
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void init(const std::string& location,
const Data& data);
@@ -87,7 +87,7 @@ protected:
v8::Handle<v8::Value> evalAsValue(const std::string& expr, bool dontThrow = false);
v8::Handle<v8::Value> getDataAsValue(const Data& data);
- v8::Handle<v8::Value> getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc);
+ v8::Handle<v8::Value> getNodeAsValue(const Arabica::DOM::Node<std::string>& node);
void throwExceptionEvent(const v8::TryCatch& tryCatch);
};
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h
index 3c5e6ee..9cc4ad4 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h
@@ -41,7 +41,7 @@ public:
static bool hasInstance(v8::Handle<v8::Value>);
- static v8::Handle<v8::Value> eventTypeCustomAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
+ static v8::Handle<v8::Value> typeCustomAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> nameAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> originAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> origintypeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
@@ -63,7 +63,7 @@ public:
instance->SetInternalFieldCount(1);
- instance->SetAccessor(v8::String::NewSymbol("eventType"), V8SCXMLEvent::eventTypeCustomAttrGetter, 0,
+ instance->SetAccessor(v8::String::NewSymbol("type"), V8SCXMLEvent::typeCustomAttrGetter, 0,
v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
instance->SetAccessor(v8::String::NewSymbol("name"), V8SCXMLEvent::nameAttrGetter, 0,
v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp
index d02a4cb..a8870cc 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp
@@ -3,7 +3,7 @@
namespace Arabica {
namespace DOM {
-v8::Handle<v8::Value> V8SCXMLEvent::eventTypeCustomAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+v8::Handle<v8::Value> V8SCXMLEvent::typeCustomAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
v8::Local<v8::Object> self = info.Holder();
V8SCXMLEventPrivate* privData = V8DOM::toClassPtr<V8SCXMLEventPrivate >(self->GetInternalField(0));
diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.h b/src/uscxml/plugins/datamodel/null/NULLDataModel.h
index b86c01c..74d170f 100644
--- a/src/uscxml/plugins/datamodel/null/NULLDataModel.h
+++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.h
@@ -42,12 +42,12 @@ public:
virtual void popContext();
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {}
virtual void assign(const std::string& location, const Data& data) {}
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content) {}
virtual void init(const std::string& location, const Data& data) {}
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
index a72fc6c..07cba96 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
@@ -223,7 +223,8 @@ void SWIDataModel::setEvent(const Event& event) {
if (event.dom) {
std::stringstream dataInitStr;
std::stringstream xmlDoc;
- xmlDoc << event.getFirstDOMElement();
+// xmlDoc << event.getFirstDOMElement();
+ xmlDoc << event.dom;
domUrl = URL::toLocalFile(xmlDoc.str(), ".pl");
dataInitStr << "load_xml_file('" << domUrl.asLocalFile(".pl") << "', XML), copy_term(XML,DATA), assert(event(data(DATA)))";
PlCall(dataInitStr.str().c_str());
@@ -408,7 +409,7 @@ std::map<std::string, PlTerm> SWIDataModel::resolveAtoms(PlTerm& term, PlTerm& o
}
void SWIDataModel::assign(const Element<std::string>& assignElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
SET_PL_CONTEXT
std::string expr = content;
@@ -435,15 +436,15 @@ void SWIDataModel::assign(const Element<std::string>& assignElem,
URL domUrl;
Data json;
- if (!doc)
+ if (!node)
json = Data::fromJSON(expr);
- if (doc) {
+ if (node) {
std::stringstream dataInitStr;
std::stringstream xmlDoc;
- Node<std::string> node = Event::getFirstDOMElement(doc);
+ Node<std::string> child = node;
while(node) {
- xmlDoc << node;
- node = node.getNextSibling();
+ xmlDoc << child;
+ child = node.getNextSibling();
}
domUrl = URL::toLocalFile(xmlDoc.str(), ".pl");
if (boost::iequals(type, "retract"))
@@ -488,9 +489,9 @@ void SWIDataModel::assign(const std::string& location, const Data& data) {
}
void SWIDataModel::init(const Element<std::string>& dataElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
- assign(dataElem, doc, content);
+ assign(dataElem, node, content);
}
void SWIDataModel::init(const std::string& location, const Data& data) {
assign(location, data);
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h
index 123e938..0a26643 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h
@@ -42,12 +42,12 @@ public:
virtual void popContext();
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void assign(const std::string& location, const Data& data);
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void init(const std::string& location, const Data& data);
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
index 842c560..cb40890 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
@@ -174,7 +174,8 @@ void XPathDataModel::setEvent(const Event& event) {
eventDataElem.appendChild(textNode);
}
if (event.dom) {
- Node<std::string> importedNode = _doc.importNode(event.getFirstDOMElement(), true);
+// Node<std::string> importedNode = _doc.importNode(event.getFirstDOMElement(), true);
+ Node<std::string> importedNode = _doc.importNode(event.dom, true);
eventDataElem.appendChild(importedNode);
}
@@ -370,7 +371,7 @@ double XPathDataModel::evalAsNumber(const std::string& expr) {
}
void XPathDataModel::assign(const Element<std::string>& assignElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
std::string location;
if (HAS_ATTR(assignElem, "id")) {
@@ -399,9 +400,9 @@ void XPathDataModel::assign(const Element<std::string>& assignElem,
}
#endif
NodeSet<std::string> nodeSet;
- if (doc) {
- if (doc.getDocumentElement()) {
- Node<std::string> data = doc.getDocumentElement().getFirstChild();
+ if (node) {
+ if (node) {
+ Node<std::string> data = node;
while (data) {
// do not add empty text as a node
if (data.getNodeType() == Node_base::TEXT_NODE) {
@@ -447,7 +448,7 @@ NodeSet<std::string> XPathDataModel::dataToNodeSet(const Data& data) {
}
void XPathDataModel::init(const Element<std::string>& dataElem,
- const Document<std::string>& doc,
+ const Node<std::string>& node,
const std::string& content) {
std::string location;
if (HAS_ATTR(dataElem, "id")) {
@@ -458,9 +459,9 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
Element<std::string> container = _doc.createElement("data");
container.setAttribute("id", location);
- if (doc) {
- if (doc.getDocumentElement()) {
- Node<std::string> data = doc.getDocumentElement().getFirstChild();
+ if (node) {
+ if (node) {
+ Node<std::string> data = node;
while (data) {
Node<std::string> dataClone = _doc.importNode(data, true);
container.appendChild(dataClone);
@@ -504,10 +505,10 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
#if 0
nodeSet.push_back(container);
#else
- Node<std::string> node = container.getFirstChild();
- while(node) {
- nodeSet.push_back(node);
- node = node.getNextSibling();
+ Node<std::string> child = container.getFirstChild();
+ while(child) {
+ nodeSet.push_back(child);
+ child = child.getNextSibling();
}
#endif
_varResolver.setVariable(location, nodeSet);
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
index 240c62c..62ee439 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
@@ -89,12 +89,12 @@ public:
virtual void eval(const Arabica::DOM::Element<std::string>& scriptElem,
const std::string& expr);
virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void assign(const std::string& location, const Data& data);
virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
- const Arabica::DOM::Document<std::string>& doc,
+ const Arabica::DOM::Node<std::string>& node,
const std::string& content);
virtual void init(const std::string& location, const Data& data);
diff --git a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp
index 6403a80..477a788 100644
--- a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp
+++ b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp
@@ -258,8 +258,8 @@ void OpenALInvoker::invoke(const InvokeRequest& req) {
throw std::string("openal error create context");
}
- std::cout << boost::lexical_cast<std::string>(_alContext);
- std::cout << boost::lexical_cast<std::string>(_alDevice);
+// std::cout << boost::lexical_cast<std::string>(_alContext);
+// std::cout << boost::lexical_cast<std::string>(_alDevice);
// alcMakeContextCurrent(_alContext);
// float listener[3] = {0,0,0};
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
index 06141c3..090f1b3 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
@@ -49,11 +49,9 @@ void OSGInvoker::invoke(const InvokeRequest& req) {
evTarget.addEventListener("DOMNodeRemoved", *this, false);
evTarget.addEventListener("DOMAttrModified", *this, false);
- Arabica::XPath::NodeSet<std::string> content = Interpreter::filterChildElements("content", req.dom);
-
std::set<std::string> validChilds;
validChilds.insert("display");
- processChildren(validChilds, content[0]);
+ processChildren(validChilds, req.dom);
}
void OSGInvoker::runOnMainThread() {
diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
index c697993..85c4b9c 100644
--- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
@@ -35,7 +35,7 @@ Data USCXMLInvoker::getDataModelVariables() {
}
void USCXMLInvoker::send(const SendRequest& req) {
- _invokedInterpreter.getImpl()->_externalQueue.push(req);
+ _invokedInterpreter.receive(req);
}
void USCXMLInvoker::cancel(const std::string sendId) {
@@ -46,7 +46,12 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) {
if (req.src.length() > 0) {
_invokedInterpreter = Interpreter::fromURI(req.src);
} else if (req.dom) {
- _invokedInterpreter = Interpreter::fromDOM(req.dom);
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> dom = domFactory.createDocument(req.dom.getNamespaceURI(), "", 0);
+ // we need to import the parent - to support xpath test150
+ Arabica::DOM::Node<std::string> newNode = dom.importNode(req.dom, true);
+ dom.appendChild(newNode);
+ _invokedInterpreter = Interpreter::fromDOM(dom);
} else if (req.content.size() > 0) {
_invokedInterpreter = Interpreter::fromXML(req.content);
} else {
@@ -73,7 +78,8 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) {
/// test240 assumes that invoke request params will carry over to the datamodel
_invokedInterpreter.getImpl()->setInvokeRequest(req);
- _invokedInterpreter.getImpl()->start();
+ _invokedInterpreter.start();
+// tthread::this_thread::sleep_for(tthread::chrono::seconds(1));
} else {
/// test 530
_parentInterpreter->receive(Event("done.invoke." + _invokeId, Event::PLATFORM));
diff --git a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
index ddca2eb..c0d3329 100644
--- a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
@@ -58,7 +58,8 @@ void VoiceXMLInvoker::send(const SendRequest& req) {
// }
// }
// }
- domSS << req.getFirstDOMElement();
+// domSS << req.getFirstDOMElement();
+ domSS << req.dom;
start.content = domSS.str();
_interpreter->getDataModel().replaceExpressions(start.content);
diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
index 059e7f5..acbf085 100644
--- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
@@ -88,7 +88,8 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
std::string content;
std::stringstream ss;
if (_invokeReq.dom) {
- ss << _invokeReq.getFirstDOMElement();
+// ss << _invokeReq.getFirstDOMElement();
+ ss << _invokeReq.dom;
content = ss.str();
} else if(_invokeReq.data) {
ss << _invokeReq.data;
@@ -160,14 +161,16 @@ void XHTMLInvoker::reply(const SendRequest& req, const HTTPServer::Request& long
if (req.dom) {
std::stringstream ss;
- Arabica::DOM::Node<std::string> content = req.dom.getDocumentElement();
+// Arabica::DOM::Node<std::string> content = req.dom.getDocumentElement();
+ Arabica::DOM::Node<std::string> content = req.dom;
if (content && boost::iequals(content.getLocalName(), "content")) {
reply.headers["X-SCXML-Type"] = (HAS_ATTR(content, "type") ? ATTR(content, "type") : "replacechildren");
reply.headers["X-SCXML-XPath"] = (HAS_ATTR(content, "xpath") ? ATTR(content, "xpath") : "/html/body");
if (HAS_ATTR(content, "attr"))
reply.headers["X-SCXML-Attr"] = ATTR(content, "attr");
}
- ss << req.getFirstDOMElement();
+// ss << req.getFirstDOMElement();
+ ss << req.dom;
reply.content = ss.str();
reply.headers["Content-Type"] = "application/xml";
} else if (req.data) {
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 56e2523..90cebc3 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -255,6 +255,16 @@ void BasicHTTPIOProcessor::downloadCompleted(const URL& url) {
std::map<std::string, std::pair<URL, SendRequest> >::iterator reqIter = _sendRequests.begin();
while(reqIter != _sendRequests.end()) {
if (reqIter->second.first == url) {
+ // test 513
+ std::string statusCode = url.getStatusCode();
+ if (statusCode.length() > 0) {
+ std::string statusPrefix = statusCode.substr(0,1);
+ std::string statusRest = statusCode.substr(1);
+ Event event;
+ event.data = url;
+ event.name = "HTTP." + statusPrefix + "." + statusRest;
+ returnEvent(event);
+ }
_sendRequests.erase(reqIter);
return;
}
diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
index 98d98e1..ac570c4 100644
--- a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
@@ -158,6 +158,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
LOG(ERROR) << "Not sure what to make of the target '" << reqCopy.target << "' - raising error" << std::endl;
Event error("error.execution", Event::PLATFORM);
error.sendid = reqCopy.sendid;
+ // test 159 still fails
_interpreter->receiveInternal(error);
}
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a78c079..53ec38f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -109,9 +109,11 @@ foreach( W3C_TEST ${W3C_TESTS} )
if (NOT TEST_NAME MATCHES ".*sub.*")
if (RUN_W3C_ECMA_TESTS AND TEST_NAME MATCHES "^ecma\\/.*")
add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST})
+ set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED")
endif()
if (RUN_W3C_XPATH_TESTS AND TEST_NAME MATCHES "^xpath\\/.*")
add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST})
+ set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED")
endif()
endif()
endforeach()
diff --git a/test/samples/uscxml/test-markup-passing.scxml b/test/samples/uscxml/test-markup-passing.scxml
new file mode 100644
index 0000000..32866b1
--- /dev/null
+++ b/test/samples/uscxml/test-markup-passing.scxml
@@ -0,0 +1,54 @@
+<scxml binding="late" datamodel="ecmascript"
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:foo="http://uscxml.tk.informatik.tu-darmstadt.de/foo.xsd">
+ <!--
+ embedded markup contains a single child
+ -->
+ <state id="markup-embedded-single">
+ <datamodel>
+ <data id="markup">
+ <root>
+ <child>1</child>
+ <foo:child>2</foo:child>
+ </root>
+ </data>
+ </datamodel>
+ <onentry>
+ <log label="markup-embedded-single" expr="markup.nodeName" />
+ </onentry>
+ <transition cond="markup.nodeName === 'root'" target="markup-embedded-many" />
+ </state>
+
+ <!--
+ embedded markup contains multiple childs
+ -->
+ <state id="markup-embedded-many">
+ <datamodel>
+ <data id="markup">
+ <root>
+ <child>1</child>
+ <foo:child>2</foo:child>
+ </root>
+ <root>
+ <child>1</child>
+ <foo:child>2</foo:child>
+ </root>
+ </data>
+ </datamodel>
+ <onentry>
+ <log label="markup-embedded-many" expr="markup.nodeName" />
+ </onentry>
+ <transition cond="markup.nodeName === 'data'" target="markup-file" />
+ </state>
+
+ <state id="markup-file">
+ <datamodel>
+ <data id="markup" src="test-markup.xml" />
+ </datamodel>
+ <onentry>
+ <log label="markup-file" expr="markup.nodeName" />
+ </onentry>
+ <transition cond="markup.nodeName === 'root'" target="exit" />
+ </state>
+ <final id="exit" />
+</scxml> \ No newline at end of file
diff --git a/test/samples/uscxml/test-markup.xml b/test/samples/uscxml/test-markup.xml
new file mode 100644
index 0000000..81da3d2
--- /dev/null
+++ b/test/samples/uscxml/test-markup.xml
@@ -0,0 +1,6 @@
+<root
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:foo="http://uscxml.tk.informatik.tu-darmstadt.de/scenegraph.xsd">
+ <child>1</child>
+ <foo:child>2</foo:child>
+</root> \ No newline at end of file
diff --git a/test/samples/uscxml/test-scenegraph.scxml b/test/samples/uscxml/test-scenegraph.scxml
index f0d1173..0efcd6d 100644
--- a/test/samples/uscxml/test-scenegraph.scxml
+++ b/test/samples/uscxml/test-scenegraph.scxml
@@ -23,17 +23,17 @@
</scenegraph:viewport>
<scenegraph:viewport x="0" y="50%" width="50%" height="50%" id="scene3">
<scenegraph:rotation id="treeRotation" pitch="100deg" roll="3.15149rad" yaw="10deg">
- <scenegraph:node src="http://people.sc.fsu.edu/~jburkardt/data/obj/airboat.obj" />
+ <scenegraph:node src="http://cs.iupui.edu/~aharris/webDesign/vrml/tree.wrl" />
</scenegraph:rotation>
</scenegraph:viewport>
<scenegraph:viewport x="50%" y="50%" width="50%" height="50%" id="scene4">
<scenegraph:translation x="0" y="0" z="0">
- <scenegraph:node src="http://people.sc.fsu.edu/~jburkardt/data/obj/airboat.obj" />
+ <scenegraph:node src="scenegraph/HARD_MP_VAL_000.wrl" />
</scenegraph:translation>
</scenegraph:viewport>
<scenegraph:viewport x="50%" y="0" width="50%" height="50%" id="scene2">
<scenegraph:translation x="0" y="0" z="0">
- <scenegraph:node src="http://people.sc.fsu.edu/~jburkardt/data/obj/airboat.obj" />
+ <scenegraph:node src="http://cs.iupui.edu/~aharris/mm/vrml4/house.wrl" />
</scenegraph:translation>
</scenegraph:viewport>
</scenegraph:display>
diff --git a/test/samples/w3c/ecma/test159.scxml b/test/samples/w3c/ecma/test159.scxml
index d144855..d7b7821 100644
--- a/test/samples/w3c/ecma/test159.scxml
+++ b/test/samples/w3c/ecma/test159.scxml
@@ -6,8 +6,8 @@ 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=""/>
- <conf:incrementId id="1"/>
+ <send event="thisWillFail" target="baz"/>
+ <assign location="Var1" expr="Var1 + 1"/>
</onentry>
<transition cond="Var1==1" target="fail"/>
<transition target="pass"/>
diff --git a/test/samples/w3c/ecma/test191.scxml b/test/samples/w3c/ecma/test191.scxml
index a44856b..6e82274 100644
--- a/test/samples/w3c/ecma/test191.scxml
+++ b/test/samples/w3c/ecma/test191.scxml
@@ -22,7 +22,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha
</content>
</invoke>
<transition event="childToParent" target="pass"/>
- <transition event="*" target="pass"/>
+ <transition event="*" target="fail"/>
</state>
<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final>
diff --git a/test/samples/w3c/ecma/test354.scxml b/test/samples/w3c/ecma/test354.scxml
new file mode 100644
index 0000000..3a3c33b
--- /dev/null
+++ b/test/samples/w3c/ecma/test354.scxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that event.data can be populated using both namelist, param and <content>
+and that correct values are used --><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="1"/>
+ <data id="Var2"/>
+ <data id="Var3"/>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <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.Var1"/>
+ <assign location="Var3" expr="_event.data.param1"/>
+ </transition>
+ <transition event="*" target="fail">
+ </transition>
+
+</state>
+
+<state id="s1">
+
+ <transition cond="Var2==1" target="s2"/>
+ <transition target="fail"/>
+ </state>
+
+<state id="s2">
+ <transition cond="Var3==2" target="s3"/>
+ <transition target="fail"/>
+ </state>
+
+<state id="s3">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event2">
+ <content>foo</content>
+ </send>
+ </onentry>
+ <transition event="event2" cond="_event.data === 'foo'" 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/samples/w3c/ecma/test415.scxml b/test/samples/w3c/ecma/test415.scxml
new file mode 100644
index 0000000..159218b
--- /dev/null
+++ b/test/samples/w3c/ecma/test415.scxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Test that the state machine halts when it enters a top-level final state. Since
+ the initial state is a final state, this machine should halt immediately without
+ processing "event1" which is raised in the final state's on-entry handler. This
+ is a manual test since there is no platform-independent way to test that event1
+ is not processed --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="ecmascript">
+ <final id="final">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ </final>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/ecma/test483.scxml b/test/samples/w3c/ecma/test483.scxml
new file mode 100644
index 0000000..0a1b236
--- /dev/null
+++ b/test/samples/w3c/ecma/test483.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that foreach works correctly, iterating over node set in document order.
+ This tests assertions 483-485 --><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">
+ <datamodel>
+ <data id="var1">
+ <nodes xmlns="">
+ <node/>
+ <node/>
+ <node/>
+ </nodes>
+ </data>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <foreach array="$var1/nodes/node" item="item" index="pos">
+ <assign location="$item" type="addattribute" attr="position" expr="$pos"/>
+ </foreach>
+ </onentry>
+
+ <transition cond="$var1/nodes/node[1]/@position = 1 and $var1/nodes/node[2]/@position = 2 and $var1/nodes/node[3]/@position = 3" 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/samples/w3c/ecma/test513.scxml b/test/samples/w3c/ecma/test513.scxml
new file mode 100644
index 0000000..c26d498
--- /dev/null
+++ b/test/samples/w3c/ecma/test513.scxml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that we get an HTTP success code back on successful delivery. To run this test, implementations
+must support an extension to send: if the parameter httpResponse is present with value 'true', then when
+the processor gets an http response code back, it must raise an event 'http.n1.nrest' where 'ni' is
+the first digit of the response code and 'nrest' are the remaining digits--><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" initial="s01">
+ <datamodel>
+ <data id="Var1"/>
+ </datamodel>
+
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <!-- child script. Once we're running send childRunning to parent and include basicHTTPAccess URI -->
+ <scxml initial="child0" datamodel="ecmascript" version="1.0">
+ <state id="child0">
+ <onentry>
+ <send target="#_parent" event="childRunning">
+ <param name="uri" expr="_ioprocessors['basichttp']['location']"/>
+ </send>
+ </onentry>
+ </state>
+ </scxml>
+ </content>
+ </invoke>
+
+ <transition event="*" target="fail"/>
+
+ <state id="s01">
+ <!-- when we get the event from the child, extract the access uri and use
+ the basicHTTP event i/o processor to send it an event -->
+ <transition event="childRunning" target="s02">
+ <assign location="Var1" expr="_event.data.uri"/>
+ <send event="test" targetexpr="Var1" httpResponse="true" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/>
+ </transition>
+ </state>
+
+ <state id="s02">
+ <!-- the child should send this back automatically. It does not need to take
+ any transition on the event -->
+ <transition event="HTTP.2" target="pass"/>
+ </state>
+ </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/samples/w3c/ecma/test528.scxml b/test/samples/w3c/ecma/test528.scxml
index edeb367..f0e8911 100644
--- a/test/samples/w3c/ecma/test528.scxml
+++ b/test/samples/w3c/ecma/test528.scxml
@@ -6,8 +6,7 @@
<transition event="error.execution" target="s1"/>
<transition event="done.state.s0" target="fail"/>
- <transition event="done.state.s0" target="fail">
- </transition>
+ <transition event="done.state.s0" target="fail"/>
<state id="s01">
<transition target="s02"/>
diff --git a/test/samples/w3c/txml/test159.txml b/test/samples/w3c/txml/test159.txml
index abf1925..b7245c0 100644
--- a/test/samples/w3c/txml/test159.txml
+++ b/test/samples/w3c/txml/test159.txml
@@ -11,7 +11,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=""/>
- <conf:incrementId id="1"/>
+ <conf:incrementID id="1"/>
</onentry>
<transition conf:idVal="1=1" conf:targetfail=""/>
<transition conf:targetpass=""/>
diff --git a/test/samples/w3c/txml/test191.txml b/test/samples/w3c/txml/test191.txml
index 60b44a9..6f42159 100644
--- a/test/samples/w3c/txml/test191.txml
+++ b/test/samples/w3c/txml/test191.txml
@@ -25,7 +25,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha
</content>
</invoke>
<transition event="childToParent" conf:targetpass=""/>
- <transition event="*" conf:targetpass=""/>
+ <transition event="*" conf:targetfail=""/>
</state>
<conf:pass/>
diff --git a/test/samples/w3c/txml/test354.txml b/test/samples/w3c/txml/test354.txml
new file mode 100644
index 0000000..d9e643a
--- /dev/null
+++ b/test/samples/w3c/txml/test354.txml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+
+<!-- test that event.data can be populated using both namelist, param and <content>
+and that correct values are used -->
+
+<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">
+<datamodel>
+ <data conf:id="1" expr="1"/>
+ <data conf:id="2"/>
+ <data conf:id="3"/>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="Var1">
+ <param name="param1" conf:expr="2"/>
+ </send>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign conf:location="2" conf:eventDataNamelistValue="Var1"/>
+ <assign conf:location="3" conf:eventDataParamValue="param1"/>
+ </transition>
+ <transition event="*" conf:targetfail="">
+ </transition>
+
+</state>
+
+<state id="s1">
+
+ <transition conf:idVal="2=1" target="s2"/>
+ <transition conf:targetfail=""/>
+ </state>
+
+<state id="s2">
+ <transition conf:idVal="3=2" target="s3"/>
+ <transition conf:targetfail=""/>
+ </state>
+
+<state id="s3">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event2">
+ <content>foo</content>
+ </send>
+ </onentry>
+ <transition event="event2" conf:eventdataVal="foo" conf:targetpass=""/>
+ <transition event="*" conf:targetfail=""/>
+
+</state>
+
+
+ <conf:pass/>
+ <conf:fail/>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/txml/test415.txml b/test/samples/w3c/txml/test415.txml
new file mode 100644
index 0000000..5bb3343
--- /dev/null
+++ b/test/samples/w3c/txml/test415.txml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!-- Test that the state machine halts when it enters a top-level final state. Since
+ the initial state is a final state, this machine should halt immediately without
+ processing "event1" which is raised in the final state's on-entry handler. This
+ is a manual test since there is no platform-independent way to test that event1
+ is not processed -->
+
+<scxml initial="final" version="1.0" conf:datamodel="" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance">
+ <final id="final">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ </final>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/txml/test483.txml b/test/samples/w3c/txml/test483.txml
new file mode 100644
index 0000000..7eab75b
--- /dev/null
+++ b/test/samples/w3c/txml/test483.txml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+ <!-- test that foreach works correctly, iterating over node set in document order.
+ This tests assertions 483-485 -->
+
+ <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">
+ <datamodel>
+ <data id="var1">
+ <nodes xmlns="">
+ <node/>
+ <node/>
+ <node/>
+ </nodes>
+ </data>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <foreach array="$var1/nodes/node" item="item" index="pos">
+ <assign location="$item" type="addattribute" attr="position" expr="$pos"/>
+ </foreach>
+ </onentry>
+
+ <transition cond="$var1/nodes/node[1]/@position = 1 and $var1/nodes/node[2]/@position = 2 and $var1/nodes/node[3]/@position = 3" conf:targetpass=""/>
+ <transition conf:targetfail=""/>
+ </state>
+
+<conf:pass/>
+<conf:fail/>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/txml/test513.txml b/test/samples/w3c/txml/test513.txml
new file mode 100644
index 0000000..65dda29
--- /dev/null
+++ b/test/samples/w3c/txml/test513.txml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+
+<!-- test that we get an HTTP success code back on successful delivery. To run this test, implementations
+must support an extension to send: if the parameter httpResponse is present with value 'true', then when
+the processor gets an http response code back, it must raise an event 'http.n1.nrest' where 'ni' is
+the first digit of the response code and 'nrest' are the remaining digits-->
+
+<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" initial="s01">
+ <datamodel>
+ <data conf:id="1"/>
+ </datamodel>
+
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <!-- child script. Once we're running send childRunning to parent and include basicHTTPAccess URI -->
+ <scxml initial="child0" conf:datamodel="" version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance">
+ <state id="child0">
+ <onentry>
+ <send target="#_parent" event="childRunning">
+ <param name="uri" conf:basicHTTPAccessURI=""/>
+ </send>
+ </onentry>
+ </state>
+ </scxml>
+ </content>
+ </invoke>
+
+ <transition event="*" conf:targetfail=""/>
+
+ <state id="s01">
+ <!-- when we get the event from the child, extract the access uri and use
+ the basicHTTP event i/o processor to send it an event -->
+ <transition event="childRunning" target="s02">
+ <assign conf:location="1" conf:eventDataFieldValue="uri"/>
+ <send event="test" conf:targetExpr="1" httpResponse="true" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/>
+ </transition>
+ </state>
+
+ <state id="s02">
+ <!-- the child should send this back automatically. It does not need to take
+ any transition on the event -->
+ <transition event="HTTP.2" conf:targetpass=""/>
+ </state>
+ </state>
+
+ <conf:pass/>
+ <conf:fail/>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/txml/test528.txml b/test/samples/w3c/txml/test528.txml
index 69b7bb2..271bb1c 100644
--- a/test/samples/w3c/txml/test528.txml
+++ b/test/samples/w3c/txml/test528.txml
@@ -9,8 +9,7 @@
<transition event="error.execution" target="s1"/>
<transition event="done.state.s0" conf:targetfail=""/>
- <transition event="done.state.s0" conf:targetfail="">
- </transition>
+ <transition event="done.state.s0" conf:targetfail=""/>
<state id="s01">
<transition target="s02"/>
diff --git a/test/samples/w3c/xpath/test159.scxml b/test/samples/w3c/xpath/test159.scxml
index 70a325d..1f2af35 100644
--- a/test/samples/w3c/xpath/test159.scxml
+++ b/test/samples/w3c/xpath/test159.scxml
@@ -7,7 +7,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=""/>
- <conf:incrementId id="1"/>
+ <assign location="$Var1" expr="$Var1 + 1"/>
</onentry>
<transition cond="$Var1/text() =1" target="fail"/>
<transition target="pass"/>
diff --git a/test/samples/w3c/xpath/test191.scxml b/test/samples/w3c/xpath/test191.scxml
index 25862ac..1910eaf 100644
--- a/test/samples/w3c/xpath/test191.scxml
+++ b/test/samples/w3c/xpath/test191.scxml
@@ -22,7 +22,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha
</content>
</invoke>
<transition event="childToParent" target="pass"/>
- <transition event="*" target="pass"/>
+ <transition event="*" target="fail"/>
</state>
<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final>
diff --git a/test/samples/w3c/xpath/test354.scxml b/test/samples/w3c/xpath/test354.scxml
new file mode 100644
index 0000000..93d768d
--- /dev/null
+++ b/test/samples/w3c/xpath/test354.scxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that event.data can be populated using both namelist, param and <content>
+and that correct values are used --><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">
+<datamodel>
+ <data id="Var1" expr="1"/>
+ <data id="Var2"/>
+ <data id="Var3"/>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <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="$Var3" expr="$_event/data/data[@id='param1']/text()"/>
+ </transition>
+ <transition event="*" target="fail">
+ </transition>
+
+</state>
+
+<state id="s1">
+
+ <transition cond="$Var2/text() =1" target="s2"/>
+ <transition target="fail"/>
+ </state>
+
+<state id="s2">
+ <transition cond="$Var3/text() =2" target="s3"/>
+ <transition target="fail"/>
+ </state>
+
+<state id="s3">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event2">
+ <content>foo</content>
+ </send>
+ </onentry>
+ <transition event="event2" cond="$_event/data = 'foo'" 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/samples/w3c/xpath/test415.scxml b/test/samples/w3c/xpath/test415.scxml
new file mode 100644
index 0000000..2da0bef
--- /dev/null
+++ b/test/samples/w3c/xpath/test415.scxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Test that the state machine halts when it enters a top-level final state. Since
+ the initial state is a final state, this machine should halt immediately without
+ processing "event1" which is raised in the final state's on-entry handler. This
+ is a manual test since there is no platform-independent way to test that event1
+ is not processed --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="xpath">
+ <final id="final">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ </final>
+
+</scxml> \ No newline at end of file
diff --git a/test/samples/w3c/xpath/test483.scxml b/test/samples/w3c/xpath/test483.scxml
new file mode 100644
index 0000000..0a1b236
--- /dev/null
+++ b/test/samples/w3c/xpath/test483.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that foreach works correctly, iterating over node set in document order.
+ This tests assertions 483-485 --><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">
+ <datamodel>
+ <data id="var1">
+ <nodes xmlns="">
+ <node/>
+ <node/>
+ <node/>
+ </nodes>
+ </data>
+ </datamodel>
+
+<state id="s0">
+ <onentry>
+ <foreach array="$var1/nodes/node" item="item" index="pos">
+ <assign location="$item" type="addattribute" attr="position" expr="$pos"/>
+ </foreach>
+ </onentry>
+
+ <transition cond="$var1/nodes/node[1]/@position = 1 and $var1/nodes/node[2]/@position = 2 and $var1/nodes/node[3]/@position = 3" 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/samples/w3c/xpath/test513.scxml b/test/samples/w3c/xpath/test513.scxml
new file mode 100644
index 0000000..bc29bb4
--- /dev/null
+++ b/test/samples/w3c/xpath/test513.scxml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- test that we get an HTTP success code back on successful delivery. To run this test, implementations
+must support an extension to send: if the parameter httpResponse is present with value 'true', then when
+the processor gets an http response code back, it must raise an event 'http.n1.nrest' where 'ni' is
+the first digit of the response code and 'nrest' are the remaining digits--><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" initial="s01">
+ <datamodel>
+ <data id="Var1"/>
+ </datamodel>
+
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <!-- child script. Once we're running send childRunning to parent and include basicHTTPAccess URI -->
+ <scxml initial="child0" datamodel="xpath" version="1.0">
+ <state id="child0">
+ <onentry>
+ <send target="#_parent" event="childRunning">
+ <param name="uri" expr="_ioprocessors/processor[@name=&#34;http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor&#34;]/location/text()"/>
+ </send>
+ </onentry>
+ </state>
+ </scxml>
+ </content>
+ </invoke>
+
+ <transition event="*" target="fail"/>
+
+ <state id="s01">
+ <!-- when we get the event from the child, extract the access uri and use
+ the basicHTTP event i/o processor to send it an event -->
+ <transition event="childRunning" target="s02">
+ <assign location="$Var1" expr="$_event/data/data[@id='uri']/text()"/>
+ <send event="test" targetexpr="$Var1" httpResponse="true" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/>
+ </transition>
+ </state>
+
+ <state id="s02">
+ <!-- the child should send this back automatically. It does not need to take
+ any transition on the event -->
+ <transition event="HTTP.2" target="pass"/>
+ </state>
+ </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/samples/w3c/xpath/test528.scxml b/test/samples/w3c/xpath/test528.scxml
index 7cc88f7..f8f8416 100644
--- a/test/samples/w3c/xpath/test528.scxml
+++ b/test/samples/w3c/xpath/test528.scxml
@@ -6,8 +6,7 @@
<transition event="error.execution" target="s1"/>
<transition event="done.state.s0" target="fail"/>
- <transition event="done.state.s0" target="fail">
- </transition>
+ <transition event="done.state.s0" target="fail"/>
<state id="s01">
<transition target="s02"/>
diff --git a/test/src/test-arabica-xpath.cpp b/test/src/test-arabica-xpath.cpp
index ced1de3..408cc2b 100644
--- a/test/src/test-arabica-xpath.cpp
+++ b/test/src/test-arabica-xpath.cpp
@@ -52,7 +52,7 @@ public:
virtual Arabica::XPath::XPathValue<string_type, string_adaptor> resolveVariable(const string_type& /* namespace_uri */,
const string_type& name) const {
using namespace Arabica::XPath;
- typename VarMap::const_iterator n = map_.find(name);
+ VarMap::const_iterator n = map_.find(name);
if(n == map_.end())
throw UnboundVariableException(string_adaptor::asStdString(name));
return XPathValue<string_type, string_adaptor>(new StringValue<string_type, string_adaptor>((*n).second));
diff --git a/test/src/test-datamodel.cpp b/test/src/test-datamodel.cpp
index b0ed107..773fe7f 100644
--- a/test/src/test-datamodel.cpp
+++ b/test/src/test-datamodel.cpp
@@ -19,7 +19,8 @@ int main(int argc, char** argv) {
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
- DataModel dm(Factory::getInstance()->createDataModel("ecmascript", NULL));
+ Interpreter interpreter = Interpreter::fromXML("<scxml></scxml>");
+ DataModel dm(Factory::getInstance()->createDataModel("ecmascript", interpreter.getImpl().get()));
dm.evalAsString("var foo = 12");
{
diff --git a/test/src/test-w3c.cpp b/test/src/test-w3c.cpp
index f18b339..1600c27 100644
--- a/test/src/test-w3c.cpp
+++ b/test/src/test-w3c.cpp
@@ -98,8 +98,11 @@ void printUsageAndExit() {
class W3CStatusMonitor : public uscxml::InterpreterMonitor {
void beforeCompletion(uscxml::Interpreter interpreter) {
Arabica::XPath::NodeSet<std::string> config = interpreter.getConfiguration();
- if (config.size() == 1 && boost::iequals(ATTR(config[0], "id"), "pass"))
+ if (config.size() == 1 && boost::iequals(ATTR(config[0], "id"), "pass")) {
+ std::cout << "TEST SUCCEEDED" << std::endl;
exit(EXIT_SUCCESS);
+ }
+ std::cout << "TEST FAILED" << std::endl;
exit(EXIT_FAILURE);
}
};