summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt39
-rw-r--r--contrib/cmake/FindArabica.cmake8
-rw-r--r--src/uscxml/Factory.cpp83
-rw-r--r--src/uscxml/Factory.h4
-rw-r--r--src/uscxml/Interpreter.cpp118
-rw-r--r--src/uscxml/Interpreter.h12
-rw-r--r--src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp11
-rw-r--r--src/uscxml/concurrency/eventqueue/DelayedEventQueue.h3
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp33
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.cpp9
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.h53
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.cpp59
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.h104
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.cpp24
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.h87
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.cpp23
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.h161
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.cpp60
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.h41
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp219
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h61
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.cpp30
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.h75
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp74
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h19
-rw-r--r--src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp95
-rw-r--r--src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h54
-rw-r--r--src/uscxml/plugins/invoker/sample/SampleInvoker.cpp1
-rw-r--r--src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp81
-rw-r--r--src/uscxml/plugins/invoker/umundo/UmundoInvoker.h11
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp3
-rw-r--r--test/CMakeLists.txt5
-rw-r--r--test/samples/uscxml/applications/3dviewer.scxml84
-rw-r--r--test/samples/uscxml/arabica/test-arabica-events.xml10
-rw-r--r--test/samples/uscxml/proto/3DViewer/CameraPos.proto9
-rw-r--r--test/samples/uscxml/proto/3DViewer/DirectoryListingService.proto48
-rw-r--r--test/samples/uscxml/proto/3DViewer/LinearAlgebra.proto18
-rw-r--r--test/samples/uscxml/proto/3DViewer/ModelInfo.proto10
-rw-r--r--test/samples/uscxml/proto/3DViewer/Pose.proto22
-rw-r--r--test/samples/uscxml/proto/3DViewer/SceneSetup.proto8
-rw-r--r--test/samples/uscxml/proto/3DViewer/SceneShotService.proto24
-rw-r--r--test/samples/uscxml/scripts/test-simple-ecmascript.scxml12
-rw-r--r--test/samples/uscxml/test-scenegraph.scxml45
-rw-r--r--test/src/test-arabica-events.cpp61
44 files changed, 1569 insertions, 442 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e9ce992..1067dd2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -324,6 +324,7 @@ add_definitions(-DGLOG_NO_ABBREVIATED_SEVERITIES)
# ARABICA
+# set($ENV{ARABICA_SRC} ${PROJECT_SOURCE_DIR}/../arabica)
find_package(Arabica REQUIRED)
include_directories(${ARABICA_INCLUDE_DIR})
list (APPEND USCXML_CORE_LIBS ${ARABICA_LIBRARY})
@@ -424,20 +425,28 @@ endif()
find_package(V8)
if (V8_FOUND)
include_directories(${V8_INCLUDE_DIR})
- file(GLOB_RECURSE V8_DATAMODEL
+ file(GLOB V8_DATAMODEL
src/uscxml/plugins/datamodel/ecmascript/v8/*.cpp
src/uscxml/plugins/datamodel/ecmascript/v8/*.h
)
+ file(GLOB_RECURSE V8_DOM
+ src/uscxml/plugins/datamodel/ecmascript/v8/dom/*.cpp
+ src/uscxml/plugins/datamodel/ecmascript/v8/dom/*.h
+ )
+ source_group("DOM" FILES ${V8_DOM})
+
if (BUILD_AS_PLUGINS)
add_library(
datamodel_v8 SHARED
- ${V8_DATAMODEL})
+ ${V8_DATAMODEL}
+ ${V8_DOM})
target_link_libraries(datamodel_v8
uscxml
${V8_LIBRARY})
set_target_properties(datamodel_v8 PROPERTIES FOLDER "Plugin DataModel")
else()
list (APPEND USCXML_FILES ${V8_DATAMODEL})
+ list (APPEND USCXML_FILES ${V8_DOM})
list (APPEND USCXML_OPT_LIBS ${V8_LIBRARY})
endif()
endif()
@@ -519,8 +528,27 @@ else()
endif()
+# Heartbeat invoker
+
+file(GLOB_RECURSE HEARTBEAT_INVOKER
+ src/uscxml/plugins/invoker/heartbeat/*.cpp
+ src/uscxml/plugins/invoker/heartbeat/*.h
+)
+if (BUILD_AS_PLUGINS)
+ add_library(
+ invoker_heartbeat SHARED
+ ${HEARTBEAT_INVOKER})
+ target_link_libraries(invoker_heartbeat uscxml)
+ set_target_properties(invoker_heartbeat PROPERTIES FOLDER "Plugin Invoker")
+else()
+ list (APPEND USCXML_FILES ${HEARTBEAT_INVOKER})
+endif()
+
+
# OpenSceneGraph invoker
-set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG}) # link dynamically!
+if (UNIX)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG}) # link dynamically!
+endif()
find_package(OpenSceneGraph COMPONENTS osgViewer osgGA osgText osgFX osgManipulator osgDB osgUtil OpenThreads)
if (OPENSCENEGRAPH_FOUND)
@@ -545,8 +573,9 @@ if (OPENSCENEGRAPH_FOUND)
endif()
endif()
-set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
-
+if (UNIX)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
# MILES modality components
diff --git a/contrib/cmake/FindArabica.cmake b/contrib/cmake/FindArabica.cmake
index 7ed0c7d..8e60d56 100644
--- a/contrib/cmake/FindArabica.cmake
+++ b/contrib/cmake/FindArabica.cmake
@@ -12,12 +12,16 @@ FIND_PATH(ARABICA_INCLUDE_DIR Arabica/getparam.hpp
set(ARABICA_LIBRARY)
FIND_LIBRARY(ARABICA_LIBRARY_RELEASE
NAMES arabica
- HINTS $ENV{ARABICA_SRC}/src/.libs/
+ HINTS
+ $ENV{ARABICA_SRC}/src/.libs/
+ $ENV{ARABICA_SRC}/build/
)
FIND_LIBRARY(ARABICA_LIBRARY_DEBUG
NAMES arabica_d arabica_debug
- HINTS $ENV{ARABICA_SRC}/src/.libs/
+ HINTS
+ $ENV{ARABICA_SRC}/src/.libs/
+ $ENV{ARABICA_SRC}/build/
)
if (ARABICA_LIBRARY_RELEASE AND NOT ARABICA_LIBRARY_DEBUG)
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 3f94901..3cac6b1 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -10,6 +10,7 @@
# include "uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h"
# include "uscxml/plugins/invoker/scxml/USCXMLInvoker.h"
+# include "uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h"
# ifdef UMUNDO_FOUND
# include "uscxml/plugins/invoker/umundo/UmundoInvoker.h"
@@ -110,6 +111,10 @@ Factory::Factory() {
registerInvoker(invoker);
}
{
+ HeartbeatInvoker* invoker = new HeartbeatInvoker();
+ registerInvoker(invoker);
+ }
+ {
EventIOProcessor* ioProcessor = new EventIOProcessor();
registerIOProcessor(ioProcessor);
}
@@ -125,28 +130,40 @@ Factory::~Factory() {
void Factory::registerIOProcessor(IOProcessor* ioProcessor) {
std::set<std::string> names = ioProcessor->getNames();
std::set<std::string>::iterator nameIter = names.begin();
- while(nameIter != names.end()) {
- _ioProcessors[*nameIter] = ioProcessor;
- nameIter++;
- }
+ if (nameIter != names.end()) {
+ std::string canonicalName = *nameIter;
+ _ioProcessors[canonicalName] = ioProcessor;
+ while(nameIter != names.end()) {
+ _ioProcessorAliases[*nameIter] = canonicalName;
+ nameIter++;
+ }
+ }
}
void Factory::registerDataModel(DataModel* dataModel) {
std::set<std::string> names = dataModel->getNames();
std::set<std::string>::iterator nameIter = names.begin();
- while(nameIter != names.end()) {
- _dataModels[*nameIter] = dataModel;
- nameIter++;
- }
+ if (nameIter != names.end()) {
+ std::string canonicalName = *nameIter;
+ _dataModels[canonicalName] = dataModel;
+ while(nameIter != names.end()) {
+ _dataModelAliases[*nameIter] = canonicalName;
+ nameIter++;
+ }
+ }
}
-
+
void Factory::registerInvoker(Invoker* invoker) {
std::set<std::string> names = invoker->getNames();
std::set<std::string>::iterator nameIter = names.begin();
- while(nameIter != names.end()) {
- _invokers[*nameIter] = invoker;
- nameIter++;
- }
+ if (nameIter != names.end()) {
+ std::string canonicalName = *nameIter;
+ _invokers[canonicalName] = invoker;
+ while(nameIter != names.end()) {
+ _invokerAliases[*nameIter] = canonicalName;
+ nameIter++;
+ }
+ }
}
void Factory::registerExecutableContent(const std::string tag, ExecutableContent* executableContent) {
@@ -155,28 +172,41 @@ void Factory::registerExecutableContent(const std::string tag, ExecutableContent
Invoker* Factory::getInvoker(const std::string type, Interpreter* interpreter) {
Factory* factory = getInstance();
- if (factory->_invokers.find(type) != factory->_invokers.end()) {
- return (Invoker*)factory->_invokers[type]->create(interpreter);
- }
- return NULL;
+ if (factory->_invokerAliases.find(type) == factory->_invokerAliases.end())
+ return NULL;
+
+ std::string canonicalName = factory->_invokerAliases[type];
+ if (factory->_invokers.find(canonicalName) == factory->_invokers.end())
+ return NULL;
+
+ return factory->_invokers[canonicalName]->create(interpreter);
}
DataModel* Factory::getDataModel(const std::string type, Interpreter* interpreter) {
Factory* factory = getInstance();
- if (factory->_dataModels.find(type) != factory->_dataModels.end()) {
- return factory->_dataModels[type]->create(interpreter);
- }
- return NULL;
+ if (factory->_dataModelAliases.find(type) == factory->_dataModelAliases.end())
+ return NULL;
+
+ std::string canonicalName = factory->_dataModelAliases[type];
+ if (factory->_dataModels.find(canonicalName) == factory->_dataModels.end())
+ return NULL;
+
+ return factory->_dataModels[canonicalName]->create(interpreter);
}
IOProcessor* Factory::getIOProcessor(const std::string type, Interpreter* interpreter) {
Factory* factory = getInstance();
- if (factory->_ioProcessors.find(type) != factory->_ioProcessors.end()) {
- return factory->_ioProcessors[type]->create(interpreter);
- }
- return NULL;
+ if (factory->_ioProcessorAliases.find(type) == factory->_ioProcessorAliases.end())
+ return NULL;
+
+ std::string canonicalName = factory->_ioProcessorAliases[type];
+ if (factory->_ioProcessors.find(canonicalName) == factory->_ioProcessors.end())
+ return NULL;
+
+ return factory->_ioProcessors[canonicalName]->create(interpreter);
}
+#if 0
ExecutableContent* Factory::getExecutableContent(const std::string tag, Interpreter* interpreter) {
Factory* factory = getInstance();
if (factory->_executableContent.find(tag) != factory->_executableContent.end()) {
@@ -184,7 +214,8 @@ ExecutableContent* Factory::getExecutableContent(const std::string tag, Interpre
}
return NULL;
}
-
+#endif
+
Factory* Factory::getInstance() {
if (_instance == NULL) {
_instance = new Factory();
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index 172ec99..16b26da 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -58,6 +58,7 @@ class Invoker : public IOProcessor {
public:
virtual void invoke(InvokeRequest& req) = 0;
virtual void sendToParent(SendRequest& req) = 0;
+ virtual Invoker* create(Interpreter* interpreter) = 0;
};
class DataModel {
@@ -99,8 +100,11 @@ public:
static Factory* getInstance();
std::map<std::string, DataModel*> _dataModels;
+ std::map<std::string, std::string> _dataModelAliases;
std::map<std::string, IOProcessor*> _ioProcessors;
+ std::map<std::string, std::string> _ioProcessorAliases;
std::map<std::string, Invoker*> _invokers;
+ std::map<std::string, std::string> _invokerAliases;
std::map<std::string, ExecutableContent*> _executableContent;
static std::string pluginPath;
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index f961b60..453bdd5 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -28,7 +28,7 @@ const std::string Interpreter::getUUID() {
return boost::lexical_cast<std::string>(uuidGen());
}
-Interpreter::Interpreter() {
+Interpreter::Interpreter() : Arabica::SAX2DOM::Parser<std::string>() {
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
@@ -38,8 +38,8 @@ Interpreter::Interpreter() {
Interpreter* Interpreter::fromDOM(const Arabica::DOM::Node<std::string>& node) {
Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
Interpreter* interpreter = new Interpreter();
- interpreter->_doc = domFactory.createDocument("http://www.w3.org/2005/07/scxml", "scxml", 0);
- interpreter->_doc.appendChild(node);
+ interpreter->_document = domFactory.createDocument("http://www.w3.org/2005/07/scxml", "scxml", 0);
+ interpreter->_document.appendChild(node);
interpreter->init();
return interpreter;
@@ -103,13 +103,17 @@ bool Interpreter::makeAbsolute(Arabica::io::URI& uri) {
return false;
}
+void Interpreter::startPrefixMapping(const std::string& prefix, const std::string& uri) {
+// std::cout << "starting prefix mapping " << prefix << ": " << uri << std::endl;
+ _nsContext.addNamespaceDeclaration(uri, prefix);
+}
+
Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) {
Interpreter* interpreter = new Interpreter();
- Arabica::SAX2DOM::Parser<std::string> domParser;
Arabica::SAX::CatchErrorHandler<std::string> errorHandler;
- domParser.setErrorHandler(errorHandler);
- if(!domParser.parse(source) || !domParser.getDocument().hasChildNodes()) {
+ interpreter->setErrorHandler(errorHandler);
+ if(!interpreter->parse(source) || !interpreter->Arabica::SAX2DOM::Parser<std::string>::getDocument().hasChildNodes()) {
LOG(INFO) << "could not parse input:";
if(errorHandler.errorsReported()) {
LOG(ERROR) << errorHandler.errors() << std::endl;
@@ -121,7 +125,7 @@ Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>
}
return NULL;
} else {
- interpreter->_doc = domParser.getDocument();
+ interpreter->_document = interpreter->Arabica::SAX2DOM::Parser<std::string>::getDocument();
}
interpreter->init();
return interpreter;
@@ -135,18 +139,22 @@ void Interpreter::init() {
_running = false;
_sendQueue = new DelayedEventQueue();
_sendQueue->start();
- if (_doc) {
- // do we have a xmlns attribute?
- std::string ns = _doc.getDocumentElement().getNamespaceURI();
- if(ns.size() > 0) {
- _nsContext.addNamespaceDeclaration(ns, "sc");
- _xpath.setNamespaceContext(_nsContext);
- _nsPrefix = "sc:";
- }
- NodeList<std::string> scxmls = _doc.getElementsByTagName("scxml");
+ if (_document) {
+ NodeList<std::string> scxmls = _document.getElementsByTagName("scxml");
if (scxmls.getLength() > 0) {
_scxml = (Arabica::DOM::Element<std::string>)scxmls.item(0);
- normalize(_doc);
+
+ // do we have a xmlns attribute?
+ std::string ns = _document.getDocumentElement().getNamespaceURI();
+ if(ns.size() > 0) {
+ _nsContext.addNamespaceDeclaration(ns, "sc");
+ _nsPrefix = "sc:";
+ }
+ // do we have additional namespaces?
+
+ _xpath.setNamespaceContext(_nsContext);
+
+ normalize(_document);
_name = (HAS_ATTR(_scxml, "name") ? ATTR(_scxml, "name") : getUUID());
} else {
LOG(ERROR) << "Cannot find SCXML element" << std::endl;
@@ -231,7 +239,7 @@ void Interpreter::interpret() {
setupIOProcessors();
// executeGlobalScriptElements
- NodeSet<std::string> globalScriptElems = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "script", _doc).asNodeSet();
+ NodeSet<std::string> globalScriptElems = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "script", _document).asNodeSet();
for (unsigned int i = 0; i < globalScriptElems.size(); i++) {
// std::cout << globalScriptElems[i].getFirstChild().getNodeValue() << std::endl;
if (_dataModel)
@@ -240,29 +248,29 @@ void Interpreter::interpret() {
_running = true;
- std::string binding = _xpath.evaluate("/" + _nsPrefix + "scxml/@binding", _doc).asString();
+ std::string binding = _xpath.evaluate("/" + _nsPrefix + "scxml/@binding", _document).asString();
_binding = (boost::iequals(binding, "late") ? LATE : EARLY);
// initialize all data elements
if (_dataModel && _binding == EARLY) {
- NodeSet<std::string> dataElems = _xpath.evaluate("//" + _nsPrefix + "data", _doc).asNodeSet();
+ NodeSet<std::string> dataElems = _xpath.evaluate("//" + _nsPrefix + "data", _document).asNodeSet();
for (unsigned int i = 0; i < dataElems.size(); i++) {
initializeData(dataElems[i]);
}
} else if(_dataModel) {
- NodeSet<std::string> topDataElems = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "datamodel/" + _nsPrefix + "data", _doc).asNodeSet();
+ NodeSet<std::string> topDataElems = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "datamodel/" + _nsPrefix + "data", _document).asNodeSet();
for (unsigned int i = 0; i < topDataElems.size(); i++) {
initializeData(topDataElems[i]);
}
}
// initial transition might be implict
- NodeSet<std::string> initialTransitions = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "initial/" + _nsPrefix + "transition", _doc).asNodeSet();
+ NodeSet<std::string> initialTransitions = _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "initial/" + _nsPrefix + "transition", _document).asNodeSet();
if (initialTransitions.size() == 0) {
Arabica::DOM::Element<std::string> initialState = (Arabica::DOM::Element<std::string>)getInitialState();
- Arabica::DOM::Element<std::string> initialElem = _doc.createElement("initial");
+ Arabica::DOM::Element<std::string> initialElem = _document.createElement("initial");
initialElem.setAttribute("generated", "on");
- Arabica::DOM::Element<std::string> transitionElem = _doc.createElement("transition");
+ Arabica::DOM::Element<std::string> transitionElem = _document.createElement("transition");
transitionElem.setAttribute("target", initialState.getAttribute("id"));
initialElem.appendChild(transitionElem);
_scxml.appendChild(initialElem);
@@ -316,7 +324,7 @@ void Interpreter::initializeData(const Arabica::DOM::Node<std::string>& data) {
void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
// make sure every state has an id and set isFirstEntry to true
- Arabica::XPath::NodeSet<std::string> states = _xpath.evaluate("//" + _nsPrefix + "state", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> states = _xpath.evaluate("//" + _nsPrefix + "state", _document).asNodeSet();
for (int i = 0; i < states.size(); i++) {
Arabica::DOM::Element<std::string> stateElem = Arabica::DOM::Element<std::string>(states[i]);
stateElem.setAttribute("isFirstEntry", "true");
@@ -326,7 +334,7 @@ void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
}
// make sure every invoke has an idlocation or id
- Arabica::XPath::NodeSet<std::string> invokes = _xpath.evaluate("//" + _nsPrefix + "invoke", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> invokes = _xpath.evaluate("//" + _nsPrefix + "invoke", _document).asNodeSet();
for (int i = 0; i < invokes.size(); i++) {
Arabica::DOM::Element<std::string> invokeElem = Arabica::DOM::Element<std::string>(invokes[i]);
if (!invokeElem.hasAttribute("id") && !invokeElem.hasAttribute("idlocation")) {
@@ -340,7 +348,7 @@ void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
// }
}
- Arabica::XPath::NodeSet<std::string> finals = _xpath.evaluate("//" + _nsPrefix + "final", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> finals = _xpath.evaluate("//" + _nsPrefix + "final", _document).asNodeSet();
for (int i = 0; i < finals.size(); i++) {
Arabica::DOM::Element<std::string> finalElem = Arabica::DOM::Element<std::string>(finals[i]);
finalElem.setAttribute("isFirstEntry", "true");
@@ -349,7 +357,7 @@ void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
}
}
- Arabica::XPath::NodeSet<std::string> histories = _xpath.evaluate("//" + _nsPrefix + "history", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> histories = _xpath.evaluate("//" + _nsPrefix + "history", _document).asNodeSet();
for (int i = 0; i < histories.size(); i++) {
Arabica::DOM::Element<std::string> historyElem = Arabica::DOM::Element<std::string>(histories[i]);
if (!historyElem.hasAttribute("id")) {
@@ -357,7 +365,7 @@ void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
}
}
- Arabica::XPath::NodeSet<std::string> scxml = _xpath.evaluate("/" + _nsPrefix + "scxml", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> scxml = _xpath.evaluate("/" + _nsPrefix + "scxml", _document).asNodeSet();
if (!((Arabica::DOM::Element<std::string>)scxml[0]).hasAttribute("id")) {
((Arabica::DOM::Element<std::string>)scxml[0]).setAttribute("id", getUUID());
}
@@ -365,8 +373,8 @@ void Interpreter::normalize(const Arabica::DOM::Document<std::string>& node) {
// create a pseudo initial and transition element
#if 0
Arabica::DOM::Element<std::string> initialState = (Arabica::DOM::Element<std::string>)getInitialState();
- Arabica::DOM::Element<std::string> initialElem = _doc.createElement("initial");
- Arabica::DOM::Element<std::string> transitionElem = _doc.createElement("transition");
+ Arabica::DOM::Element<std::string> initialElem = _document.createElement("initial");
+ Arabica::DOM::Element<std::string> transitionElem = _document.createElement("transition");
transitionElem.setAttribute("target", initialState.getAttribute("id"));
initialElem.appendChild(transitionElem);
_scxml.appendChild(initialElem);
@@ -385,7 +393,7 @@ void Interpreter::mainEventLoop() {
#if 0
std::cout << "Configuration: ";
for (int i = 0; i < _configuration.size(); i++) {
- std::cout << ((Arabica::DOM::Element<std::string>)_configuration[i]).getAttribute("id") << ", ";
+ std::cout << ATTR(_configuration[i], "id") << ", ";
}
std::cout << std::endl;
#endif
@@ -424,7 +432,7 @@ void Interpreter::mainEventLoop() {
_stabilized.notify_all();
}
- // whenever we have a stable configuration, run the mainThread hooks with 200fps
+ // whenever we have a stable configuration, run the mainThread hooks with 200fps
while(_externalQueue.isEmpty() && _thread == NULL) {
runOnMainThread(200);
}
@@ -1343,6 +1351,14 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet<std::string>& enable
}
}
statesToEnter.to_document_order();
+#if 0
+ std::cout << "Entering states: ";
+ for (int i = 0; i < statesToEnter.size(); i++) {
+ std::cout << ATTR(statesToEnter[i], "id") << ", ";
+ }
+ std::cout << std::endl;
+#endif
+
for (int i = 0; i < statesToEnter.size(); i++) {
Arabica::DOM::Element<std::string> stateElem = (Arabica::DOM::Element<std::string>)statesToEnter[i];
_configuration.push_back(stateElem);
@@ -1523,17 +1539,17 @@ Arabica::DOM::Node<std::string> Interpreter::getState(const std::string& stateId
}
// first try atomic and compund states
- NodeSet<std::string> target = _xpath.evaluate("//" + _nsPrefix + "state[@id='" + stateId + "']", _doc).asNodeSet();
+ NodeSet<std::string> target = _xpath.evaluate("//" + _nsPrefix + "state[@id='" + stateId + "']", _document).asNodeSet();
if (target.size() > 0)
goto FOUND;
// now parallel states
- target = _xpath.evaluate("//" + _nsPrefix + "parallel[@id='" + stateId + "']", _doc).asNodeSet();
+ target = _xpath.evaluate("//" + _nsPrefix + "parallel[@id='" + stateId + "']", _document).asNodeSet();
if (target.size() > 0)
goto FOUND;
// now final states
- target = _xpath.evaluate("//" + _nsPrefix + "final[@id='" + stateId + "']", _doc).asNodeSet();
+ target = _xpath.evaluate("//" + _nsPrefix + "final[@id='" + stateId + "']", _document).asNodeSet();
if (target.size() > 0)
goto FOUND;
@@ -1562,7 +1578,7 @@ Arabica::DOM::Node<std::string> Interpreter::getSourceState(const Arabica::DOM::
*/
Arabica::DOM::Node<std::string> Interpreter::getInitialState(Arabica::DOM::Node<std::string> state) {
if (!state) {
- state = _doc.getFirstChild();
+ state = _document.getFirstChild();
while(!isState(state))
state = state.getNextSibling();
}
@@ -1825,19 +1841,19 @@ IOProcessor* Interpreter::getIOProcessor(const std::string& type) {
bool Interpreter::validate() {
bool validationErrors = false;
- if (!_doc) {
+ if (!_document) {
LOG(ERROR) << "Document " << _baseURI.as_string() << " was not parsed successfully" << std::endl;
return false;
}
// semantic issues ------------
- if ((_xpath.evaluate("/" + _nsPrefix + "scxml/@datamodel", _doc).asNodeSet().size() == 0) &&
- _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "script", _doc).asNodeSet().size() > 0) {
+ if ((_xpath.evaluate("/" + _nsPrefix + "scxml/@datamodel", _document).asNodeSet().size() == 0) &&
+ _xpath.evaluate("/" + _nsPrefix + "scxml/" + _nsPrefix + "script", _document).asNodeSet().size() > 0) {
LOG(ERROR) << "Script elements used, but no datamodel specified" << std::endl;
}
// element issues ------------
- Arabica::XPath::NodeSet<std::string> scxmlElems = _xpath.evaluate(_nsPrefix + "scxml", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> scxmlElems = _xpath.evaluate(_nsPrefix + "scxml", _document).asNodeSet();
if (scxmlElems.size() > 0)
LOG(ERROR) << "More than one scxml element found" << std::endl;
for (unsigned int i = 0; i < scxmlElems.size(); i++) {
@@ -1859,7 +1875,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> stateElems = _xpath.evaluate(_nsPrefix + "state", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> stateElems = _xpath.evaluate(_nsPrefix + "state", _document).asNodeSet();
for (unsigned int i = 0; i < stateElems.size(); i++) {
NodeList<std::string> childs = stateElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1880,7 +1896,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> parallelElems = _xpath.evaluate(_nsPrefix + "parallel", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> parallelElems = _xpath.evaluate(_nsPrefix + "parallel", _document).asNodeSet();
for (unsigned int i = 0; i < parallelElems.size(); i++) {
NodeList<std::string> childs = parallelElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1899,7 +1915,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> transitionElems = _xpath.evaluate(_nsPrefix + "transition", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> transitionElems = _xpath.evaluate(_nsPrefix + "transition", _document).asNodeSet();
for (unsigned int i = 0; i < transitionElems.size(); i++) {
if (HAS_ATTR(transitionElems[i], "cond") &&
!HAS_ATTR(transitionElems[i], "event")) {
@@ -1912,7 +1928,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> initialElems = _xpath.evaluate(_nsPrefix + "initial", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> initialElems = _xpath.evaluate(_nsPrefix + "initial", _document).asNodeSet();
for (unsigned int i = 0; i < initialElems.size(); i++) {
NodeList<std::string> childs = initialElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1924,7 +1940,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> finalElems = _xpath.evaluate(_nsPrefix + "final", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> finalElems = _xpath.evaluate(_nsPrefix + "final", _document).asNodeSet();
for (unsigned int i = 0; i < finalElems.size(); i++) {
NodeList<std::string> childs = finalElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1938,7 +1954,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> historyElems = _xpath.evaluate(_nsPrefix + "history", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> historyElems = _xpath.evaluate(_nsPrefix + "history", _document).asNodeSet();
for (unsigned int i = 0; i < historyElems.size(); i++) {
NodeList<std::string> childs = historyElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1950,7 +1966,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> datamodelElems = _xpath.evaluate(_nsPrefix + "datamodel", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> datamodelElems = _xpath.evaluate(_nsPrefix + "datamodel", _document).asNodeSet();
for (unsigned int i = 0; i < datamodelElems.size(); i++) {
NodeList<std::string> childs = datamodelElems[i].getChildNodes();
for (unsigned int j = 0; j < childs.getLength(); j++) {
@@ -1962,7 +1978,7 @@ bool Interpreter::validate() {
}
}
- Arabica::XPath::NodeSet<std::string> dataElems = _xpath.evaluate(_nsPrefix + "data", _doc).asNodeSet();
+ Arabica::XPath::NodeSet<std::string> dataElems = _xpath.evaluate(_nsPrefix + "data", _document).asNodeSet();
for (unsigned int i = 0; i < dataElems.size(); i++) {
if (!HAS_ATTR(dataElems[i], "id"))
LOG(ERROR) << "data element has no id attribute" << std::endl;
@@ -1972,9 +1988,9 @@ bool Interpreter::validate() {
}
void Interpreter::dump() {
- if (!_doc)
+ if (!_document)
return;
- dump(_doc);
+ dump(_document);
}
void Interpreter::dump(const Arabica::DOM::Node<std::string>& node, int lvl) {
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 80468e4..edfdfd2 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -50,7 +50,7 @@ public:
std::string unit;
};
-class Interpreter {
+class Interpreter : protected Arabica::SAX2DOM::Parser<std::string> {
public:
enum Binding {
EARLY = 0,
@@ -64,6 +64,8 @@ public:
static Interpreter* fromURI(const std::string& uri);
static Interpreter* fromInputSource(Arabica::SAX::InputSource<std::string>& source);
+ virtual void startPrefixMapping(const std::string& /* prefix */, const std::string& /* uri */);
+
void start();
static void run(void*);
void join() {
@@ -93,8 +95,8 @@ public:
std::string getNSPrefix() {
return _nsPrefix;
}
- Arabica::XPath::XPath<std::string>& getXPath() {
- return _xpath;
+ Arabica::XPath::StandardNamespaceContext<std::string>& getNSContext() {
+ return _nsContext;
}
void waitForStabilization();
@@ -110,7 +112,7 @@ public:
}
Arabica::DOM::Node<std::string> getState(const std::string& stateId);
Arabica::DOM::Document<std::string>& getDocument() {
- return _doc;
+ return _document;
}
const std::string& getName() {
@@ -161,7 +163,7 @@ protected:
tthread::condition_variable _stabilized;
Arabica::io::URI _baseURI;
- Arabica::DOM::Document<std::string> _doc;
+ Arabica::DOM::Document<std::string> _document;
Arabica::DOM::Element<std::string> _scxml;
Arabica::XPath::XPath<std::string> _xpath;
Arabica::XPath::StandardNamespaceContext<std::string> _nsContext;
diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
index e582c13..5f2611f 100644
--- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
+++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
@@ -35,19 +35,20 @@ void DelayedEventQueue::run(void* instance) {
}
}
-void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData) {
+void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist) {
if(_callbackData.find(eventId) != _callbackData.end()) {
cancelEvent(eventId);
}
struct timeval delay = {delayMs / 1000, (delayMs % 1000) * 1000};
- struct event* event = event_new(_eventLoop, -1, 0, DelayedEventQueue::timerCallback, &_callbackData[eventId]);
+ struct event* event = event_new(_eventLoop, -1, (persist ? EV_PERSIST : 0), DelayedEventQueue::timerCallback, &_callbackData[eventId]);
_callbackData[eventId].eventId = eventId;
_callbackData[eventId].userData = userData;
_callbackData[eventId].eventQueue = this;
_callbackData[eventId].callback = callback;
_callbackData[eventId].event = event;
+ _callbackData[eventId].persist = persist;
event_add(event, &delay);
}
@@ -84,9 +85,11 @@ void DelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg)
tthread::lock_guard<tthread::recursive_mutex> lock(data->eventQueue->_mutex);
std::string eventId = data->eventId; // copy eventId
- event_free(data->event);
data->callback(data->userData, eventId);
- data->eventQueue->_callbackData.erase(data->eventId);
+ if (!data->persist) {
+ event_free(data->event);
+ data->eventQueue->_callbackData.erase(data->eventId);
+ }
}
} \ No newline at end of file
diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
index 8825c27..84ab16e 100644
--- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
+++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
@@ -22,6 +22,7 @@ public:
void *userData;
void (*callback)(void*, const std::string eventId);
std::string eventId;
+ bool persist;
struct event *event;
DelayedEventQueue* eventQueue;
};
@@ -29,7 +30,7 @@ public:
DelayedEventQueue();
virtual ~DelayedEventQueue();
- void addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData);
+ void addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist = false);
void cancelEvent(std::string eventId);
void start();
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index 6073e26..3bdf28c 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -1,6 +1,7 @@
#include "uscxml/Common.h"
#include "V8DataModel.h"
-#include "dom/V8SCXMLDOM.h"
+#include "dom/V8DOM.h"
+#include "dom/V8Document.h"
#include "uscxml/Message.h"
#include <glog/logging.h>
@@ -28,16 +29,32 @@ DataModel* V8DataModel::create(Interpreter* interpreter) {
v8::Locker locker;
v8::HandleScope scope;
+ V8DOM* dom = new V8DOM();
+ dom->interpreter = interpreter;
+ dom->xpath = new Arabica::XPath::XPath<std::string>();
+ dom->xpath->setNamespaceContext(interpreter->getNSContext());
+
// see http://stackoverflow.com/questions/3171418/v8-functiontemplate-class-instance
-// dm->_globalTemplate = v8::Persistent<v8::ObjectTemplate>(v8::ObjectTemplate::New());
-// dm->_globalTemplate->Set(v8::String::New("In"), v8::FunctionTemplate::New(jsIn, v8::External::New(reinterpret_cast<void*>(this))));
+ // some free functions
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
- global->Set(v8::String::New("In"), v8::FunctionTemplate::New(jsIn, v8::External::New(reinterpret_cast<void*>(dm))));
- global->Set(v8::String::New("print"), v8::FunctionTemplate::New(jsPrint, v8::External::New(reinterpret_cast<void*>(dm))));
- global->Set(v8::String::New("document"), V8SCXMLDOM::getDocument(interpreter->getDocument()));
-
- dm->_contexts.push_back(v8::Context::New(NULL, global));
+ global->Set(v8::String::New("In"), v8::FunctionTemplate::New(jsIn, v8::External::New(reinterpret_cast<void*>(dm))), v8::ReadOnly);
+ global->Set(v8::String::New("print"), v8::FunctionTemplate::New(jsPrint, v8::External::New(reinterpret_cast<void*>(dm))), v8::ReadOnly);
+
+ v8::Persistent<v8::Context> context = v8::Context::New(0, global);
+ v8::Context::Scope contextScope(context);
+
+ // instantiate the document function
+ v8::Handle<v8::Function> docCtor = V8Document::getTmpl()->GetFunction();
+ v8::Handle<v8::Object> docObj = docCtor->NewInstance();
+ docObj->SetInternalField(0, V8DOM::toExternal(&(interpreter->getDocument())));
+ docObj->SetInternalField(1, V8DOM::toExternal(dom));
+ context->Global()->Set(v8::String::New("document"), docObj);
+
+ dm->_contexts.push_back(context);
+
+ // instantiate objects - we have to have a context for that!
+
dm->setName(interpreter->getName());
dm->setSessionId(interpreter->getSessionId());
dm->eval("_ioprocessors = {};");
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.cpp
new file mode 100644
index 0000000..d1aa301
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.cpp
@@ -0,0 +1,9 @@
+#include "V8DOM.h"
+
+namespace uscxml {
+
+V8DOM::V8DOM() {
+
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.h
new file mode 100644
index 0000000..9fbe0e4
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DOM.h
@@ -0,0 +1,53 @@
+#ifndef V8DOM_H_LKE1HKJK
+#define V8DOM_H_LKE1HKJK
+
+#include "uscxml/Interpreter.h"
+#include <v8.h>
+
+#define V8_DESTRUCTOR(type) \
+static void jsDestructor(v8::Persistent<v8::Value> object, void* data) { \
+v8::HandleScope handleScope; \
+type* thing = static_cast<type*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value()); \
+delete thing; \
+object.Dispose(); \
+object.Clear(); \
+}
+
+#define ASSERT_ARGS1(args, type1) \
+assert(args.Length() == 1); \
+assert(args[0]->type1());
+
+#define ASSERT_ARGS2(args, type1, type2) \
+assert(args.Length() == 2); \
+assert(args[0]->type1()); \
+assert(args[1]->type2());
+
+namespace uscxml {
+
+class V8DOM {
+public:
+ V8DOM();
+ virtual ~V8DOM() { };
+
+ template <typename T>
+ static T* toClassPtr(v8::Local<v8::Value> data) {
+ if(data.IsEmpty())
+ return NULL;
+ else if(!data->IsExternal())
+ return NULL;
+ else
+ return static_cast<T *>(v8::External::Unwrap(data));
+ return NULL;
+ }
+ static v8::Local<v8::External> toExternal(void* pointer) {
+ v8::HandleScope scope;
+ return scope.Close(v8::External::New(pointer));
+ }
+
+ Interpreter* interpreter;
+ Arabica::XPath::XPath<std::string>* xpath;
+};
+
+}
+
+#endif /* end of include guard: V8DOM_H_LKE1HKJK */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.cpp
new file mode 100644
index 0000000..31372ed
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.cpp
@@ -0,0 +1,59 @@
+#include "V8Document.h"
+#include "V8Element.h"
+#include "V8XPathResult.h"
+
+namespace uscxml {
+
+using namespace Arabica::DOM;
+using namespace Arabica::XPath;
+
+v8::Persistent<v8::FunctionTemplate> V8Document::Tmpl;
+
+v8::Handle<v8::Value> V8Document::createElementCallback(const v8::Arguments& args) {
+ ASSERT_ARGS1(args, IsString);
+ v8::String::AsciiValue tagName(args[0]);
+
+ v8::Local<v8::Object> self = args.Holder();
+ Document<std::string>* doc = V8DOM::toClassPtr<Document<std::string> >(self->GetInternalField(0));
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+
+ Element<std::string>* element = new Element<std::string>(doc->createElement(*tagName));
+
+ v8::Handle<v8::Function> elemCtor = V8Element::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> elemObj = v8::Persistent<v8::Object>::New(elemCtor->NewInstance());
+
+ elemObj->SetInternalField(0, V8DOM::toExternal(element));
+ elemObj->SetInternalField(1, self->GetInternalField(1));
+
+ elemObj.MakeWeak(0, V8Element::jsDestructor);
+ return elemObj;
+}
+
+v8::Handle<v8::Value> V8Document::evaluateCallback(const v8::Arguments& args) {
+ ASSERT_ARGS1(args, IsString);
+ v8::String::AsciiValue xpathExpr(args[0]);
+
+ v8::Local<v8::Object> self = args.Holder();
+ Document<std::string>* doc = V8DOM::toClassPtr<Document<std::string> >(self->GetInternalField(0));
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+
+ Node<std::string>* context;
+ if (args.Length() > 1) {
+ context = V8DOM::toClassPtr<Node<std::string> >(args[1]->ToObject()->GetInternalField(0));
+ } else {
+ context = doc;
+ }
+
+ XPathValue<std::string>* xpathValue = new XPathValue<std::string>(dom->xpath->evaluate(*xpathExpr, *context));
+
+ v8::Handle<v8::Function> xpathResultCtor = V8XPathResult::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> xpathResultObj = v8::Persistent<v8::Object>::New(xpathResultCtor->NewInstance());
+
+ xpathResultObj->SetInternalField(0, V8DOM::toExternal(xpathValue));
+ xpathResultObj->SetInternalField(1, self->GetInternalField(1));
+
+ xpathResultObj.MakeWeak(0, V8XPathResult::jsDestructor);
+ return xpathResultObj;
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.h
new file mode 100644
index 0000000..680c433
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Document.h
@@ -0,0 +1,104 @@
+#ifndef V8DOCUMENT_H_COKK9O3L
+#define V8DOCUMENT_H_COKK9O3L
+
+#include "V8DOM.h"
+#include "V8Node.h"
+
+namespace uscxml {
+
+ class V8Document {
+ public:
+ static v8::Handle<v8::Value> doctypeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> implementationAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> documentElementAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> createElementCallback(const v8::Arguments& args);
+ static v8::Handle<v8::Value> createDocumentFragmentCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createTextNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createCommentCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createCDATASectionCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createProcessingInstructionCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createAttributeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createEntityReferenceCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getElementsByTagNameCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> importNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createElementNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createAttributeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getElementsByTagNameNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getElementByIdCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> createEventCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> createExpressionCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> createNSResolverCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> evaluateCallback(const v8::Arguments& args);
+
+ V8_DESTRUCTOR(Arabica::DOM::Document<std::string>);
+
+ static v8::Persistent<v8::FunctionTemplate> Tmpl;
+ static v8::Handle<v8::FunctionTemplate> getTmpl() {
+ if (Tmpl.IsEmpty()) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::New("Document"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ instance->SetInternalFieldCount(2);
+
+ instance->SetAccessor(v8::String::NewSymbol("doctype"), V8Document::doctypeAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("implementation"), V8Document::implementationAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("documentElement"), V8Document::documentElementAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+
+ prototype->Set(v8::String::NewSymbol("createElement"),
+ v8::FunctionTemplate::New(V8Document::createElementCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createDocumentFragment"),
+ v8::FunctionTemplate::New(V8Document::createDocumentFragmentCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createTextNode"),
+ v8::FunctionTemplate::New(V8Document::createTextNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createComment"),
+ v8::FunctionTemplate::New(V8Document::createCommentCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createCDATASection"),
+ v8::FunctionTemplate::New(V8Document::createCDATASectionCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createProcessingInstruction"),
+ v8::FunctionTemplate::New(V8Document::createProcessingInstructionCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createAttribute"),
+ v8::FunctionTemplate::New(V8Document::createAttributeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createEntityReference"),
+ v8::FunctionTemplate::New(V8Document::createEntityReferenceCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getElementsByTagName"),
+ v8::FunctionTemplate::New(V8Document::getElementsByTagNameCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("importNode"),
+ v8::FunctionTemplate::New(V8Document::importNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createElementNS"),
+ v8::FunctionTemplate::New(V8Document::createElementNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createAttributeNS"),
+ v8::FunctionTemplate::New(V8Document::createAttributeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getElementsByTagNameNS"),
+ v8::FunctionTemplate::New(V8Document::getElementsByTagNameNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getElementById"),
+ v8::FunctionTemplate::New(V8Document::getElementByIdCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createEvent"),
+ v8::FunctionTemplate::New(V8Document::createEventCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createExpression"),
+ v8::FunctionTemplate::New(V8Document::createExpressionCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("createNSResolver"),
+ v8::FunctionTemplate::New(V8Document::createNSResolverCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("evaluate"),
+ v8::FunctionTemplate::New(V8Document::evaluateCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+
+ tmpl->Inherit(V8Node::getTmpl());
+ Tmpl = v8::Persistent<v8::FunctionTemplate>::New(tmpl);
+ }
+ return Tmpl;
+ }
+
+ };
+
+}
+
+
+#endif /* end of include guard: V8DOCUMENT_H_COKK9O3L */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.cpp
new file mode 100644
index 0000000..14b2eae
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.cpp
@@ -0,0 +1,24 @@
+#include "V8Element.h"
+#include <DOM/Element.hpp>
+
+namespace uscxml {
+
+using namespace Arabica::DOM;
+
+v8::Persistent<v8::FunctionTemplate> V8Element::Tmpl;
+
+v8::Handle<v8::Value> V8Element::setAttributeCallback(const v8::Arguments& args) {
+ ASSERT_ARGS2(args, IsString, IsString);
+ v8::String::AsciiValue key(args[0]);
+ v8::String::AsciiValue value(args[1]);
+
+ v8::Local<v8::Object> self = args.Holder();
+ Element<std::string>* elem = V8DOM::toClassPtr<Element<std::string> >(self->GetInternalField(0));
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+
+ elem->setAttribute(*key, *value);
+
+ return v8::Undefined();
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.h
new file mode 100644
index 0000000..f610108
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Element.h
@@ -0,0 +1,87 @@
+#ifndef V8ELEMENT_H_B55C09NB
+#define V8ELEMENT_H_B55C09NB
+
+#include "V8DOM.h"
+#include "V8Node.h"
+
+namespace uscxml {
+
+ class V8Element {
+ public:
+ static v8::Handle<v8::Value> tagNameAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> getAttributeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> setAttributeCallback(const v8::Arguments& args);
+ static v8::Handle<v8::Value> removeAttributeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getAttributeNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> setAttributeNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> removeAttributeNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getElementsByTagNameCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getAttributeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> setAttributeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> removeAttributeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getElementsByTagNameNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> getAttributeNodeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> setAttributeNodeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> hasAttributeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> hasAttributeNSCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ V8_DESTRUCTOR(Arabica::DOM::Element<std::string>);
+
+ static v8::Persistent<v8::FunctionTemplate> Tmpl;
+ static v8::Handle<v8::FunctionTemplate> getTmpl() {
+ if (Tmpl.IsEmpty()) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::New("Element"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ instance->SetInternalFieldCount(2);
+
+ instance->SetAccessor(v8::String::NewSymbol("tagName"), V8Element::tagNameAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+
+ prototype->Set(v8::String::NewSymbol("getAttribute"),
+ v8::FunctionTemplate::New(V8Element::getAttributeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("setAttribute"),
+ v8::FunctionTemplate::New(V8Element::setAttributeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("removeAttribute"),
+ v8::FunctionTemplate::New(V8Element::removeAttributeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getAttributeNode"),
+ v8::FunctionTemplate::New(V8Element::getAttributeNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("setAttributeNode"),
+ v8::FunctionTemplate::New(V8Element::setAttributeNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("removeAttributeNode"),
+ v8::FunctionTemplate::New(V8Element::removeAttributeNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getElementsByTagName"),
+ v8::FunctionTemplate::New(V8Element::getElementsByTagNameCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getAttributeNS"),
+ v8::FunctionTemplate::New(V8Element::getAttributeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("setAttributeNS"),
+ v8::FunctionTemplate::New(V8Element::setAttributeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("removeAttributeNS"),
+ v8::FunctionTemplate::New(V8Element::removeAttributeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getElementsByTagNameNS"),
+ v8::FunctionTemplate::New(V8Element::getElementsByTagNameNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("getAttributeNodeNS"),
+ v8::FunctionTemplate::New(V8Element::getAttributeNodeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("setAttributeNodeNS"),
+ v8::FunctionTemplate::New(V8Element::setAttributeNodeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("hasAttribute"),
+ v8::FunctionTemplate::New(V8Element::hasAttributeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("hasAttributeNS"),
+ v8::FunctionTemplate::New(V8Element::hasAttributeNSCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+
+ tmpl->Inherit(V8Node::getTmpl());
+ Tmpl = v8::Persistent<v8::FunctionTemplate>::New(tmpl);
+ }
+ return Tmpl;
+ }
+
+ };
+
+}
+
+
+#endif /* end of include guard: V8ELEMENT_H_B55C09NB */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.cpp
new file mode 100644
index 0000000..97a8c1a
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.cpp
@@ -0,0 +1,23 @@
+#include "V8Node.h"
+#include <DOM/Node.hpp>
+
+namespace uscxml {
+
+using namespace Arabica::DOM;
+
+v8::Persistent<v8::FunctionTemplate> V8Node::Tmpl;
+
+v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args) {
+ assert(args.Length() == 1);
+ assert(args[0]->IsObject());
+
+ v8::Local<v8::Object> self = args.Holder();
+
+ Node<std::string>* node = V8DOM::toClassPtr<Node<std::string> >(self->GetInternalField(0));
+ Node<std::string>* childToAppend = V8DOM::toClassPtr<Node<std::string> >(args[0]->ToObject()->GetInternalField(0));
+ node->appendChild(*childToAppend);
+
+ return v8::Undefined();
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.h
new file mode 100644
index 0000000..7048ab5
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8Node.h
@@ -0,0 +1,161 @@
+#ifndef V8NODE_H_9VGQMJNI
+#define V8NODE_H_9VGQMJNI
+
+#include "V8DOM.h"
+
+namespace uscxml {
+
+ class V8Node {
+ public:
+ static v8::Handle<v8::Value> nodeNameAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> nodeValueAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> nodeTypeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> parentNodeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> childNodesAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> firstChildAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> lastChildAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> previousSiblingAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> nextSiblingAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> attributesAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> ownerDocumentAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> namespaceURIAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> prefixAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> localNameAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> baseURIAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> textContentAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> parentElementAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+
+ static void nodeValueAttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { }
+ static void prefixAttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { }
+ static void textContentAttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { }
+
+ static v8::Handle<v8::Value> insertBeforeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> replaceChildCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> removeChildCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> appendChildCallback(const v8::Arguments& args);
+ static v8::Handle<v8::Value> hasChildNodesCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> cloneNodeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> normalizeCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> isSupportedCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> hasAttributesCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> lookupPrefixCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> isDefaultNamespaceCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> lookupNamespaceURICallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> addEventListenerCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> removeEventListenerCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ V8_DESTRUCTOR(Arabica::DOM::Node<std::string>);
+
+ static v8::Persistent<v8::FunctionTemplate> Tmpl;
+ static v8::Handle<v8::FunctionTemplate> getTmpl() {
+ if (Tmpl.IsEmpty()) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::New("Node"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ instance->SetInternalFieldCount(2);
+
+ instance->SetAccessor(v8::String::NewSymbol("nodeName"), V8Node::nodeNameAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("nodeValue"), V8Node::nodeValueAttrGetter, V8Node::nodeValueAttrSetter,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("nodeType"), V8Node::nodeTypeAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("parentNode"), V8Node::parentNodeAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("childNodes"), V8Node::childNodesAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("firstChild"), V8Node::firstChildAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("lastChild"), V8Node::lastChildAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("previousSibling"), V8Node::previousSiblingAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("nextSibling"), V8Node::nextSiblingAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("attributes"), V8Node::attributesAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("ownerDocument"), V8Node::ownerDocumentAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("namespaceURI"), V8Node::namespaceURIAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("prefix"), V8Node::prefixAttrGetter, V8Node::prefixAttrSetter,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("localName"), V8Node::localNameAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("baseURI"), V8Node::baseURIAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("textContent"), V8Node::textContentAttrGetter, V8Node::textContentAttrSetter,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("parentElement"), V8Node::parentElementAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+
+ prototype->Set(v8::String::NewSymbol("insertBefore"),
+ v8::FunctionTemplate::New(V8Node::insertBeforeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("replaceChild"),
+ v8::FunctionTemplate::New(V8Node::replaceChildCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("removeChild"),
+ v8::FunctionTemplate::New(V8Node::removeChildCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("appendChild"),
+ v8::FunctionTemplate::New(V8Node::appendChildCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("hasChildNodes"),
+ v8::FunctionTemplate::New(V8Node::hasChildNodesCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("cloneNode"),
+ v8::FunctionTemplate::New(V8Node::cloneNodeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("normalize"),
+ v8::FunctionTemplate::New(V8Node::normalizeCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("isSupported"),
+ v8::FunctionTemplate::New(V8Node::isSupportedCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("hasAttributes"),
+ v8::FunctionTemplate::New(V8Node::hasAttributesCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("lookupPrefix"),
+ v8::FunctionTemplate::New(V8Node::lookupPrefixCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("isDefaultNamespace"),
+ v8::FunctionTemplate::New(V8Node::isDefaultNamespaceCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("lookupNamespaceURI"),
+ v8::FunctionTemplate::New(V8Node::lookupNamespaceURICallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("addEventListener"),
+ v8::FunctionTemplate::New(V8Node::addEventListenerCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("removeEventListener"),
+ v8::FunctionTemplate::New(V8Node::removeEventListenerCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+
+ tmpl->Set(v8::String::NewSymbol("ELEMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ELEMENT_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("ELEMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ELEMENT_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("ATTRIBUTE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ATTRIBUTE_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("ATTRIBUTE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ATTRIBUTE_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("TEXT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::TEXT_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("TEXT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::TEXT_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("CDATA_SECTION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::CDATA_SECTION_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("CDATA_SECTION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::CDATA_SECTION_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("ENTITY_REFERENCE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ENTITY_REFERENCE_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("ENTITY_REFERENCE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ENTITY_REFERENCE_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("ENTITY_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ENTITY_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("ENTITY_NODE"), v8::Integer::New(Arabica::DOM::Node_base::ENTITY_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("PROCESSING_INSTRUCTION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::PROCESSING_INSTRUCTION_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("PROCESSING_INSTRUCTION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::PROCESSING_INSTRUCTION_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("COMMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::COMMENT_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("COMMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::COMMENT_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("DOCUMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("DOCUMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("DOCUMENT_TYPE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_TYPE_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("DOCUMENT_TYPE_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_TYPE_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("DOCUMENT_FRAGMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_FRAGMENT_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("DOCUMENT_FRAGMENT_NODE"), v8::Integer::New(Arabica::DOM::Node_base::DOCUMENT_FRAGMENT_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("NOTATION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::NOTATION_NODE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("NOTATION_NODE"), v8::Integer::New(Arabica::DOM::Node_base::NOTATION_NODE), v8::ReadOnly);
+ tmpl->Set(v8::String::NewSymbol("MAX_TYPE"), v8::Integer::New(Arabica::DOM::Node_base::MAX_TYPE), v8::ReadOnly);
+ prototype->Set(v8::String::NewSymbol("MAX_TYPE"), v8::Integer::New(Arabica::DOM::Node_base::MAX_TYPE), v8::ReadOnly);
+
+ Tmpl = v8::Persistent<v8::FunctionTemplate>::New(tmpl);
+ }
+ return Tmpl;
+ }
+
+ };
+
+}
+
+
+#endif /* end of include guard: V8NODE_H_9VGQMJNI */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.cpp
new file mode 100644
index 0000000..cadcf7f
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.cpp
@@ -0,0 +1,60 @@
+#include "V8NodeSet.h"
+#include "V8Element.h"
+#include "V8Node.h"
+#include <DOM/Node.hpp>
+
+namespace uscxml {
+
+using namespace Arabica::DOM;
+using namespace Arabica::XPath;
+
+v8::Persistent<v8::FunctionTemplate> V8NodeSet::Tmpl;
+
+
+v8::Handle<v8::Value> V8NodeSet::indexGetter(uint32_t index, const v8::AccessorInfo &info) {
+ v8::Local<v8::Object> self = info.Holder();
+
+ NodeSet<std::string>* nodeSet = V8DOM::toClassPtr<NodeSet<std::string> >(self->GetInternalField(0));
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+
+ if (nodeSet->size() >= index) {
+ switch((*nodeSet)[index].getNodeType()) {
+ case Node_base::ELEMENT_NODE: {
+ v8::Handle<v8::Function> elementCtor = V8Element::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> elementObj = v8::Persistent<v8::Object>::New(elementCtor->NewInstance());
+
+ Element<std::string>* element = new Element<std::string>((*nodeSet)[index]);
+
+ elementObj->SetInternalField(0, V8DOM::toExternal(element));
+ elementObj->SetInternalField(1, self->GetInternalField(1));
+ elementObj.MakeWeak(0, V8Element::jsDestructor);
+ return elementObj;
+ }
+ default: {
+ v8::Handle<v8::Function> nodeCtor = V8Node::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> nodeObj = v8::Persistent<v8::Object>::New(nodeCtor->NewInstance());
+
+ Node<std::string>* node = new Node<std::string>((*nodeSet)[index]);
+
+ nodeObj->SetInternalField(0, V8DOM::toExternal(node));
+ nodeObj->SetInternalField(1, self->GetInternalField(1));
+ nodeObj.MakeWeak(0, V8Node::jsDestructor);
+ return nodeObj;
+
+ }
+ }
+ }
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> V8NodeSet::lengthAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ v8::Local<v8::Object> self = info.Holder();
+
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+ NodeSet<std::string>* nodeSet = V8DOM::toClassPtr<NodeSet<std::string> >(self->GetInternalField(1));
+
+ return v8::Integer::New(nodeSet->size());
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.h
new file mode 100644
index 0000000..cb95a5d
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8NodeSet.h
@@ -0,0 +1,41 @@
+#ifndef V8NODESET_HPP_WKKXJ1RD
+#define V8NODESET_HPP_WKKXJ1RD
+
+#include "V8DOM.h"
+
+namespace uscxml {
+
+ class V8NodeSet {
+ public:
+ static v8::Handle<v8::Value> indexGetter(uint32_t index, const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> indexSetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> lengthAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
+
+ V8_DESTRUCTOR(Arabica::XPath::NodeSet<std::string>);
+
+ static v8::Persistent<v8::FunctionTemplate> Tmpl;
+ static v8::Handle<v8::FunctionTemplate> getTmpl() {
+ if (Tmpl.IsEmpty()) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::New("NodeSet"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ // v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ instance->SetInternalFieldCount(2);
+
+ instance->SetIndexedPropertyHandler(V8NodeSet::indexGetter, V8NodeSet::indexSetter);
+
+ instance->SetAccessor(v8::String::NewSymbol("length"), V8NodeSet::lengthAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+
+ Tmpl = v8::Persistent<v8::FunctionTemplate>::New(tmpl);
+ }
+ return Tmpl;
+ }
+
+ };
+
+}
+
+#endif /* end of include guard: V8NODESET_HPP_WKKXJ1RD */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp
deleted file mode 100644
index 585bdd7..0000000
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#endif
-#include "V8SCXMLDOM.h"
-
-#define ASSERT_ARGS1(args, type1) \
-assert(args.Length() == 1); \
-assert(args[0]->type1());
-
-#define ASSERT_ARGS2(args, type1, type2) \
-assert(args.Length() == 2); \
-assert(args[0]->type1()); \
-assert(args[1]->type2());
-
-namespace uscxml {
-
-using namespace Arabica::DOM;
-using namespace Arabica::XPath;
-
-V8SCXMLDOM::V8SCXMLDOM() {
-}
-
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getDocument(Arabica::DOM::Document<std::string>& document) {
- v8::Handle<v8::ObjectTemplate> documentTmpl = v8::ObjectTemplate::New();
- documentTmpl->Set(v8::String::New("createElement"), v8::FunctionTemplate::New(jsDocumentCreateElement, v8::External::New(reinterpret_cast<void*>(&document))));
- documentTmpl->Set(v8::String::New("evaluate"), v8::FunctionTemplate::New(jsDocumentEvaluate, v8::External::New(reinterpret_cast<void*>(&document))));
- return documentTmpl;
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsDocumentCreateElement(const v8::Arguments& args) {
- assert(!args.Data().IsEmpty());
- assert(args.Data()->IsExternal());
-
- ASSERT_ARGS1(args, IsString)
-
- Document<std::string>* document = static_cast<Document<std::string>*>(v8::External::Unwrap(args.Data()));
- v8::Persistent<v8::Object> elementJS = v8::Persistent<v8::Object>::New(getElementTmpl()->NewInstance());
-
- v8::String::AsciiValue tagName(args[0]);
- Element<std::string>* element = new Element<std::string>(document->createElement(*tagName));
-
- elementJS->SetInternalField(0, v8::External::New(element));
- elementJS.MakeWeak(NULL, jsElementDestructor);
- return elementJS;
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsDocumentEvaluate(const v8::Arguments& args) {
- assert(!args.Data().IsEmpty());
- assert(args.Data()->IsExternal());
-
- assert(args.Length() > 0);
- assert(args[0]->IsString());
-
-
- Document<std::string>* document = static_cast<Document<std::string>*>(v8::External::Unwrap(args.Data()));
- Node<std::string> context;
- if (args.Length() > 1) {
- assert(args[1]->ToObject()->InternalFieldCount() == 1);
- context = *static_cast<Node<std::string>*>(v8::Local<v8::External>::Cast(args[1]->ToObject()->GetInternalField(0))->Value());
- } else {
- context = *document;
- }
- v8::String::AsciiValue xpathExpr(args[0]);
- XPath<std::string> xpath;
- XPathValue<std::string>* xpathValue = new XPathValue<std::string>(xpath.evaluate(*xpathExpr, context));
-
- v8::Persistent<v8::Object> xpathValueJS = v8::Persistent<v8::Object>::New(getXPathValueTmpl()->NewInstance());
- xpathValueJS->SetInternalField(0, v8::External::New(xpathValue));
- xpathValueJS.MakeWeak(NULL, jsXPathValueDestructor);
- return xpathValueJS;
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsElementTagName(v8::Local<v8::String> property, const v8::AccessorInfo &info) {
- Element<std::string>* element = static_cast<Element<std::string>*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
- return v8::String::New(element->getTagName().c_str());
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsElementGetAttribute(const v8::Arguments& args) {
- assert(!args.Data().IsEmpty());
- assert(args.Data()->IsExternal());
-
- ASSERT_ARGS1(args, IsString);
-
- Element<std::string>* element = static_cast<Element<std::string>*>(v8::External::Unwrap(args.Data()));
-
- v8::String::AsciiValue attribute(args[0]);
- if (element->hasAttribute(*attribute)) {
- return v8::String::New(element->getAttribute(*attribute).c_str());
- }
- return v8::String::New("");
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsElementSetAttribute(const v8::Arguments& args) {
- v8::Local<v8::Object> self = args.Holder();
- assert(self->InternalFieldCount() == 1);
-
- ASSERT_ARGS2(args, IsString, IsString);
-
- v8::String::AsciiValue attribute(args[0]);
- v8::String::AsciiValue value(args[1]);
-
- Element<std::string>* element = static_cast<Element<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
- element->setAttribute(*attribute, *value);
- return v8::Undefined();
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsXPathValueAsNodeSet(const v8::Arguments& args) {
- v8::Local<v8::Object> self = args.Holder();
- assert(self->InternalFieldCount() == 1);
- XPathValue<std::string>* xPathValue = static_cast<XPathValue<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
-
- v8::Persistent<v8::Object> nodeSetJS = v8::Persistent<v8::Object>::New(getNodeSetTmpl()->NewInstance());
- nodeSetJS->SetInternalField(0, v8::External::New(new NodeSet<std::string>(xPathValue->asNodeSet())));
- nodeSetJS.MakeWeak(NULL, jsNodeSetDestructor);
- return nodeSetJS;
-
-}
-
-void V8SCXMLDOM::jsNodeSetDestructor(v8::Persistent<v8::Value> object, void* data) {
- NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
- delete nodeSet;
-}
-
-void V8SCXMLDOM::jsNodeDestructor(v8::Persistent<v8::Value> object, void* data) {
- Node<std::string>* node = static_cast<Node<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
- delete node;
-}
-
-void V8SCXMLDOM::jsXPathValueDestructor(v8::Persistent<v8::Value> object, void* data) {
- XPathValue<std::string>* xPathValue = static_cast<XPathValue<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
- delete xPathValue;
-}
-
-void V8SCXMLDOM::jsElementDestructor(v8::Persistent<v8::Value> object, void* data) {
- Element<std::string>* element = static_cast<Element<std::string>*>(v8::Local<v8::External>::Cast(object->ToObject()->GetInternalField(0))->Value());
- delete element;
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsNodeSetGetIndex(uint32_t index, const v8::AccessorInfo &info) {
- v8::Local<v8::Object> self = info.Holder();
- assert(self->InternalFieldCount() == 1);
- NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0))->Value());
-
- if (nodeSet->size() >= index) {
- Node<std::string>* node = new Node<std::string>((*nodeSet)[index]);
- v8::Persistent<v8::Object> nodeJS = v8::Persistent<v8::Object>::New(getNodeTmpl()->NewInstance());
- nodeJS->SetInternalField(0, v8::External::New(node));
- nodeJS.MakeWeak(NULL, jsNodeDestructor);
- return nodeJS;
- }
- return v8::Undefined();
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsNodeSetLength(const v8::Arguments& args) {
- v8::Local<v8::Object> self = args.Holder();
- assert(self->InternalFieldCount() == 1);
- NodeSet<std::string>* nodeSet = static_cast<NodeSet<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
- return v8::Integer::New(nodeSet->size());
-}
-
-v8::Handle<v8::Value> V8SCXMLDOM::jsNodeAppendChild(const v8::Arguments& args) {
- v8::Local<v8::Object> self = args.Holder();
- assert(self->InternalFieldCount() == 1);
- Node<std::string>* node = static_cast<Node<std::string>*>(v8::External::Unwrap(self->GetInternalField(0)));
-
- assert(args.Length() == 1);
- assert(args[0]->IsObject());
-
- Node<std::string>* childToAppend = static_cast<Node<std::string>*>(v8::External::Unwrap(args[0]->ToObject()->GetInternalField(0)));
- node->appendChild(*childToAppend);
-
- return v8::Undefined();
-}
-
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::xPathValueTmpl;
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getXPathValueTmpl() {
- if (xPathValueTmpl.IsEmpty()) {
- xPathValueTmpl = v8::ObjectTemplate::New();
- xPathValueTmpl->SetInternalFieldCount(1);
- xPathValueTmpl->Set(v8::String::New("asNodeSet"), v8::FunctionTemplate::New(jsXPathValueAsNodeSet));
- }
- return xPathValueTmpl;
-}
-
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::nodeSetTmpl;
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getNodeSetTmpl() {
- if (nodeSetTmpl.IsEmpty()) {
- nodeSetTmpl = v8::ObjectTemplate::New();
- nodeSetTmpl->SetInternalFieldCount(1);
- nodeSetTmpl->SetIndexedPropertyHandler(jsNodeSetGetIndex);
- nodeSetTmpl->Set(v8::String::New("length"), v8::FunctionTemplate::New(jsNodeSetLength));
- }
- return nodeSetTmpl;
-}
-
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::nodeTmpl;
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getNodeTmpl() {
- if (nodeTmpl.IsEmpty()) {
- nodeTmpl = v8::ObjectTemplate::New();
- nodeTmpl->SetInternalFieldCount(1);
- nodeTmpl->Set(v8::String::New("appendChild"), v8::FunctionTemplate::New(jsNodeAppendChild));
- }
- return nodeTmpl;
-}
-
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::elementTmpl;
-v8::Handle<v8::ObjectTemplate> V8SCXMLDOM::getElementTmpl() {
- if (elementTmpl.IsEmpty()) {
- elementTmpl = v8::ObjectTemplate::New();
- elementTmpl->SetAccessor(v8::String::New("tagName"), V8SCXMLDOM::jsElementTagName);
- elementTmpl->Set(v8::String::New("getAttribute"), v8::FunctionTemplate::New(jsElementGetAttribute));
- elementTmpl->Set(v8::String::New("setAttribute"), v8::FunctionTemplate::New(jsElementSetAttribute));
- elementTmpl->SetInternalFieldCount(1);
- }
- return elementTmpl;
-}
-
-} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h
deleted file mode 100644
index 36c6b15..0000000
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLDOM.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef V8SCXMLDOM_H_AREM0ZC4
-#define V8SCXMLDOM_H_AREM0ZC4
-
-#include "uscxml/Interpreter.h"
-
-#include <DOM/Document.hpp>
-#include <v8.h>
-
-#include <list>
-
-namespace uscxml {
-
-class V8SCXMLDOM {
-public:
- V8SCXMLDOM();
- virtual ~V8SCXMLDOM() {};
-
- static v8::Handle<v8::ObjectTemplate> getDocument(Arabica::DOM::Document<std::string>& document);
- static v8::Handle<v8::Value> jsDocumentCreateElement(const v8::Arguments& args);
- static v8::Handle<v8::Value> jsDocumentEvaluate(const v8::Arguments& args);
-
- static v8::Handle<v8::Value> jsElementTagName(v8::Local<v8::String> property, const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> jsElementGetAttribute(const v8::Arguments& args);
- static v8::Handle<v8::Value> jsElementSetAttribute(const v8::Arguments& args);
- static void jsElementDestructor(v8::Persistent<v8::Value> object, void* data);
-
- static v8::Handle<v8::Value> jsXPathValueAsNodeSet(const v8::Arguments& args);
- static void jsXPathValueDestructor(v8::Persistent<v8::Value> object, void* data);
-
- static v8::Handle<v8::Value> jsNodeSetGetIndex(uint32_t index, const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> jsNodeSetLength(const v8::Arguments& args);
- static void jsNodeSetDestructor(v8::Persistent<v8::Value> object, void* data);
-
- static v8::Handle<v8::Value> jsNodeAppendChild(const v8::Arguments& args);
- static void jsNodeDestructor(v8::Persistent<v8::Value> object, void* data);
-
- static v8::Handle<v8::ObjectTemplate> getXPathValueTmpl();
- static v8::Handle<v8::ObjectTemplate> getNodeSetTmpl();
- static v8::Handle<v8::ObjectTemplate> getNodeTmpl();
- static v8::Handle<v8::ObjectTemplate> getElementTmpl();
-
- static v8::Handle<v8::ObjectTemplate> xPathValueTmpl;
- static v8::Handle<v8::ObjectTemplate> nodeSetTmpl;
- static v8::Handle<v8::ObjectTemplate> nodeTmpl;
- static v8::Handle<v8::ObjectTemplate> elementTmpl;
-
-};
-
-class V8Node {
-};
-
-class V8DOMDocument {
- V8DOMDocument();
- virtual ~V8DOMDocument();
-
- v8::Handle<v8::Array> jsChildNodes();
-};
-
-}
-
-#endif /* end of include guard: V8SCXMLDOM_H_AREM0ZC4 */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.cpp
new file mode 100644
index 0000000..04bfcbe
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.cpp
@@ -0,0 +1,30 @@
+#include "V8XPathResult.h"
+#include "V8NodeSet.h"
+
+namespace uscxml {
+
+using namespace Arabica::DOM;
+using namespace Arabica::XPath;
+
+v8::Persistent<v8::FunctionTemplate> V8XPathResult::Tmpl;
+
+v8::Handle<v8::Value> V8XPathResult::asNodeSetCallback(const v8::Arguments& args) {
+
+ v8::Local<v8::Object> self = args.Holder();
+ XPathValue<std::string>* xpathValue = V8DOM::toClassPtr<XPathValue<std::string> >(self->GetInternalField(0));
+ V8DOM* dom = V8DOM::toClassPtr<V8DOM>(self->GetInternalField(1)); (void)dom;
+
+ v8::Handle<v8::Function> nodeSetCtor = V8NodeSet::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> nodeSetObj = v8::Persistent<v8::Object>::New(nodeSetCtor->NewInstance());
+
+ Arabica::XPath::NodeSet<std::string>* nodeSet = new Arabica::XPath::NodeSet<std::string>(xpathValue->asNodeSet());
+
+ nodeSetObj->SetInternalField(0, V8DOM::toExternal(nodeSet));
+ nodeSetObj->SetInternalField(1, self->GetInternalField(1));
+
+ nodeSetObj.MakeWeak(0, V8NodeSet::jsDestructor);
+ return nodeSetObj;
+
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.h
new file mode 100644
index 0000000..ce5e2d5
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8XPathResult.h
@@ -0,0 +1,75 @@
+#ifndef V8XPATHRESULT_HPP_AYZD0IRH
+#define V8XPATHRESULT_HPP_AYZD0IRH
+
+#include "V8DOM.h"
+
+namespace uscxml {
+ class V8XPathResult {
+ public:
+ static v8::Handle<v8::Value> resultTypeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> numberValueAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> stringValueAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> booleanValueAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> singleNodeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> invalidIteratorStateAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> snapshotLengthAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> iterateNextCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> snapshotItemCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ static v8::Handle<v8::Value> asNodeSetCallback(const v8::Arguments& args);
+ static v8::Handle<v8::Value> asBoolCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> asStringCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+ static v8::Handle<v8::Value> asNumberCallback(const v8::Arguments& args) { assert(false); return v8::Undefined(); }
+
+ V8_DESTRUCTOR(Arabica::XPath::XPathValue<std::string>);
+
+ static v8::Persistent<v8::FunctionTemplate> Tmpl;
+ static v8::Handle<v8::FunctionTemplate> getTmpl() {
+ if (Tmpl.IsEmpty()) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::New("XPathResult"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ instance->SetInternalFieldCount(2);
+
+ instance->SetAccessor(v8::String::NewSymbol("resultType"), V8XPathResult::resultTypeAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("numberValue"), V8XPathResult::numberValueAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("stringValue"), V8XPathResult::stringValueAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("booleanValue"), V8XPathResult::booleanValueAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("singleNode"), V8XPathResult::singleNodeAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("invalidIteratorState"), V8XPathResult::invalidIteratorStateAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+ instance->SetAccessor(v8::String::NewSymbol("snapshotLength"), V8XPathResult::snapshotLengthAttrGetter, 0,
+ v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+
+ prototype->Set(v8::String::NewSymbol("iterateNext"),
+ v8::FunctionTemplate::New(V8XPathResult::iterateNextCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("snapshotItem"),
+ v8::FunctionTemplate::New(V8XPathResult::snapshotItemCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("asNodeSet"),
+ v8::FunctionTemplate::New(V8XPathResult::asNodeSetCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("asBool"),
+ v8::FunctionTemplate::New(V8XPathResult::asBoolCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("asString"),
+ v8::FunctionTemplate::New(V8XPathResult::asStringCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+ prototype->Set(v8::String::NewSymbol("asNumber"),
+ v8::FunctionTemplate::New(V8XPathResult::asNumberCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+
+ Tmpl = v8::Persistent<v8::FunctionTemplate>::New(tmpl);
+ }
+ return Tmpl;
+ }
+
+ };
+}
+
+
+#endif /* end of include guard: V8XPATHRESULT_HPP_AYZD0IRH */
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
index 2712be3..7a0e63a 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
@@ -45,6 +45,13 @@ void OSGInvoker::sendToParent(SendRequest& req) {
void OSGInvoker::invoke(InvokeRequest& req) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+ // register default event handlers
+ Arabica::DOM::Events::EventTarget<std::string> evTarget = Arabica::DOM::Events::EventTarget<std::string>(req.dom);
+ evTarget.addEventListener("DOMSubtreeModified", *this, false);
+ evTarget.addEventListener("DOMNodeInserted", *this, false);
+ 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;
@@ -62,7 +69,19 @@ void OSGInvoker::runOnMainThread() {
_mutex.unlock();
}
}
-
+
+void OSGInvoker::handleEvent(Arabica::DOM::Events::Event<std::string>& event) {
+// std::cout << "Handling Event!" << std::endl;
+ Arabica::DOM::Node<std::string> node(event.getTarget());
+ if (_nodes.find(node) != _nodes.end()) {
+ osg::Node* osgNode = _nodes[node];
+ if (false) {
+ } else if (boost::iequals(LOCALNAME(node), "rotation")) {
+ updateRotation(osgNode, event);
+ }
+ }
+}
+
void OSGInvoker::processDisplay(const Arabica::DOM::Node<std::string>& element) {
// std::cout << element << std::endl;
@@ -108,13 +127,17 @@ void OSGInvoker::processViewport(const Arabica::DOM::Node<std::string>& element)
compDisp->addView(name, viewPort, sceneView);
std::set<std::string> validChilds;
+ validChilds.insert("camera");
validChilds.insert("translation");
validChilds.insert("rotation");
validChilds.insert("scale");
validChilds.insert("node");
- processChildren(validChilds, element);
+ processChildren(validChilds, element);
}
+void OSGInvoker::processCamera(const Arabica::DOM::Node<std::string>& element) {}
+void OSGInvoker::updateCamera(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event) {}
+
void OSGInvoker::processTranslation(const Arabica::DOM::Node<std::string>& element) {
assert(_nodes.find(element.getParentNode()) != _nodes.end());
osg::Node* node = _nodes[element.getParentNode()];
@@ -146,7 +169,31 @@ void OSGInvoker::processTranslation(const Arabica::DOM::Node<std::string>& eleme
void OSGInvoker::processRotation(const Arabica::DOM::Node<std::string>& element) {
assert(_nodes.find(element.getParentNode()) != _nodes.end());
osg::Node* node = _nodes[element.getParentNode()];
-
+
+ osg::Matrix rotation = rotationFromElement(element);
+ osg::MatrixTransform* transform = new osg::MatrixTransform();
+ transform->setMatrix(rotation);
+ node->asGroup()->addChild(transform);
+ _nodes[element] = transform;
+
+ std::set<std::string> validChilds;
+ validChilds.insert("translation");
+ validChilds.insert("rotation");
+ validChilds.insert("scale");
+ validChilds.insert("node");
+ processChildren(validChilds, element);
+}
+
+void OSGInvoker::updateRotation(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event) {
+ osg::MatrixTransform* transform = static_cast<osg::MatrixTransform*>(node);
+ if (false) {
+ } else if (boost::iequals(event.getType(), "DOMAttrModified")) {
+ osg::Matrix rotation = rotationFromElement(Arabica::DOM::Node<std::string>(event.getTarget()));
+ transform->setMatrix(rotation);
+ }
+}
+
+osg::Matrix OSGInvoker::rotationFromElement(const Arabica::DOM::Node<std::string>& element) {
double pitch = 0, roll = 0, yaw = 0;
if (HAS_ATTR(element, "pitch")) {
NumAttr pitchAttr = NumAttr(ATTR(element, "pitch"));
@@ -178,24 +225,13 @@ void OSGInvoker::processRotation(const Arabica::DOM::Node<std::string>& element)
yaw = strTo<float>(yawAttr.value);
}
}
-
+
osg::Matrix rotation;
rotation.makeRotate(roll, osg::Vec3(0,1,0), // roll
pitch, osg::Vec3(1,0,0) , // pitch
yaw, osg::Vec3(0,0,1) ); // heading
-
- osg::MatrixTransform* transform = new osg::MatrixTransform();
- transform->setMatrix(rotation);
- node->asGroup()->addChild(transform);
- _nodes[element] = transform;
-
- std::set<std::string> validChilds;
- validChilds.insert("translation");
- validChilds.insert("rotation");
- validChilds.insert("scale");
- validChilds.insert("node");
- processChildren(validChilds, element);
+ return rotation;
}
void OSGInvoker::processScale(const Arabica::DOM::Node<std::string>& element) {
@@ -227,6 +263,9 @@ void OSGInvoker::processScale(const Arabica::DOM::Node<std::string>& element) {
}
void OSGInvoker::processNode(const Arabica::DOM::Node<std::string>& element) {
+ _nodes_t::iterator nodeIter = _nodes.find(element.getParentNode());
+ assert(nodeIter != _nodes.end());
+
assert(_nodes.find(element.getParentNode()) != _nodes.end());
osg::Node* parent = _nodes[element.getParentNode()];
@@ -276,6 +315,9 @@ void OSGInvoker::processChildren(const std::set<std::string>& validChildren, con
} else if (boost::iequals(LOCALNAME(childs.item(i)), "viewport") &&
validChildren.find("viewport") != validChildren.end()) {
processViewport(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "camera") &&
+ validChildren.find("camera") != validChildren.end()) {
+ processCamera(childs.item(i));
} else if (boost::iequals(LOCALNAME(childs.item(i)), "display") &&
validChildren.find("display") != validChildren.end()) {
processDisplay(childs.item(i));
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
index cf1556e..90dda31 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
@@ -2,6 +2,9 @@
#define OSGINVOKER_H_H6T4R8HU
#include <uscxml/Interpreter.h>
+#include <DOM/Events/MutationEvent.hpp>
+#include <DOM/Events/EventListener.hpp>
+#include <DOM/Events/Event.hpp>
#include "CompositeDisplay.h"
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
@@ -13,7 +16,7 @@
namespace uscxml {
-class OSGInvoker : public Invoker {
+class OSGInvoker : public Invoker, public Arabica::DOM::Events::EventListener<std::string> {
public:
OSGInvoker();
virtual ~OSGInvoker();
@@ -32,16 +35,30 @@ public:
virtual void cancel(const std::string sendId);
virtual void invoke(InvokeRequest& req);
virtual void sendToParent(SendRequest& req);
+ virtual void handleEvent(Arabica::DOM::Events::Event<std::string>& event);
virtual void runOnMainThread();
protected:
void processDisplay(const Arabica::DOM::Node<std::string>& element);
+ void updateDisplay(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
void processViewport(const Arabica::DOM::Node<std::string>& element);
+ void updateViewport(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
+ void processCamera(const Arabica::DOM::Node<std::string>& element);
+ void updateCamera(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
+
void processTranslation(const Arabica::DOM::Node<std::string>& element);
+ void updateTranslation(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
+
void processRotation(const Arabica::DOM::Node<std::string>& element);
+ void updateRotation(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
+ static osg::Matrix rotationFromElement(const Arabica::DOM::Node<std::string>& element);
+
void processScale(const Arabica::DOM::Node<std::string>& element);
+ void updateScale(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
void processNode(const Arabica::DOM::Node<std::string>& element);
+ void updateNode(osg::Node* node, Arabica::DOM::Events::Event<std::string>& event);
+
void processChildren(const std::set<std::string>& validChildren, const Arabica::DOM::Node<std::string>& element);
void getViewport(const Arabica::DOM::Node<std::string>& element,
diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp
new file mode 100644
index 0000000..6bc06d9
--- /dev/null
+++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.cpp
@@ -0,0 +1,95 @@
+#include "HeartbeatInvoker.h"
+#include <glog/logging.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include <Pluma/Connector.hpp>
+#endif
+
+namespace uscxml {
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_CONNECTOR
+bool connect(pluma::Host& host) {
+ host.add( new HeartbeatInvokerProvider() );
+ return true;
+}
+#endif
+
+HeartbeatInvoker::HeartbeatInvoker() {
+}
+
+HeartbeatInvoker::~HeartbeatInvoker() {
+};
+
+Invoker* HeartbeatInvoker::create(Interpreter* interpreter) {
+ HeartbeatInvoker* invoker = new HeartbeatInvoker();
+ invoker->_interpreter = interpreter;
+ return invoker;
+}
+
+Data HeartbeatInvoker::getDataModelVariables() {
+ Data data;
+ return data;
+}
+
+void HeartbeatInvoker::send(SendRequest& req) {
+}
+
+void HeartbeatInvoker::cancel(const std::string sendId) {
+ HeartbeatDispatcher::getInstance()->cancelEvent(toStr(this));
+}
+
+void HeartbeatInvoker::sendToParent(SendRequest& req) {
+}
+
+void HeartbeatInvoker::invoke(InvokeRequest& req) {
+ _invokeId = req.invokeid;
+ _event.invokeid = _invokeId;
+ std::string intervalStr;
+ double interval = 0;
+ unsigned long intervalMs = 0;
+ InvokeRequest::params_t::iterator paramIter = req.params.begin();
+ while(paramIter != req.params.end()) {
+ if (boost::iequals(paramIter->first, "interval")) {
+ intervalStr = paramIter->second;
+ NumAttr intervalAttr(paramIter->second);
+ interval = strTo<double>(intervalAttr.value);
+ if (false) {
+ } else if (boost::iequals(intervalAttr.unit, "s")) {
+ intervalMs = interval * 1000;
+ } else if (boost::iequals(intervalAttr.unit, "ms")) {
+ intervalMs = interval;
+ } else {
+ intervalMs = interval;
+ }
+ }
+ if (boost::iequals(paramIter->first, "eventname")) {
+ _event.name = paramIter->second;
+ }
+ paramIter++;
+ }
+ if (_event.name.length() == 0)
+ _event.name = std::string("heartbeat." + intervalStr);
+
+ if (intervalMs > 0) {
+ HeartbeatDispatcher::getInstance()->addEvent(toStr(this), HeartbeatInvoker::dispatch, intervalMs, this, true);
+ }
+}
+
+void HeartbeatInvoker::dispatch(void* instance, std::string name) {
+ HeartbeatInvoker* invoker = (HeartbeatInvoker*)instance;
+ invoker->_interpreter->receive(invoker->_event);
+}
+
+HeartbeatDispatcher* HeartbeatDispatcher::_instance = NULL;
+HeartbeatDispatcher* HeartbeatDispatcher::getInstance() {
+ if (_instance == NULL) {
+ _instance = new HeartbeatDispatcher();
+ _instance->start();
+ }
+ return _instance;
+}
+
+HeartbeatDispatcher::HeartbeatDispatcher() {}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h
new file mode 100644
index 0000000..9a6cb47
--- /dev/null
+++ b/src/uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h
@@ -0,0 +1,54 @@
+#ifndef HEARTBEATINVOKER_H_W09J90F0
+#define HEARTBEATINVOKER_H_W09J90F0
+
+#include <uscxml/Interpreter.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+namespace uscxml {
+
+class HeartbeatInvoker : public Invoker {
+public:
+ HeartbeatInvoker();
+ virtual ~HeartbeatInvoker();
+ virtual Invoker* create(Interpreter* interpreter);
+
+ virtual std::set<std::string> getNames() {
+ std::set<std::string> names;
+ names.insert("heartbeat");
+ names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#heartbaet");
+ return names;
+ }
+
+ virtual Data getDataModelVariables();
+ virtual void send(SendRequest& req);
+ virtual void cancel(const std::string sendId);
+ virtual void invoke(InvokeRequest& req);
+ virtual void sendToParent(SendRequest& req);
+
+ static void dispatch(void* instance, std::string name);
+
+protected:
+ std::string _invokeId;
+ Event _event;
+
+};
+
+class HeartbeatDispatcher : public DelayedEventQueue {
+public:
+ static HeartbeatDispatcher* getInstance();
+protected:
+ static HeartbeatDispatcher* _instance;
+ HeartbeatDispatcher();
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(HeartbeatInvoker, Invoker);
+#endif
+
+}
+
+
+#endif /* end of include guard: HEARTBEATINVOKER_H_W09J90F0 */
diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
index b5c351c..f115c25 100644
--- a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
+++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
@@ -42,6 +42,7 @@ void SampleInvoker::sendToParent(SendRequest& req) {
}
void SampleInvoker::invoke(InvokeRequest& req) {
+ _invokeId = req.invokeid;
}
} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
index ee6c903..9957bfa 100644
--- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
+++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
@@ -1,5 +1,6 @@
#include "UmundoInvoker.h"
#include <glog/logging.h>
+#include "uscxml/URL.h"
#ifdef BUILD_AS_PLUGINS
#include <Pluma/Connector.hpp>
@@ -15,12 +16,16 @@ bool connect(pluma::Host& host) {
}
#endif
-UmundoInvoker::UmundoInvoker() {
+UmundoInvoker::UmundoInvoker() : _node(NULL), _pub(NULL), _sub(NULL) {
}
UmundoInvoker::~UmundoInvoker() {
- _node.removeSubscriber(_sub);
- _node.removePublisher(_pub);
+ if (_node) {
+ if (_sub)
+ _node->removeSubscriber(*_sub);
+ if (_pub)
+ _node->removePublisher(*_pub);
+ }
};
Invoker* UmundoInvoker::create(Interpreter* interpreter) {
@@ -63,8 +68,8 @@ void UmundoInvoker::send(SendRequest& req) {
} else {
// add all s11n properties
if (!_isService) {
- _pub.prepareMsg(msg, type, pbMsg);
- _pub.send(msg);
+ _pub->prepareMsg(msg, type, pbMsg);
+ _pub->send(msg);
} else {
std::map<umundo::ServiceDescription, umundo::ServiceStub*>::iterator svcIter = _svcs.begin();
while(svcIter != _svcs.end()) {
@@ -107,11 +112,12 @@ void UmundoInvoker::sendToParent(SendRequest& req) {
void UmundoInvoker::invoke(InvokeRequest& req) {
_invokeId = req.invokeid;
+ std::string domain;
std::string channelName;
std::string serviceName;
if (req.params.find("channel") != req.params.end()) {
- channelName = req.params.find("type")->second;
+ channelName = req.params.find("channel")->second;
_isService = false;
} else if (req.params.find("service") != req.params.end()) {
serviceName = req.params.find("service")->second;
@@ -120,34 +126,50 @@ void UmundoInvoker::invoke(InvokeRequest& req) {
LOG(ERROR) << "Invoking umundo needs a service or a channel param";
return;
}
+ if (req.params.find("domain") != req.params.end()) {
+ domain = req.params.find("domain")->second;
+ }
+ _node = getNode(_interpreter, domain);
- _node = getNode(_interpreter);
-
- // add types from .proto or .desc files
- if (req.params.find("types") != req.params.end()) {
+ // add type from .proto or .desc files
+ if (req.params.find("type") != req.params.end()) {
std::pair<InvokeRequest::params_t::iterator, InvokeRequest::params_t::iterator> typeRange = req.params.equal_range("types");
for (InvokeRequest::params_t::iterator it = typeRange.first; it != typeRange.second; it++) {
- Arabica::io::URI srcURI(it->first);
- // if (!_interpreter->makeAbsolute(srcURI)) {
- // LOG(ERROR) << "Relative URI for types in umundo invoker " << *typeIter << " with no base URI set for interpreter";
- // return;
- // }
- umundo::PBSerializer::addProto(srcURI.path());
+ URL typeURI(it->second);
+ if (typeURI.toAbsolute(_interpreter->getBaseURI())) {
+ std::string filename = typeURI.asLocalFile(".proto");
+ umundo::PBSerializer::addProto(filename);
+ } else {
+ LOG(ERROR) << "umundo invoker has relative type src but nor baseURI set with interpreter.";
+ }
}
}
+ // add directory with .proto or .desc files
+ if (req.params.find("types") != req.params.end()) {
+ std::pair<InvokeRequest::params_t::iterator, InvokeRequest::params_t::iterator> typeRange = req.params.equal_range("types");
+ for (InvokeRequest::params_t::iterator it = typeRange.first; it != typeRange.second; it++) {
+ URL typeURI(it->second);
+ if (typeURI.toAbsolute(_interpreter->getBaseURI()) && typeURI.scheme().compare("file") == 0) {
+ umundo::PBSerializer::addProto(typeURI.path());
+ } else {
+ LOG(ERROR) << "invoke element has relative src URI with no baseURI set.";
+ }
+ }
+ }
+
if (!_isService) {
// use umundo to publish objects on a channel
- _pub = umundo::TypedPublisher(channelName);
- _sub = umundo::TypedSubscriber(channelName, this);
+ _pub = new umundo::TypedPublisher(channelName);
+ _sub = new umundo::TypedSubscriber(channelName, this);
- _node.addPublisher(_pub);
- _node.addSubscriber(_sub);
+ _node->addPublisher(*_pub);
+ _node->addSubscriber(*_sub);
} else if (serviceName.length() > 0) {
// use umundo to access services
_svcFilter = umundo::ServiceFilter(serviceName);
- _node.connect(&_svcMgr);
+ _node->connect(&_svcMgr);
_svcMgr.startQuery(_svcFilter, this);
}
}
@@ -233,12 +255,17 @@ void UmundoInvoker::removed(umundo::ServiceDescription desc) {
void UmundoInvoker::changed(umundo::ServiceDescription desc) {
}
-std::map<std::string, umundo::Node> UmundoInvoker::_nodes;
-umundo::Node UmundoInvoker::getNode(Interpreter* interpreter) {
- if ((_nodes.find(interpreter->getName()) == _nodes.end())) {
- _nodes[interpreter->getName()] = umundo::Node();
- }
- return _nodes[interpreter->getName()];
+std::multimap<std::string, std::pair<std::string, umundo::Node*> > UmundoInvoker::_nodes;
+umundo::Node* UmundoInvoker::getNode(Interpreter* interpreter, const std::string& domain) {
+ std::pair<_nodes_t::iterator, _nodes_t::iterator> range = _nodes.equal_range(interpreter->getName());
+ for (_nodes_t::iterator it = range.first; it != range.second; it++) {
+ if (it->second.first.compare(domain) == 0)
+ return it->second.second;
+ }
+ umundo::Node* node = new umundo::Node(domain);
+ std::pair<std::string, std::pair<std::string, umundo::Node*> > pair = std::make_pair(interpreter->getName(), std::make_pair(domain, node));
+ _nodes.insert(pair);
+ return node;
}
bool UmundoInvoker::protobufToData(Data& data, const google::protobuf::Message& msg) {
diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h
index 72fcc9b..09d07bf 100644
--- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h
+++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.h
@@ -49,16 +49,17 @@ protected:
bool dataToProtobuf(google::protobuf::Message* msg, Data& data);
bool protobufToData(Data& data, const google::protobuf::Message& msg);
- umundo::TypedPublisher _pub;
- umundo::TypedSubscriber _sub;
- umundo::Node _node;
+ umundo::Node* _node;
+ umundo::TypedPublisher* _pub;
+ umundo::TypedSubscriber* _sub;
umundo::ServiceFilter _svcFilter;
umundo::ServiceManager _svcMgr;
std::map<umundo::ServiceDescription, umundo::ServiceStub*> _svcs;
- static std::map<std::string, umundo::Node> _nodes;
- static umundo::Node getNode(Interpreter* interpreter);
+ static std::multimap<std::string, std::pair<std::string, umundo::Node*> > _nodes;
+ typedef std::multimap<std::string, std::pair<std::string, umundo::Node*> > _nodes_t;
+ static umundo::Node* getNode(Interpreter* interpreter, const std::string& domain);
};
#ifdef BUILD_AS_PLUGINS
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
index 78ecbe3..a50dcaf 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
@@ -313,6 +313,8 @@ void EventIOServer::registerProcessor(EventIOProcessor* processor) {
INSTANCE->_processors[actualPath.str()] = processor;
processor->setURL(processorURL.str());
+ LOG(INFO) << "SCXML listening at: " << processorURL.str() << std::endl;
+
evhttp_set_cb(INSTANCE->_http, ("/" + actualPath.str()).c_str(), EventIOProcessor::httpRecvReq, processor);
// evhttp_set_cb(THIS->_http, "/", EventIOProcessor::httpRecvReq, processor);
// evhttp_set_gencb(THIS->_http, EventIOProcessor::httpRecvReq, NULL);
@@ -332,7 +334,6 @@ void EventIOServer::start() {
void EventIOServer::run(void* instance) {
EventIOServer* INSTANCE = (EventIOServer*)instance;
while(INSTANCE->_isRunning) {
- LOG(INFO) << "Dispatching HTTP Server" << std::endl;
event_base_dispatch(INSTANCE->_base);
}
LOG(INFO) << "HTTP Server stopped" << std::endl;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index d47364e..39a4667 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -48,3 +48,8 @@ add_executable(test-completion src/test-completion.cpp)
target_link_libraries(test-completion uscxml)
add_test(test-completion ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-completion ${CMAKE_SOURCE_DIR}/test/samples/uscxml/test-donedata.scxml)
set_target_properties(test-completion PROPERTIES FOLDER "Tests")
+
+add_executable(test-arabica-events src/test-arabica-events.cpp)
+target_link_libraries(test-arabica-events uscxml)
+add_test(test-arabica-events ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-arabica-events ${CMAKE_SOURCE_DIR}/test/samples/arabica/test-arabica-events.xml)
+set_target_properties(test-arabica-events PROPERTIES FOLDER "Tests")
diff --git a/test/samples/uscxml/applications/3dviewer.scxml b/test/samples/uscxml/applications/3dviewer.scxml
new file mode 100644
index 0000000..90970d3
--- /dev/null
+++ b/test/samples/uscxml/applications/3dviewer.scxml
@@ -0,0 +1,84 @@
+<scxml
+ datamodel="ecmascript"
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:scenegraph="http://uscxml.tk.informatik.tu-darmstadt.de/scenegraph.xsd">
+ <datamodel>
+ <data id="localCam" />
+ <data id="foo" />
+ </datamodel>
+ <state id="start">
+ <!-- setup all invokers -->
+
+ <!-- 20ms heartbeat -->
+ <invoke type="heartbeat" id="heartbeat.20ms">
+ <param name="interval" expr="'20ms'" />
+ </invoke>
+
+ <!-- receive files -->
+ <invoke type="umundo" id="umundo.files">
+ <param name="domain" expr="''" />
+ <param name="channel" expr="'umundo.files'" />
+ <param name="types" expr="'../proto/3DViewer'" />
+ </invoke>
+
+ <!-- publish / subscribe to remote pose -->
+ <invoke type="umundo" id="umundo.pose">
+ <param name="domain" expr="''" />
+ <param name="channel" expr="'umundo.pose'" />
+ <param name="types" expr="'../proto/3DViewer'" />
+ </invoke>
+
+ <!-- 3D viewer
+ This is only a template for nodes inserted per javascript
+ -->
+ <invoke type="scenegraph">
+ <content>
+ <scenegraph:display id="localDisplay" width="50%" height="50%">
+ <scenegraph:viewport>
+ <scenegraph:camera id="localCam">
+ </scenegraph:camera>
+ <scenegraph:translation>
+ <scenegraph:rotation>
+ <scenegraph:scale>
+ <scenegraph:node />
+ </scenegraph:scale>
+ </scenegraph:rotation>
+ </scenegraph:translation>
+ </scenegraph:viewport>
+ </scenegraph:display>
+ </content>
+ </invoke>
+ <state id="sendPose">
+ <transition target="sendPose" event="heartbeat.20ms" />
+ <onentry>
+ <script>
+ localCam = document.evaluate("//scenegraph:display[@id='localDisplay']").asNodeSet();
+ print(localCam[0].getAttribute("pitch"));
+ </script>
+ <send target="#_umundo.pose" event="umundo.pose">
+ <param name="type" expr="'SceneSetup'" />
+ <content>
+({
+ 'camPose': {
+ 'euler': {
+ 'pitch': localCam.getAttribute("pitch"),
+ 'roll': localCam.getAttribute("roll"),
+ 'yaw': localCam.getAttribute("yaw"),
+ }
+ },
+ 'modelPose': {
+ 'euler': {
+ 'pitch': localCam.getAttribute("pitch"),
+ 'roll': localCam.getAttribute("roll"),
+ 'yaw': localCam.getAttribute("yaw"),
+ }
+ },
+ 'modelName': "foo",
+ 'bandName': "foo"
+})
+ </content>
+ </send>
+ </onentry>
+ </state>
+ </state>
+</scxml> \ No newline at end of file
diff --git a/test/samples/uscxml/arabica/test-arabica-events.xml b/test/samples/uscxml/arabica/test-arabica-events.xml
new file mode 100644
index 0000000..8998fd9
--- /dev/null
+++ b/test/samples/uscxml/arabica/test-arabica-events.xml
@@ -0,0 +1,10 @@
+<root>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <h1>This is Foo!</h1>
+ <p>This not supposed to be valid HTML</p>
+ <div id="container" />
+ </body>
+</root> \ No newline at end of file
diff --git a/test/samples/uscxml/proto/3DViewer/CameraPos.proto b/test/samples/uscxml/proto/3DViewer/CameraPos.proto
new file mode 100644
index 0000000..6178ef4
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/CameraPos.proto
@@ -0,0 +1,9 @@
+import "LinearAlgebra.proto";
+
+message CameraPos {
+ required Vector3 center = 1;
+ required Quaternion rotation = 2;
+ required double distance = 3;
+ required double lastFrameTime = 4;
+ required bool thrown = 5 [default = false];
+} \ No newline at end of file
diff --git a/test/samples/uscxml/proto/3DViewer/DirectoryListingService.proto b/test/samples/uscxml/proto/3DViewer/DirectoryListingService.proto
new file mode 100644
index 0000000..4a0e412
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/DirectoryListingService.proto
@@ -0,0 +1,48 @@
+option java_package = "org.umundo.filesystem";
+
+message DirectoryEntry {
+ enum Type {
+ NAMED_PIPE = 0;
+ CHAR_DEV = 1;
+ BLOCK_DEV = 2;
+ FILE = 3;
+ DIR = 4;
+ SYMLINK = 5;
+ SOCKET = 6;
+ UNKNOWN = 7;
+ }
+ required string name = 1;
+ required Type type = 2;
+ required string path = 3;
+ required int64 size = 4;
+ optional string extension = 5;
+
+ repeated string segments = 6;
+
+ optional int64 atime_ms = 11;
+ optional int64 ctime_ms = 12;
+ optional int64 mtime_ms = 13;
+ optional int64 btime_ms = 14;
+
+ required string hostId = 15;
+
+}
+
+message DirectoryListingRequest {
+ required string pattern = 1;
+}
+
+message DirectoryListingReply {
+ repeated DirectoryEntry entries = 1;
+}
+
+message DirectoryEntryContent {
+ required bytes content = 1;
+ required string md5 = 2;
+}
+
+service DirectoryListingService {
+ rpc list (DirectoryListingRequest) returns (DirectoryListingReply);
+ rpc get (DirectoryEntry) returns (DirectoryEntryContent);
+}
+
diff --git a/test/samples/uscxml/proto/3DViewer/LinearAlgebra.proto b/test/samples/uscxml/proto/3DViewer/LinearAlgebra.proto
new file mode 100644
index 0000000..135ed00
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/LinearAlgebra.proto
@@ -0,0 +1,18 @@
+message Quaternion {
+ required double w = 1;
+ required double x = 2;
+ required double y = 3;
+ required double z = 4;
+}
+
+message Vector3 {
+ required double x = 1 [default = 0];
+ required double y = 2 [default = 0];
+ required double z = 3 [default = 0];
+}
+
+message Matrix3 {
+ required Vector3 x = 1;
+ required Vector3 y = 2;
+ required Vector3 z = 3;
+}
diff --git a/test/samples/uscxml/proto/3DViewer/ModelInfo.proto b/test/samples/uscxml/proto/3DViewer/ModelInfo.proto
new file mode 100644
index 0000000..3214a71
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/ModelInfo.proto
@@ -0,0 +1,10 @@
+import "LinearAlgebra.proto";
+
+message ModelInfo {
+ required string name = 1;
+ required string description = 2;
+}
+
+message Annotation {
+ required Vector3 position = 1;
+} \ No newline at end of file
diff --git a/test/samples/uscxml/proto/3DViewer/Pose.proto b/test/samples/uscxml/proto/3DViewer/Pose.proto
new file mode 100644
index 0000000..c29d6ff
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/Pose.proto
@@ -0,0 +1,22 @@
+import "LinearAlgebra.proto";
+
+message EulerAngles {
+ required double pitch = 1 [default = 0];
+ required double roll = 2 [default = 0];
+ required double yaw = 3 [default = 0];
+}
+
+message Heading {
+ required Vector3 direction = 1;
+ optional double timestamp = 2;
+ optional double magneticHeading = 3;
+ optional double trueHeading = 4;
+}
+
+message Pose {
+ optional Matrix3 orientation = 1;
+ optional EulerAngles euler = 2;
+ optional Vector3 position = 3;
+ optional Heading heading = 4;
+ optional double timestamp = 5;
+}
diff --git a/test/samples/uscxml/proto/3DViewer/SceneSetup.proto b/test/samples/uscxml/proto/3DViewer/SceneSetup.proto
new file mode 100644
index 0000000..b3b7697
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/SceneSetup.proto
@@ -0,0 +1,8 @@
+import "Pose.proto";
+
+message SceneSetup {
+ optional Pose modelPose = 1;
+ optional Pose camPose = 2;
+ required string modelName = 3;
+ required string bandName = 4;
+} \ No newline at end of file
diff --git a/test/samples/uscxml/proto/3DViewer/SceneShotService.proto b/test/samples/uscxml/proto/3DViewer/SceneShotService.proto
new file mode 100644
index 0000000..c7412a3
--- /dev/null
+++ b/test/samples/uscxml/proto/3DViewer/SceneShotService.proto
@@ -0,0 +1,24 @@
+import "SceneSetup.proto";
+
+message SceneShotReply {
+ optional bytes data = 1;
+ optional string base64 = 2;
+ optional string url = 3;
+ required uint32 width = 4;
+ required uint32 height = 5;
+}
+
+message SceneShotRequest {
+ required uint32 width = 1 [default = 640];
+ required uint32 height = 2 [default = 480];
+ optional string format = 3 [default = "png"];
+ optional string filename = 4;
+ optional SceneSetup sceneSetup = 5;
+ optional double pitch = 6;
+ optional double roll = 7;
+ optional double zoom = 8;
+}
+
+service SceneShotService {
+ rpc sceneShot (SceneShotRequest) returns (SceneShotReply);
+}
diff --git a/test/samples/uscxml/scripts/test-simple-ecmascript.scxml b/test/samples/uscxml/scripts/test-simple-ecmascript.scxml
new file mode 100644
index 0000000..10dee02
--- /dev/null
+++ b/test/samples/uscxml/scripts/test-simple-ecmascript.scxml
@@ -0,0 +1,12 @@
+<scxml datamodel="ecmascript">
+ <state id="start">
+ <onentry>
+ <script>
+ var nodeSet = document.evaluate("//state").asNodeSet();
+ nodeSet[0].setAttribute("foo", "bar");
+ </script>
+ <raise event="redo" />
+ </onentry>
+ <transition target="start" event="redo" />
+ </state>
+</scxml> \ No newline at end of file
diff --git a/test/samples/uscxml/test-scenegraph.scxml b/test/samples/uscxml/test-scenegraph.scxml
index 25e13ed..0efcd6d 100644
--- a/test/samples/uscxml/test-scenegraph.scxml
+++ b/test/samples/uscxml/test-scenegraph.scxml
@@ -1,5 +1,16 @@
-<scxml datamodel="ecmascript" initial="start" binding="late" xmlns:scenegraph="http://uscxml.tk.informatik.tu-darmstadt.de/scenegraph.xsd">
+<scxml datamodel="ecmascript" initial="start" binding="late"
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:scenegraph="http://uscxml.tk.informatik.tu-darmstadt.de/scenegraph.xsd">
+ <datamodel>
+ <data id="pitch">0</data>
+ <data id="yaw">0</data>
+ <data id="roll">0</data>
+ </datamodel>
<state id="start">
+ <invoke type="heartbeat">
+ <param name="interval" expr="'10ms'" />
+ <param name="eventname" expr="'heartbeat.20ms'" />
+ </invoke>
<invoke type="scenegraph">
<content>
<scenegraph:display x="10%" y="10 %" width="50 % " height=" 50 % ">
@@ -10,13 +21,8 @@
</scenegraph:translation>
</scenegraph:scale>
</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://cs.iupui.edu/~aharris/mm/vrml4/house.wrl" />
- </scenegraph:translation>
- </scenegraph:viewport>
<scenegraph:viewport x="0" y="50%" width="50%" height="50%" id="scene3">
- <scenegraph:rotation pitch="100deg" roll="3.15149rad" yaw="10deg">
+ <scenegraph:rotation id="treeRotation" pitch="100deg" roll="3.15149rad" yaw="10deg">
<scenegraph:node src="http://cs.iupui.edu/~aharris/webDesign/vrml/tree.wrl" />
</scenegraph:rotation>
</scenegraph:viewport>
@@ -25,17 +31,36 @@
<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://cs.iupui.edu/~aharris/mm/vrml4/house.wrl" />
+ </scenegraph:translation>
+ </scenegraph:viewport>
</scenegraph:display>
- <!-- scenegraph:display x="20%" y="20 %" width="50 % " height=" 50 % ">
- <scenegraph:viewport x="0" y="0" width="50%" height="50%" id="scene1">
+ <scenegraph:display x="20%" y="20 %" width="50 % " height=" 50 % ">
+ <scenegraph:viewport x="0" y="0" width="100%" height="100%" id="scene1">
<scenegraph:translation x="0" y="0" z="0">
<scenegraph:node src="scenegraph/HARD_MP_VAL_000.wrl" />
</scenegraph:translation>
</scenegraph:viewport>
- </scenegraph:display -->
+ </scenegraph:display>
</content>
</invoke>
+ <state id="animate">
+ <onentry>
+ <script>
+ var nodeSet = document.evaluate("//scenegraph:rotation[@id='treeRotation']").asNodeSet();
+ nodeSet[0].setAttribute("pitch", "pitch" + pitch + "deg");
+ nodeSet[0].setAttribute("roll", "roll" + roll + "deg");
+ nodeSet[0].setAttribute("yaw", "yaw" + yaw + "deg");
+ pitch += 0.5;
+ roll += 0.3;
+ yaw += 0.1;
+ </script>
+ </onentry>
+ <transition event="heartbeat.20ms" target="animate" />
+ </state>
</state>
<final id="final">
<onentry>
diff --git a/test/src/test-arabica-events.cpp b/test/src/test-arabica-events.cpp
new file mode 100644
index 0000000..fcf4ea8
--- /dev/null
+++ b/test/src/test-arabica-events.cpp
@@ -0,0 +1,61 @@
+#include <XPath/XPath.hpp>
+#include <DOM/Document.hpp>
+#include <DOM/SAX2DOM/SAX2DOM.hpp>
+#include <SAX/helpers/CatchErrorHandler.hpp>
+#include <DOM/Events/EventTarget.hpp>
+#include <DOM/Events/EventListener.hpp>
+
+using namespace Arabica::DOM;
+
+class CapturingEventListener : public Events::EventListener<std::string> {
+public:
+ void handleEvent(Events::Event<std::string>& event) {
+ std::cout << "Handling captured event " << event.getType() << std::endl;
+ }
+};
+
+class BubblingEventListener : public Events::EventListener<std::string> {
+public:
+ void handleEvent(Events::Event<std::string>& event) {
+ std::cout << "Handling bubbling event " << event.getType() << std::endl;
+ }
+};
+
+int main(int argc, char** argv) {
+ Arabica::SAX::InputSource<std::string> inputSource(argv[1]);
+
+ Arabica::SAX2DOM::Parser<std::string> domParser;
+ Arabica::SAX::CatchErrorHandler<std::string> errorHandler;
+ domParser.setErrorHandler(errorHandler);
+ if(!domParser.parse(inputSource)) {
+ return -1;
+ }
+ Document<std::string> doc = domParser.getDocument();
+ Element<std::string> elem = doc.getDocumentElement();
+
+ CapturingEventListener cel;
+ BubblingEventListener bel;
+
+ Events::EventTarget<std::string> eventTarget(elem);
+ eventTarget.addEventListener("DOMNodeInserted", cel, true);
+ eventTarget.addEventListener("DOMNodeInserted", bel, false);
+ eventTarget.addEventListener("DOMNodeRemoved", cel, true);
+ eventTarget.addEventListener("DOMNodeRemoved", bel, false);
+ eventTarget.addEventListener("DOMAttrModified", cel, true);
+ eventTarget.addEventListener("DOMAttrModified", bel, false);
+
+ Arabica::XPath::XPath<std::string> xpath;
+ Arabica::XPath::NodeSet<std::string> divs = xpath.evaluate("//div", doc).asNodeSet();
+
+ for (int i = 0; i < divs.size(); i++) {
+ Element<std::string> divElem = Element<std::string>(divs[i]);
+ divElem.setAttribute("foo", "true");
+ divElem.setAttribute("foo", "false");
+
+ Element<std::string> fooElem = divElem.getOwnerDocument().createElement("foo");
+ divElem.appendChild(fooElem);
+ divElem.removeChild(fooElem);
+ }
+
+
+} \ No newline at end of file