From ce6f68d3a24759b9758ee0c5c2486ea53a1827af Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Sun, 7 Apr 2013 20:37:10 +0200 Subject: Fixed JSON in content --- src/uscxml/Interpreter.cpp | 84 ++++++++++++++++++++++++++-------------------- src/uscxml/Interpreter.h | 5 ++- src/uscxml/Message.cpp | 2 +- src/uscxml/Message.h | 4 +++ 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 9d6b764..c63ccc8 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -548,7 +548,7 @@ void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node& st if (contents.size() > 1) LOG(ERROR) << "Only a single content element is allowed for send elements - using first one"; if (contents.size() > 0) - processContentElement(contents[0], event.dom, event.content); + processContentElement(contents[0], event.dom, event.content, event.data); } event.name = "done.state." + ATTR(stateElem.getParentNode(), "id"); // parent?! @@ -556,59 +556,71 @@ void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node& st } -void InterpreterImpl::processContentElement(const Arabica::DOM::Node& content, Arabica::DOM::Document& dom, std::string& text) { +void InterpreterImpl::processContentElement(const Arabica::DOM::Node& content, + Arabica::DOM::Document& dom, + std::string& text, + Data& data) { try { + std::string contentToProcess; if (HAS_ATTR(content, "expr")) { if (_dataModel) { /// this is out of spec - std::string contentValue = _dataModel.evalAsString(ATTR(content, "expr")); - text = contentValue; + contentToProcess = _dataModel.evalAsString(ATTR(content, "expr")); // sendReq.data.atom = contentValue; // sendReq.data.type = Data::VERBATIM; } else { LOG(ERROR) << "content element has expr attribute but no datamodel is specified."; } } else if (content.hasChildNodes()) { - bool presentAsDOM = false; - NodeList contentChilds = content.getChildNodes(); - for (int i = 0; i < contentChilds.getLength(); i++) { - if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) { - presentAsDOM = true; + bool presentAsDom = false; + Node contentChild = content.getFirstChild(); + while(contentChild) { + if (contentChild.getNodeType() == Node_base::TEXT_NODE) { + std::string trimmed = contentChild.getNodeValue(); + boost::trim(trimmed); + if (trimmed.length() > 0) + break; + } + if (contentChild.getNodeType() == Node_base::ELEMENT_NODE) { + presentAsDom = true; break; } + contentChild = contentChild.getNextSibling(); } - if (presentAsDOM) { + + if (contentChild && presentAsDom) { // use the whole dom - Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); - dom = domFactory.createDocument(content.getNamespaceURI(), "", 0); - Node newNode = dom.importNode(content, true); + DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); + dom = domFactory.createDocument(contentChild.getNamespaceURI(), "", 0); + Node newNode = dom.importNode(contentChild, true); dom.appendChild(newNode); + } else if (contentChild) { + contentToProcess = contentChild.getNodeValue(); } else { - Node textChild = content.getFirstChild(); - while(textChild && textChild.getNodeType() != Node_base::TEXT_NODE) { - textChild = textChild.getNextSibling(); - } - if (textChild && textChild.getNodeType() == Node_base::TEXT_NODE) { - /// create space normalized string - std::istringstream iss(content.getFirstChild().getNodeValue()); - std::stringstream content; - std::string seperator; - do { - std::string token; - iss >> token; - if (token.length() > 0) { - content << seperator << token; - seperator = " "; - } - } while (iss); - text = content.str(); - } else { - LOG(ERROR) << "content element has neither text nor element children."; - } + LOG(ERROR) << "content element has neither text nor element children."; } } else { LOG(ERROR) << "content element does not specify any content."; } + if (contentToProcess.size() > 0) { + /// try to interpret as JSON + data = Data::fromJSON(contentToProcess); + if (data) + return; + /// create space normalized string + std::istringstream iss(contentToProcess); + std::stringstream content; + std::string seperator; + do { + std::string token; + iss >> token; + if (token.length() > 0) { + content << seperator << token; + seperator = " "; + } + } while (iss); + text = content.str(); + } } catch (Event e) { e.name = "error.execution"; receiveInternal(e); @@ -780,7 +792,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node& element) { if (contents.size() > 1) LOG(ERROR) << "Only a single content element is allowed for send elements - using first one"; if (contents.size() > 0) { - processContentElement(contents[0], sendReq.dom, sendReq.content); + processContentElement(contents[0], sendReq.dom, sendReq.content, sendReq.data); } } catch (Event e) { LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl; @@ -898,7 +910,7 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node& element) { if (contents.size() > 1) LOG(ERROR) << "Only a single content element is allowed for send elements - using first one"; if (contents.size() > 0) { - processContentElement(contents[0], invokeReq.dom, invokeReq.content); + processContentElement(contents[0], invokeReq.dom, invokeReq.content, invokeReq.data); } } catch (Event e) { LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 2a63604..90540a7 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -267,7 +267,10 @@ protected: void executeContent(const Arabica::DOM::NodeList& content, bool rethrow = false); void executeContent(const Arabica::XPath::NodeSet& content, bool rethrow = false); - void processContentElement(const Arabica::DOM::Node& element, Arabica::DOM::Document& dom, std::string& text); + void processContentElement(const Arabica::DOM::Node& element, + Arabica::DOM::Document& dom, + std::string& text, + Data& data); void processParamChilds(const Arabica::DOM::Node& element, std::multimap& params); void send(const Arabica::DOM::Node& element); diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index 3ada20c..65a66ce 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -189,7 +189,7 @@ Data Data::fromJSON(const std::string& jsonString) { // we do not know the number of tokens beforehand, start with something sensible and increase int rv; - int frac = 32; // this will get decreased to 16 to first iteration for 1/16 length/token ratio + int frac = 16; // this will get decreased to 16 to first iteration for 1/16 length/token ratio do { jsmn_init(&p); diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 9f5e8e2..3d41f70 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -31,6 +31,10 @@ public: explicit Data(const Arabica::DOM::Node& dom); virtual ~Data() {} + operator bool() const { + return (atom.length() > 0 || !compound.empty() || !array.empty()); + } + static Data fromJSON(const std::string& jsonString); static Data fromXML(const std::string& xmlString); Arabica::DOM::Document toDocument(); -- cgit v0.12