From 71e1b30a2dcb8eefae105a5562239e21f07768c7 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Thu, 31 Oct 2013 17:43:13 +0100 Subject: Moved Parser into DOMUtils and new node -> xpath function for debugging --- apps/uscxml-browser.cpp | 1 + src/uscxml/DOMUtils.cpp | 104 ++++++++++++++++ src/uscxml/DOMUtils.h | 73 +++++++++++ src/uscxml/Interpreter.cpp | 138 +++++++++++++-------- src/uscxml/Interpreter.h | 10 ++ src/uscxml/Message.cpp | 10 +- src/uscxml/Message.h | 6 - src/uscxml/NameSpacingParser.cpp | 61 --------- src/uscxml/NameSpacingParser.h | 61 --------- src/uscxml/debug/SCXMLDotWriter.cpp | 1 + src/uscxml/interpreter/InterpreterDraft6.cpp | 1 + src/uscxml/interpreter/InterpreterDraft7.cpp | 1 + .../ecmascript/JavaScriptCore/JSCDataModel.cpp | 1 + .../datamodel/ecmascript/v8/V8DataModel.cpp | 1 + .../plugins/datamodel/null/NULLDataModel.cpp | 1 + .../plugins/datamodel/prolog/swi/SWIDataModel.cpp | 1 + .../plugins/datamodel/xpath/XPathDataModel.cpp | 1 + src/uscxml/plugins/element/fetch/FetchElement.cpp | 1 + src/uscxml/plugins/element/file/FileElement.cpp | 2 +- .../plugins/element/postpone/PostponeElement.cpp | 1 + .../plugins/element/respond/RespondElement.cpp | 1 + .../invoker/graphics/openscenegraph/OSGInvoker.cpp | 1 + src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp | 1 + src/uscxml/server/HTTPServer.cpp | 2 +- test/src/test-arabica-xpath.cpp | 18 +++ 25 files changed, 316 insertions(+), 183 deletions(-) create mode 100644 src/uscxml/DOMUtils.cpp create mode 100644 src/uscxml/DOMUtils.h delete mode 100644 src/uscxml/NameSpacingParser.cpp delete mode 100644 src/uscxml/NameSpacingParser.h diff --git a/apps/uscxml-browser.cpp b/apps/uscxml-browser.cpp index bba1bc0..8708e09 100644 --- a/apps/uscxml-browser.cpp +++ b/apps/uscxml-browser.cpp @@ -1,5 +1,6 @@ #include "uscxml/config.h" #include "uscxml/Interpreter.h" +#include "uscxml/DOMUtils.h" #include "uscxml/debug/SCXMLDotWriter.h" #include diff --git a/src/uscxml/DOMUtils.cpp b/src/uscxml/DOMUtils.cpp new file mode 100644 index 0000000..d521b49 --- /dev/null +++ b/src/uscxml/DOMUtils.cpp @@ -0,0 +1,104 @@ +/** + * @file + * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see . + * @endcond + */ + +#include +#include "DOMUtils.h" +#include +#include +#include + +namespace uscxml { + +std::string DOMUtils::xPathForNode(const Arabica::DOM::Node& node) { + std::string xPath; + + if (!node || node.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) + return xPath; + + Arabica::DOM::Node curr = node; + while(curr) { + switch (curr.getNodeType()) { + case Arabica::DOM::Node_base::ELEMENT_NODE: { + if (HAS_ATTR(curr, "id")) { + // we assume ids to be unique and return immediately + xPath.insert(0, "//" + TAGNAME(curr) + "[@id=\"" + ATTR(curr, "id") + "\"]"); + return xPath; + } else { + // check previous siblings to count our index + Arabica::DOM::Node sibling = curr.getPreviousSibling(); + int index = 1; + while(sibling) { + if (sibling.getNodeType() == Arabica::DOM::Node_base::ELEMENT_NODE) { + if (iequals(TAGNAME(sibling), TAGNAME(curr))) { + index++; + } + } + sibling = sibling.getPreviousSibling(); + } + xPath.insert(0, "/" + TAGNAME(curr) + "[" + toStr(index) + "]"); + } + break; + } + case Arabica::DOM::Node_base::DOCUMENT_NODE: + return xPath; + default: + LOG(ERROR) << "Only nodes of type element supported for now"; + return ""; + break; + } + curr = curr.getParentNode(); + } + return xPath; +} + +NameSpacingParser NameSpacingParser::fromXML(const std::string& xml) { + std::stringstream* ss = new std::stringstream(); + (*ss) << xml; + // we need an auto_ptr for arabica to assume ownership + std::auto_ptr ssPtr(ss); + Arabica::SAX::InputSource inputSource; + inputSource.setByteStream(ssPtr); + return fromInputSource(inputSource); +} + +NameSpacingParser NameSpacingParser::fromInputSource(Arabica::SAX::InputSource& source) { + NameSpacingParser parser; + if(!parser.parse(source) || !parser.getDocument().hasChildNodes()) { + if(parser._errorHandler.errorsReported()) { + LOG(ERROR) << "could not parse input:"; + LOG(ERROR) << parser._errorHandler.errors() << std::endl; + } else { + Arabica::SAX::InputSourceResolver resolver(source, Arabica::default_string_adaptor()); + if (!resolver.resolve()) { + LOG(ERROR) << source.getSystemId() << ": no such file"; + } + } + } + return parser; +} + +NameSpacingParser::NameSpacingParser() { + setErrorHandler(_errorHandler); +} + +void NameSpacingParser::startPrefixMapping(const std::string& prefix, const std::string& uri) { + nameSpace.insert(std::make_pair(uri, prefix)); +} + +} \ No newline at end of file diff --git a/src/uscxml/DOMUtils.h b/src/uscxml/DOMUtils.h new file mode 100644 index 0000000..31e7df0 --- /dev/null +++ b/src/uscxml/DOMUtils.h @@ -0,0 +1,73 @@ +/** + * @file + * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see . + * @endcond + */ + +#ifndef DOMUTILS_H_WK0WAEA7 +#define DOMUTILS_H_WK0WAEA7 + +#include "uscxml/Common.h" +#include +#include + +#define TAGNAME(elem) ((Arabica::DOM::Element)elem).getTagName() +#define LOCALNAME(elem) ((Arabica::DOM::Element)elem).getLocalName() +#define ATTR(elem, attr) ((Arabica::DOM::Element)elem).getAttribute(attr) +#define ATTR_NODE(elem, attr) ((Arabica::DOM::Element)elem).getAttributeNode(attr) +#define HAS_ATTR(elem, attr) ((Arabica::DOM::Element)elem).hasAttribute(attr) + +namespace uscxml { + +class USCXML_API DOMUtils { +public: + static std::string xPathForNode(const Arabica::DOM::Node& node); +}; + +class ScriptEntityResolver : public Arabica::SAX::EntityResolver { + virtual InputSourceT resolveEntity(const std::string& publicId, const std::string& systemId) { + Arabica::SAX::InputSource is; + return is; + } +}; + +class USCXML_API NameSpacingParser : public Arabica::SAX2DOM::Parser { +public: + NameSpacingParser(); + NameSpacingParser(const NameSpacingParser& other) {} + static NameSpacingParser fromXML(const std::string& xml); + static NameSpacingParser fromInputSource(Arabica::SAX::InputSource& source); + + void startPrefixMapping(const std::string& prefix, const std::string& uri); + + std::map nameSpace; + + virtual bool errorsReported() { + return _errorHandler.errorsReported(); + } + + virtual const std::string& errors() { + return _errorHandler.errors(); + } + +private: + Arabica::SAX::CatchErrorHandler _errorHandler; +}; + +} + + +#endif /* end of include guard: DOMUTILS_H_WK0WAEA7 */ diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index bb54c6f..b91991b 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -22,7 +22,7 @@ #include "uscxml/Interpreter.h" #include "uscxml/URL.h" #include "uscxml/UUID.h" -#include "uscxml/NameSpacingParser.h" +#include "uscxml/DOMUtils.h" #include "uscxml/debug/SCXMLDotWriter.h" #include "uscxml/plugins/invoker/http/HTTPServletInvoker.h" @@ -56,6 +56,19 @@ catch (Event e) {\ }\ } +#define CATCH_AND_DISTRIBUTE2(msg, node) \ +catch (Event e) {\ + LOG(ERROR) << msg << " " << DOMUtils::xPathForNode(node) << ":" << std::endl << e << std::endl;\ + if (rethrow) {\ + throw(e);\ + } else {\ + e.name = "error.execution";\ + e.eventType = Event::PLATFORM;\ + e.dom = node;\ + receiveInternal(e);\ + }\ +} + namespace uscxml { using namespace Arabica::XPath; @@ -245,7 +258,8 @@ InterpreterImpl::InterpreterImpl() { _httpServlet = NULL; _factory = NULL; _capabilities = CAN_BASIC_HTTP | CAN_GENERIC_HTTP; - + _domEventListener._interpreter = this; + #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); @@ -458,6 +472,12 @@ void InterpreterImpl::init() { _sendQueue = new DelayedEventQueue(); _sendQueue->start(); + // register for dom events to manage cached states + Arabica::DOM::Events::EventTarget eventTarget(_scxml); + eventTarget.addEventListener("DOMNodeInserted", _domEventListener, true); + eventTarget.addEventListener("DOMNodeRemoved", _domEventListener, true); + eventTarget.addEventListener("DOMSubtreeModified", _domEventListener, true); + if (_factory == NULL) _factory = Factory::getInstance(); @@ -491,7 +511,7 @@ void InterpreterImpl::initializeData(const Element& data) { try { _dataModel.init(ATTR(data, "id"), _invokeReq.params.find(ATTR(data, "id"))->second); } catch (Event e) { - LOG(ERROR) << "Syntax error when initializing data from parameters:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error when initializing data " << DOMUtils::xPathForNode(data) << " from parameters:" << std::endl << e << std::endl; receiveInternal(e); } return; @@ -500,7 +520,7 @@ void InterpreterImpl::initializeData(const Element& data) { try { _dataModel.init(ATTR(data, "id"), _invokeReq.namelist.find(ATTR(data, "id"))->second); } catch (Event e) { - LOG(ERROR) << "Syntax error when initializing data from namelist:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error when initializing data " << DOMUtils::xPathForNode(data) << " from namelist:" << std::endl << e << std::endl; receiveInternal(e); } return; @@ -512,7 +532,7 @@ void InterpreterImpl::initializeData(const Element& data) { processDOMorText(data, dom, text); _dataModel.init(data, dom, text); } catch (Event e) { - LOG(ERROR) << "Syntax error when initializing data:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error when initializing data " << DOMUtils::xPathForNode(data) << ":" << std::endl << e << std::endl; receiveInternal(e); } } @@ -618,6 +638,7 @@ void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node& st event.content =_dataModel.evalAsString(expr); } catch (Event e) { e.name = "error.execution"; + e.dom = contents[0]; receiveInternal(e); } } @@ -751,34 +772,35 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& el void InterpreterImpl::processParamChilds(const Arabica::DOM::Node& element, std::multimap& params) { NodeSet paramElems = filterChildElements(_xmlNSPrefix + "param", element); - try { for (int i = 0; i < paramElems.size(); i++) { - if (!HAS_ATTR(paramElems[i], "name")) { - LOG(ERROR) << "param element is missing name attribute"; - continue; - } - Data paramValue; - if (HAS_ATTR(paramElems[i], "expr") && _dataModel) { - paramValue = _dataModel.getStringAsData(ATTR(paramElems[i], "expr")); - } else if(HAS_ATTR(paramElems[i], "location") && _dataModel) { - paramValue = _dataModel.getStringAsData(ATTR(paramElems[i], "location")); - } else { - LOG(ERROR) << "param element is missing expr or location or no datamodel is specified"; - continue; + try { + if (!HAS_ATTR(paramElems[i], "name")) { + LOG(ERROR) << "param element is missing name attribute"; + continue; + } + Data paramValue; + if (HAS_ATTR(paramElems[i], "expr") && _dataModel) { + paramValue = _dataModel.getStringAsData(ATTR(paramElems[i], "expr")); + } else if(HAS_ATTR(paramElems[i], "location") && _dataModel) { + paramValue = _dataModel.getStringAsData(ATTR(paramElems[i], "location")); + } else { + LOG(ERROR) << "param element is missing expr or location or no datamodel is specified"; + continue; + } + std::string paramKey = ATTR(paramElems[i], "name"); + params.insert(std::make_pair(paramKey, paramValue)); + } catch(Event e) { + LOG(ERROR) << "Syntax error while processing params " << DOMUtils::xPathForNode(paramElems[i]) << ":" << std::endl << e << std::endl; + // test 343 + std::multimap::iterator paramIter = params.begin(); + while(paramIter != params.end()) { + params.erase(paramIter++); + } + e.name = "error.execution"; + receiveInternal(e); + break; } - std::string paramKey = ATTR(paramElems[i], "name"); - params.insert(std::make_pair(paramKey, paramValue)); - } - } catch(Event e) { - LOG(ERROR) << "Syntax error while processing params:" << std::endl << e << std::endl; - // test 343 - std::multimap::iterator paramIter = params.begin(); - while(paramIter != params.end()) { - params.erase(paramIter++); } - e.name = "error.execution"; - receiveInternal(e); - } } void InterpreterImpl::send(const Arabica::DOM::Node& element) { @@ -793,7 +815,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { sendReq.name = ATTR(element, "event"); } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element eventexpr:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element eventexpr " << DOMUtils::xPathForNode(element) << ":" << std::endl << e << std::endl; return; } try { @@ -804,7 +826,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { sendReq.target = ATTR(element, "target"); } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element targetexpr:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " targetexpr:" << std::endl << e << std::endl; return; } try { @@ -815,7 +837,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { sendReq.type = ATTR(element, "type"); } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element typeexpr:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " typeexpr:" << std::endl << e << std::endl; return; } try { @@ -850,7 +872,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { } } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element idlocation:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " idlocation:" << std::endl << e << std::endl; return; } @@ -877,7 +899,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { } } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element delayexpr:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " delayexpr:" << std::endl << e << std::endl; return; } @@ -896,7 +918,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { } } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element namelist:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " namelist:" << std::endl << e << std::endl; return; } @@ -904,14 +926,14 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { // params processParamChilds(element, sendReq.params); } catch (Event e) { - LOG(ERROR) << "Syntax error in send element param expr:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " param expr:" << std::endl << e << std::endl; return; } try { // content NodeSet contents = filterChildElements(_xmlNSPrefix + "content", element); if (contents.size() > 1) - LOG(ERROR) << "Only a single content element is allowed for send elements - using first one"; + LOG(ERROR) << "Only a single content element is allowed for send elements " << DOMUtils::xPathForNode(element) << " - using first one"; if (contents.size() > 0) { std::string expr; processContentElement(contents[0], sendReq.dom, sendReq.content, expr); @@ -927,7 +949,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { } } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " content:" << std::endl << e << std::endl; return; } @@ -1058,6 +1080,7 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node& element) { invokeReq.data =_dataModel.getStringAsData(expr); } catch (Event e) { e.name = "error.execution"; + e.dom = contents[0]; receiveInternal(e); } } else if (invokeReq.content.length() > 0) { @@ -1066,7 +1089,7 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node& element) { } } catch (Event e) { - LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in send element " << DOMUtils::xPathForNode(element) << " content:" << std::endl << e << std::endl; return; } @@ -1110,7 +1133,7 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node& element) { } } catch (Event e) { - LOG(ERROR) << "Syntax error in invoke element:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in invoke element " << DOMUtils::xPathForNode(element) << ":" << std::endl << e << std::endl; } } @@ -1195,7 +1218,7 @@ bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Node& c try { return _dataModel.evalAsBool(ATTR_NODE(conditional, "cond"), ATTR(conditional, "cond")); } catch (Event e) { - LOG(ERROR) << "Syntax error in cond attribute of " << TAGNAME(conditional) << " element:" << std::endl << e << std::endl; + LOG(ERROR) << "Syntax error in cond attribute of " << TAGNAME(conditional) << " element " << DOMUtils::xPathForNode(conditional) << ":" << std::endl << e << std::endl; e.name = "error.execution"; receiveInternal(e); return false; @@ -1212,7 +1235,7 @@ void InterpreterImpl::executeContent(const NodeList& content, bool try { executeContent(content.item(i), true); } - CATCH_AND_DISTRIBUTE("Error when executing content"); + CATCH_AND_DISTRIBUTE2("Error when executing content", content.item(i)); } } @@ -1223,7 +1246,7 @@ void InterpreterImpl::executeContent(const NodeSet& content, bool r try { executeContent(content[i], true); } - CATCH_AND_DISTRIBUTE("Error when executing content"); + CATCH_AND_DISTRIBUTE2("Error when executing content", content[i]); } } @@ -1294,7 +1317,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont try { iterations = _dataModel.getLength(array); } - CATCH_AND_DISTRIBUTE("Syntax error in array attribute of foreach element:") + CATCH_AND_DISTRIBUTE2("Syntax error in array attribute of foreach element", content) try { _dataModel.pushContext(); // copy old and enter new context // if (!_dataModel.isDeclared(item)) { @@ -1308,7 +1331,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont } _dataModel.popContext(); // leave stacked context } - CATCH_AND_DISTRIBUTE("Syntax error in foreach element:") + CATCH_AND_DISTRIBUTE2("Syntax error in foreach element", content) } else { LOG(ERROR) << "Expected array and item attributes with foreach element!" << std::endl; } @@ -1322,7 +1345,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont try { std::cout << _dataModel.evalAsString(logElem.getAttribute("expr")) << std::endl; } - CATCH_AND_DISTRIBUTE("Syntax error in expr attribute of log element:") + CATCH_AND_DISTRIBUTE2("Syntax error in expr attribute of log element", content) } else { if (logElem.hasAttribute("label")) std::cout << std::endl; @@ -1342,7 +1365,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont _dataModel.assign(Element(content), dom, text); } } - CATCH_AND_DISTRIBUTE("Syntax error in attributes of assign element:") + CATCH_AND_DISTRIBUTE2("Syntax error in attributes of assign element", content) } } else if (iequals(TAGNAME(content), _xmlNSPrefix + "validate")) { // --- VALIDATE -------------------------- @@ -1394,7 +1417,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont try { _dataModel.eval((Element)content, scriptContent); } - CATCH_AND_DISTRIBUTE("Syntax error while executing script element") + CATCH_AND_DISTRIBUTE2("Syntax error while executing script element", content) } } } @@ -1404,7 +1427,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont try { send(content); } - CATCH_AND_DISTRIBUTE("Error while sending content") + CATCH_AND_DISTRIBUTE2("Error while sending content", content) } else if (iequals(TAGNAME(content), _xmlNSPrefix + "cancel")) { // --- CANCEL -------------------------- std::string sendId; @@ -1420,7 +1443,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont _sendQueue->cancelEvent(sendId); } - CATCH_AND_DISTRIBUTE("Syntax error while executing cancel element") + CATCH_AND_DISTRIBUTE2("Syntax error while executing cancel element", content) } else if (iequals(TAGNAME(content), _xmlNSPrefix + "invoke")) { // --- INVOKE -------------------------- } else { @@ -2090,6 +2113,19 @@ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { return true; } +void InterpreterImpl::DOMEventListener::handleEvent(Arabica::DOM::Events::Event& event) { + // remove modified states from cache + if (event.getType().compare("DOMAttrModified") == 0) // we do not care about attributes + return; + Node target = Arabica::DOM::Node(event.getTarget()); + NodeSet childs = Interpreter::filterChildElements(_interpreter->_xmlNSPrefix + "state", target); + for (int i = 0; i < childs.size(); i++) { + if (HAS_ATTR(childs[i], "id")) { + _interpreter->_cachedStates.erase(ATTR(childs[i], "id")); + } + } +} + void InterpreterImpl::dump() { if (!_document) return; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index ac26457..008de6f 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -37,6 +37,8 @@ #include #include +#include +#include #include "uscxml/concurrency/tinythread.h" #include "uscxml/concurrency/eventqueue/DelayedEventQueue.h" @@ -130,6 +132,12 @@ public: LATE = 1 }; + class DOMEventListener : public Arabica::DOM::Events::EventListener { + public: + void handleEvent(Arabica::DOM::Events::Event& event); + InterpreterImpl* _interpreter; + }; + virtual ~InterpreterImpl(); void start(); @@ -339,6 +347,8 @@ protected: uscxml::concurrency::BlockingQueue* _parentQueue; DelayedEventQueue* _sendQueue; + DOMEventListener _domEventListener; + Event _currEvent; Factory* _factory; InterpreterServlet* _httpServlet; diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index fd39324..c79e08a 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -21,7 +21,7 @@ #include "uscxml/Common.h" #include "uscxml/Message.h" -//#include "uscxml/Interpreter.h" +#include "uscxml/DOMUtils.h" #include #include #include @@ -509,7 +509,7 @@ std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) { indent += " "; } - os << indent<< "SendReq" << std::endl; + os << indent << "SendReq" << std::endl; if (sendReq.target.size() > 0) os << indent << " target: " << sendReq.target << std::endl; @@ -628,6 +628,12 @@ std::string Data::toJSON(const Data& data) { } else { os << data.atom; } + } else if (data.node) { + if (data.type == Data::VERBATIM) { + os << ""; + } else { + os << data.atom; + } } else { os << "undefined"; } diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 4aba5ed..1964f1c 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -40,12 +40,6 @@ #include "uscxml/util/MD5.h" #include "uscxml/util/Base64.h" -#define TAGNAME(elem) ((Arabica::DOM::Element)elem).getTagName() -#define LOCALNAME(elem) ((Arabica::DOM::Element)elem).getLocalName() -#define ATTR(elem, attr) ((Arabica::DOM::Element)elem).getAttribute(attr) -#define ATTR_NODE(elem, attr) ((Arabica::DOM::Element)elem).getAttributeNode(attr) -#define HAS_ATTR(elem, attr) ((Arabica::DOM::Element)elem).hasAttribute(attr) - namespace uscxml { class USCXML_API Blob { diff --git a/src/uscxml/NameSpacingParser.cpp b/src/uscxml/NameSpacingParser.cpp deleted file mode 100644 index beaae95..0000000 --- a/src/uscxml/NameSpacingParser.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file - * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) - * @copyright Simplified BSD - * - * @cond - * This program is free software: you can redistribute it and/or modify - * it under the terms of the FreeBSD license as published by the FreeBSD - * project. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the FreeBSD license along with this - * program. If not, see . - * @endcond - */ - -#include -#include "NameSpacingParser.h" -#include -#include - -namespace uscxml { - -NameSpacingParser NameSpacingParser::fromXML(const std::string& xml) { - std::stringstream* ss = new std::stringstream(); - (*ss) << xml; - // we need an auto_ptr for arabica to assume ownership - std::auto_ptr ssPtr(ss); - Arabica::SAX::InputSource inputSource; - inputSource.setByteStream(ssPtr); - return fromInputSource(inputSource); -} - -NameSpacingParser NameSpacingParser::fromInputSource(Arabica::SAX::InputSource& source) { - NameSpacingParser parser; - if(!parser.parse(source) || !parser.getDocument().hasChildNodes()) { - if(parser._errorHandler.errorsReported()) { - LOG(ERROR) << "could not parse input:"; - LOG(ERROR) << parser._errorHandler.errors() << std::endl; - } else { - Arabica::SAX::InputSourceResolver resolver(source, Arabica::default_string_adaptor()); - if (!resolver.resolve()) { - LOG(ERROR) << source.getSystemId() << ": no such file"; - } - } - } - return parser; -} - -NameSpacingParser::NameSpacingParser() { - setErrorHandler(_errorHandler); -} - -void NameSpacingParser::startPrefixMapping(const std::string& prefix, const std::string& uri) { - nameSpace.insert(std::make_pair(uri, prefix)); -} - -} \ No newline at end of file diff --git a/src/uscxml/NameSpacingParser.h b/src/uscxml/NameSpacingParser.h deleted file mode 100644 index 88933c6..0000000 --- a/src/uscxml/NameSpacingParser.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file - * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) - * @copyright Simplified BSD - * - * @cond - * This program is free software: you can redistribute it and/or modify - * it under the terms of the FreeBSD license as published by the FreeBSD - * project. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the FreeBSD license along with this - * program. If not, see . - * @endcond - */ - -#ifndef NAMESPACINGPARSER_H_1S91TNPM -#define NAMESPACINGPARSER_H_1S91TNPM - -#include "uscxml/Common.h" -#include -#include - -namespace uscxml { - -class ScriptEntityResolver : public Arabica::SAX::EntityResolver { - virtual InputSourceT resolveEntity(const std::string& publicId, const std::string& systemId) { - Arabica::SAX::InputSource is; - return is; - } -}; - -class USCXML_API NameSpacingParser : public Arabica::SAX2DOM::Parser { -public: - NameSpacingParser(); - NameSpacingParser(const NameSpacingParser& other) {} - static NameSpacingParser fromXML(const std::string& xml); - static NameSpacingParser fromInputSource(Arabica::SAX::InputSource& source); - - void startPrefixMapping(const std::string& prefix, const std::string& uri); - - std::map nameSpace; - - virtual bool errorsReported() { - return _errorHandler.errorsReported(); - } - - virtual const std::string& errors() { - return _errorHandler.errors(); - } - -private: - Arabica::SAX::CatchErrorHandler _errorHandler; -}; - -} - -#endif /* end of include guard: NAMESPACINGPARSER_H_1S91TNPM */ diff --git a/src/uscxml/debug/SCXMLDotWriter.cpp b/src/uscxml/debug/SCXMLDotWriter.cpp index e2d21a7..07e7b9a 100644 --- a/src/uscxml/debug/SCXMLDotWriter.cpp +++ b/src/uscxml/debug/SCXMLDotWriter.cpp @@ -19,6 +19,7 @@ #include "uscxml/Common.h" #include "SCXMLDotWriter.h" +#include "uscxml/DOMUtils.h" #include // replace_all #include diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 96b6ecb..8663cfc 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -21,6 +21,7 @@ #include #include "uscxml/UUID.h" +#include "uscxml/DOMUtils.h" namespace uscxml { diff --git a/src/uscxml/interpreter/InterpreterDraft7.cpp b/src/uscxml/interpreter/InterpreterDraft7.cpp index cc54bc0..cb0ca38 100644 --- a/src/uscxml/interpreter/InterpreterDraft7.cpp +++ b/src/uscxml/interpreter/InterpreterDraft7.cpp @@ -22,6 +22,7 @@ #include #include "uscxml/UUID.h" +#include "uscxml/DOMUtils.h" namespace uscxml { diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index dbe4be5..f17bc62 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -40,6 +40,7 @@ #include "dom/JSCDataView.h" #include "uscxml/Message.h" +#include "uscxml/DOMUtils.h" #include #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 1037802..e7c0c72 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -41,6 +41,7 @@ #include "dom/V8DataView.h" #include "uscxml/Message.h" +#include "uscxml/DOMUtils.h" #include #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp index 05072df..1938b0c 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp @@ -21,6 +21,7 @@ #include "uscxml/Common.h" #include "NULLDataModel.h" +#include "uscxml/DOMUtils.h" #include "uscxml/Message.h" #include diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 02352fc..9a0a831 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -22,6 +22,7 @@ #include "uscxml/Common.h" #include "uscxml/config.h" #include "SWIDataModel.h" +#include "uscxml/DOMUtils.h" #include "uscxml/Message.h" #include diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index e81883a..3a99df8 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -21,6 +21,7 @@ #include "XPathDataModel.h" #include "uscxml/Message.h" +#include "uscxml/DOMUtils.h" #include #include diff --git a/src/uscxml/plugins/element/fetch/FetchElement.cpp b/src/uscxml/plugins/element/fetch/FetchElement.cpp index 37dd6c0..b40f487 100644 --- a/src/uscxml/plugins/element/fetch/FetchElement.cpp +++ b/src/uscxml/plugins/element/fetch/FetchElement.cpp @@ -20,6 +20,7 @@ #include #include "FetchElement.h" +#include "uscxml/DOMUtils.h" #include #include diff --git a/src/uscxml/plugins/element/file/FileElement.cpp b/src/uscxml/plugins/element/file/FileElement.cpp index 346c75d..3a8574d 100644 --- a/src/uscxml/plugins/element/file/FileElement.cpp +++ b/src/uscxml/plugins/element/file/FileElement.cpp @@ -23,7 +23,7 @@ #include #include -#include "uscxml/NameSpacingParser.h" +#include "uscxml/DOMUtils.h" #ifdef BUILD_AS_PLUGINS #include diff --git a/src/uscxml/plugins/element/postpone/PostponeElement.cpp b/src/uscxml/plugins/element/postpone/PostponeElement.cpp index f9ddd5f..7a18b38 100644 --- a/src/uscxml/plugins/element/postpone/PostponeElement.cpp +++ b/src/uscxml/plugins/element/postpone/PostponeElement.cpp @@ -21,6 +21,7 @@ #include "PostponeElement.h" #include "uscxml/plugins/invoker/http/HTTPServletInvoker.h" +#include "uscxml/DOMUtils.h" #include #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/element/respond/RespondElement.cpp b/src/uscxml/plugins/element/respond/RespondElement.cpp index 2b8d02d..a88d9c6 100644 --- a/src/uscxml/plugins/element/respond/RespondElement.cpp +++ b/src/uscxml/plugins/element/respond/RespondElement.cpp @@ -19,6 +19,7 @@ #include "RespondElement.h" #include "uscxml/plugins/invoker/http/HTTPServletInvoker.h" +#include "uscxml/DOMUtils.h" #include #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp index cd690ff..9e435d2 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp @@ -22,6 +22,7 @@ #include "OSGInvoker.h" #include "uscxml/URL.h" #include "uscxml/UUID.h" +#include "uscxml/DOMUtils.h" #include #include diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp index 04cb143..c0a0a07 100644 --- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp @@ -22,6 +22,7 @@ #include #include "XHTMLInvoker.h" #include +#include "uscxml/DOMUtils.h" #include #include diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index 15f347c..6065740 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -25,7 +25,7 @@ #endif #include "uscxml/server/HTTPServer.h" -#include "uscxml/NameSpacingParser.h" +#include "uscxml/DOMUtils.h" #include #include diff --git a/test/src/test-arabica-xpath.cpp b/test/src/test-arabica-xpath.cpp index fe457f4..ce389fa 100644 --- a/test/src/test-arabica-xpath.cpp +++ b/test/src/test-arabica-xpath.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "uscxml/DOMUtils.h" #define string_type std::string #define string_adaptor Arabica::default_string_adaptor @@ -127,6 +128,23 @@ int main(int argc, char** argv) { std::cout << numbers_ << std::endl; std::cout << chapters_ << std::endl; + if (true) { + using namespace Arabica::XPath; + using namespace Arabica::DOM; + XPathValue result = parser.evaluate(SA::construct_from_utf8("//*"), document_); + for(int i = 0; i < result.asNodeSet().size(); i++) { + Node node = result.asNodeSet()[i]; + std::string xpathExpr = uscxml::DOMUtils::xPathForNode(node); + if (xpathExpr.size()) { + XPathValue innerResult = parser.evaluate(xpathExpr, document_); + assert(innerResult.asNodeSet().size() > 0); + assert(innerResult.asNodeSet().size() == 1); + assert(innerResult.asNodeSet()[0] == node); + } else { + assert(node.getNodeType() != Node_base::ELEMENT_NODE); + } + } + } if (false) { using namespace Arabica::XPath; -- cgit v0.12