diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-01-10 22:42:42 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-01-10 22:42:42 (GMT) |
commit | 7aa7095d17a180d663cd9647c31d99d97c1dca4f (patch) | |
tree | 460bc3a67f0adc3199bec9f22ee15a102263eb4c | |
parent | da1032ffbff229ce2ca9a83d47522ff45c90ba23 (diff) | |
download | uscxml-7aa7095d17a180d663cd9647c31d99d97c1dca4f.zip uscxml-7aa7095d17a180d663cd9647c31d99d97c1dca4f.tar.gz uscxml-7aa7095d17a180d663cd9647c31d99d97c1dca4f.tar.bz2 |
Major changes - see details
- Dynamic SceneGraph ML
- V8 DOM for ecmascript datamodel
- New heartbeat invoker
- Fixed various bugs
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 |