summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-04-21 21:29:10 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-04-21 21:29:10 (GMT)
commit4d6fb580b1c1378cb1441fff4adeca889cbba58e (patch)
tree551d02203cc74c82b363e065cb06dd2584a0e6a1 /src/uscxml
parentc1ebae519210cd4d09eb63bde593d48e769ad7ca (diff)
downloaduscxml-4d6fb580b1c1378cb1441fff4adeca889cbba58e.zip
uscxml-4d6fb580b1c1378cb1441fff4adeca889cbba58e.tar.gz
uscxml-4d6fb580b1c1378cb1441fff4adeca889cbba58e.tar.bz2
More work on XPath datamodel
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/Interpreter.cpp17
-rw-r--r--src/uscxml/Message.cpp24
-rw-r--r--src/uscxml/Message.h2
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp151
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.h11
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp4
6 files changed, 174 insertions, 35 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 21f64cb..dea7299 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -382,12 +382,12 @@ void InterpreterImpl::normalize(Arabica::DOM::Element<std::string>& scxml) {
}
void InterpreterImpl::receiveInternal(const Event& event) {
-// std::cout << _name << " receiveInternal: " << event.name << std::endl;
+ std::cout << _name << " receiveInternal: " << event.name << std::endl;
_internalQueue.push_back(event);
}
void InterpreterImpl::receive(const Event& event, bool toFront) {
-// std::cout << _name << " receive: " << event.name << std::endl;
+ std::cout << _name << " receive: " << event.name << std::endl;
if (toFront) {
_externalQueue.push_front(event);
} else {
@@ -475,6 +475,12 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
inputSource.setByteStream(ssPtr);
if (parser.parse(inputSource) && parser.getDocument()) {
dom = parser.getDocument();
+ Node<std::string> content = dom.getDocumentElement();
+ assert(content.getNodeType() == Node_base::ELEMENT_NODE);
+ Node<std::string> container = dom.createElement("container");
+ dom.replaceChild(container, content);
+ container.appendChild(content);
+ std::cout << dom << std::endl;
return;
} else {
text = srcContent.str();
@@ -890,7 +896,7 @@ bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::s
return false;
// naive case of single descriptor and exact match
- if (boost::equals(transitionEvent, event))
+ if (boost::iequals(transitionEvent, event))
return true;
boost::char_separator<char> sep(" ");
@@ -911,7 +917,7 @@ bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::s
return true;
// are they already equal?
- if (boost::equals(eventDesc, event))
+ if (boost::iequals(eventDesc, event))
return true;
// eventDesc has to be a real prefix of event now and therefore shorter
@@ -919,7 +925,8 @@ bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::s
continue;
// it is a prefix of the event name and event continues with .something
- if (eventDesc.compare(event.substr(0, eventDesc.size())) == 0)
+ if (boost::istarts_with(event, eventDesc))
+// if (eventDesc.compare(event.substr(0, eventDesc.size())) == 0)
if (event.find(".", eventDesc.size()) == eventDesc.size())
return true;
}
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index c3f4281..27e01e2 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -110,6 +110,30 @@ Arabica::DOM::Document<std::string> Data::toDocument() {
return document;
}
+Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const {
+ Arabica::DOM::Node<std::string> data = dom.getDocumentElement().getFirstChild();
+ while (data) {
+ if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) {
+ std::string trimmed = boost::trim_copy(data.getNodeValue());
+ if (trimmed.length() == 0) {
+ data = data.getNextSibling();
+ continue;
+ }
+ }
+ break;
+ }
+ return data;
+}
+
+Arabica::DOM::Document<std::string> Event::getStrippedDOM() const {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> document = domFactory.createDocument("", "", 0);
+ if (dom) {
+ document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(), true));
+ }
+ return document;
+}
+
Arabica::DOM::Document<std::string> Event::toDocument() {
Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
Arabica::DOM::Document<std::string> document = data.toDocument();
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index 27bd071..ea1e8ab 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -139,6 +139,8 @@ public:
void setDOM(const Arabica::DOM::Document<std::string>& dom) {
this->dom = dom;
}
+ Arabica::DOM::Node<std::string> getFirstDOMElement() const;
+ Arabica::DOM::Document<std::string> getStrippedDOM() const;
std::string getRaw() {
return raw;
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
index 39616f8..6377af2 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
@@ -59,11 +59,7 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr
dm->_datamodel.appendChild(ioProcElem);
NodeSet<std::string> ioProcNodeSet;
- Node<std::string> node = ioProcElem.getFirstChild();
- while(node) {
- ioProcNodeSet.push_back(node);
- node = node.getNextSibling();
- }
+ ioProcNodeSet.push_back(ioProcElem);
dm->_varResolver.setVariable("_ioprocessors", ioProcNodeSet);
Element<std::string> sessIdElem = dm->_doc.createElement("data");
@@ -107,8 +103,41 @@ void XPathDataModel::setEvent(const Event& event) {
eventElem.setAttribute("id", "_event");
Element<std::string> eventDataElem = _doc.createElement("data");
-
NodeSet<std::string> eventNodeSet;
+
+ {
+ // -- name
+ Element<std::string> eventNameElem = _doc.createElement("name");
+ Text<std::string> eventName = _doc.createTextNode(event.name.c_str());
+ eventNameElem.appendChild(eventName);
+ eventElem.appendChild(eventNameElem);
+ }
+ {
+ // -- origin
+ Element<std::string> eventOriginElem = _doc.createElement("origin");
+ Text<std::string> eventOrigin = _doc.createTextNode(event.origin.c_str());
+ eventOriginElem.appendChild(eventOrigin);
+ eventElem.appendChild(eventOriginElem);
+ }
+ {
+ // -- type
+ Element<std::string> eventTypeElem = _doc.createElement("type");
+ Text<std::string> eventType;
+ switch (event.type) {
+ case Event::INTERNAL:
+ eventType = _doc.createTextNode("internal");
+ break;
+ case Event::EXTERNAL:
+ eventType = _doc.createTextNode("external");
+ break;
+ case Event::PLATFORM:
+ eventType = _doc.createTextNode("platform");
+ break;
+ }
+ eventTypeElem.appendChild(eventType);
+ eventElem.appendChild(eventTypeElem);
+ }
+
if (event.params.size() > 0) {
std::multimap<std::string, std::string>::const_iterator paramIter = event.params.begin();
while(paramIter != event.params.end()) {
@@ -137,7 +166,7 @@ void XPathDataModel::setEvent(const Event& event) {
Element<std::string> eventRawElem = _doc.createElement("raw");
Text<std::string> textNode = _doc.createTextNode(event.raw.c_str());
eventRawElem.appendChild(textNode);
- eventDataElem.appendChild(eventRawElem);
+ eventElem.appendChild(eventRawElem);
}
if (event.content.size() > 0) {
@@ -145,12 +174,12 @@ void XPathDataModel::setEvent(const Event& event) {
eventDataElem.appendChild(textNode);
}
if (event.dom) {
- Node<std::string> importedNode = _doc.importNode(event.dom.getFirstChild(), true);
+ Node<std::string> importedNode = _doc.importNode(event.getFirstDOMElement(), true);
eventDataElem.appendChild(importedNode);
}
eventElem.appendChild(eventDataElem);
- eventNodeSet.push_back(eventDataElem);
+ eventNodeSet.push_back(eventElem);
// do we need to replace an existing event?
Node<std::string> oldEventElem = _datamodel.getFirstChild();
@@ -283,12 +312,28 @@ bool XPathDataModel::isDeclared(const std::string& expr) {
}
bool XPathDataModel::evalAsBool(const std::string& expr) {
- XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc);
+// std::cout << std::endl << evalAsString(expr);
+ XPathValue<std::string> result;
+ try {
+ result = _xpath.evaluate_expr(expr, _doc);
+ } catch(SyntaxException e) {
+ throw Event("error.execution", Event::PLATFORM);
+ } catch(std::runtime_error e) {
+ throw Event("error.execution", Event::PLATFORM);
+ }
return result.asBool();
}
std::string XPathDataModel::evalAsString(const std::string& expr) {
- XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc);
+
+ XPathValue<std::string> result;
+ try {
+ result = _xpath.evaluate_expr(expr, _doc);
+ } catch(SyntaxException e) {
+ throw Event("error.execution", Event::PLATFORM);
+ } catch(std::runtime_error e) {
+ throw Event("error.execution", Event::PLATFORM);
+ }
switch (result.type()) {
case STRING:
return result.asString();
@@ -303,7 +348,10 @@ std::string XPathDataModel::evalAsString(const std::string& expr) {
NodeSet<std::string> nodeSet = result.asNodeSet();
std::stringstream ss;
for (int i = 0; i < nodeSet.size(); i++) {
- ss << nodeSet[i] << std::endl;
+ ss << nodeSet[i];
+ if (nodeSet[i].getNodeType() != Node_base::TEXT_NODE) {
+ ss << std::endl;
+ }
}
return ss.str();
break;
@@ -330,7 +378,21 @@ void XPathDataModel::assign(const Element<std::string>& assignElem,
location = ATTR(assignElem, "location");
}
+ // test 326ff
XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc);
+ if (key.type() == NODE_SET) {
+ for (int i = 0; i < key.asNodeSet().size(); i++) {
+ Node<std::string> node = key.asNodeSet()[i];
+ if (node == _varResolver.resolveVariable("", "_ioprocessors").asNodeSet()[0])
+ throw Event("error.execution", Event::PLATFORM);
+ if (node == _varResolver.resolveVariable("", "_sessionid").asNodeSet()[0])
+ throw Event("error.execution", Event::PLATFORM);
+ if (node == _varResolver.resolveVariable("", "_name").asNodeSet()[0])
+ throw Event("error.execution", Event::PLATFORM);
+ if (node == _varResolver.resolveVariable("", "_event").asNodeSet()[0])
+ throw Event("error.execution", Event::PLATFORM);
+ }
+ }
NodeSet<std::string> nodeSet;
if (doc) {
if (doc.getDocumentElement()) {
@@ -365,7 +427,18 @@ void XPathDataModel::assign(const Element<std::string>& assignElem,
}
void XPathDataModel::assign(const std::string& location, const Data& data) {
+ XPathValue<std::string> locationResult = _xpath.evaluate_expr(location, _doc);
+ NodeSet<std::string> dataNodeSet = dataToNodeSet(data);
+ assign(locationResult, dataNodeSet, Element<std::string>());
+// std::cout << _datamodel << std::endl;
+}
+NodeSet<std::string> XPathDataModel::dataToNodeSet(const Data& data) {
+ NodeSet<std::string> dataNodeSet;
+ if (data.atom.length() > 0) {
+ dataNodeSet.push_back(_doc.createTextNode(data.atom));
+ }
+ return dataNodeSet;
}
void XPathDataModel::init(const Element<std::string>& dataElem,
@@ -396,10 +469,12 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
try {
XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc);
switch (expr.type()) {
- case NODE_SET:
- for (int i = 0; expr.asNodeSet().size(); i++)
- container.appendChild(expr.asNodeSet()[i]);
+ case NODE_SET: {
+ for (int i = 0; i < expr.asNodeSet().size(); i++) {
+ container.appendChild(expr.asNodeSet()[i].cloneNode(true));
+ }
break;
+ }
case STRING:
container.appendChild(_doc.createTextNode(expr.asString()));
break;
@@ -420,7 +495,15 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
// put data element into nodeset and bind to xpath variable
NodeSet<std::string> nodeSet;
+#if 1
nodeSet.push_back(container);
+#else
+ Node<std::string> node = container.getFirstChild();
+ while(node) {
+ nodeSet.push_back(node);
+ node = node.getNextSibling();
+ }
+#endif
_varResolver.setVariable(location, nodeSet);
// std::cout << _datamodel << std::endl;
@@ -469,6 +552,8 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
void XPathDataModel::assign(const XPathValue<std::string>& key,
const NodeSet<std::string>& value,
const Element<std::string>& assignElem) {
+ if (value.size() == 0 || !value[0])
+ return;
switch (key.type()) {
case NODE_SET: {
assign(key.asNodeSet(), value, assignElem);
@@ -540,6 +625,8 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
const Element<std::string>& assignElem) {
if (key.size() == 0)
return;
+ if (value.size() == 0 || !value[0])
+ return;
for (int i = 0; i < key.size(); i++) {
switch (key[i].getNodeType()) {
@@ -559,17 +646,20 @@ void XPathDataModel::assign(const Element<std::string>& key,
const NodeSet<std::string>& value,
const Element<std::string>& assignElem) {
Element<std::string> element(key);
+ if (value.size() == 0 || !value[0])
+ return;
+
if (false) {
} else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "firstchild")) {
// firstchild: Insert the value specified by 'expr' before all of the children at 'location'.
for (int i = value.size(); i; i--) {
- Node<std::string> importedNode = _doc.importNode(value[i-1], true);
+ Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
element.insertBefore(importedNode, element.getFirstChild());
}
} else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "lastchild")) {
// lastchild: Insert the value specified by 'expr' after all of the children at 'location'.
for (int i = 0; i < value.size(); i++) {
- Node<std::string> importedNode = _doc.importNode(value[i], true);
+ Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
element.appendChild(importedNode);
}
} else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) {
@@ -579,7 +669,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
if (!parent)
throw Event("error.execution", Event::PLATFORM);
for (int i = 0; i < value.size(); i++) {
- Node<std::string> importedNode = _doc.importNode(value[i], true);
+ Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
parent.insertBefore(importedNode, element);
}
} else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) {
@@ -589,7 +679,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
if (!parent)
throw Event("error.execution", Event::PLATFORM);
for (int i = value.size(); i; i--) {
- Node<std::string> importedNode = _doc.importNode(value[i-1], true);
+ Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
Node<std::string> nextSibling = element.getNextSibling();
if (nextSibling) {
parent.insertBefore(importedNode, element.getNextSibling());
@@ -604,7 +694,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
throw Event("error.execution", Event::PLATFORM);
if (value.size() != 1)
throw Event("error.execution", Event::PLATFORM);
- Node<std::string> importedNode = _doc.importNode(value[0], true);
+ Node<std::string> importedNode = (value[0].getOwnerDocument() == _doc ? value[0].cloneNode(true) : _doc.importNode(value[0], true));
parent.replaceChild(importedNode, element);
} else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) {
// delete: Delete the node specified by 'location'. ('expr' is ignored.).
@@ -617,7 +707,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
while(element.hasChildNodes())
element.removeChild(element.getChildNodes().item(0));
for (int i = 0; i < value.size(); i++) {
- Node<std::string> importedNode = _doc.importNode(value[i], true);
+ Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
element.appendChild(importedNode);
}
}
@@ -630,8 +720,8 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri,
if(n == _variables.end()) {
throw Event("error.execution");
}
-#if 0
- std::cout << std::endl << name << ":" << std::endl;
+#if 1
+ std::cout << std::endl << "Getting " << name << ":" << std::endl;
for (int i = 0; i < n->second.size(); i++) {
std::cout << n->second[i].getNodeType() << " | " << n->second[i] << std::endl;
}
@@ -640,6 +730,21 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri,
return XPathValue<std::string>(new NodeSetValue<std::string>(n->second));
}
+void NodeSetVariableResolver::setVariable(const std::string& name, const NodeSet<std::string>& value) {
+#if 1
+ std::cout << std::endl << "Setting " << name << ":" << std::endl;
+ for (int i = 0; i < value.size(); i++) {
+ std::cout << value[i].getNodeType() << " | " << value[i] << std::endl;
+ }
+ std::cout << std::endl;
+#endif
+ _variables[name] = value;
+}
+
+bool NodeSetVariableResolver::isDeclared(const std::string& name) {
+ return _variables.find(name) != _variables.end();
+}
+
XPathFunction<std::string>*
XPathFunctionResolver::resolveFunction(const std::string& namespace_uri,
const std::string& name,
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
index 7140b2f..104d100 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h
@@ -52,12 +52,8 @@ class NodeSetVariableResolver : public Arabica::XPath::VariableResolver<std::str
public:
Arabica::XPath::XPathValue<std::string> resolveVariable(const std::string& namepaceUri,
const std::string& name) const;
- void setVariable(const std::string& name, const Arabica::XPath::NodeSet<std::string>& value) {
- _variables[name] = value;
- }
- bool isDeclared(const std::string& name) {
- return _variables.find(name) != _variables.end();
- }
+ void setVariable(const std::string& name, const Arabica::XPath::NodeSet<std::string>& value);
+ bool isDeclared(const std::string& name);
private:
std::map<std::string, Arabica::XPath::NodeSet<std::string> > _variables;
@@ -115,6 +111,7 @@ protected:
Arabica::DOM::Document<std::string> _doc;
bool isValidIdentifier(const std::string& identifier);
+ Arabica::XPath::NodeSet<std::string> dataToNodeSet(const Data& data);
// resolve value to its type
void assign(const Arabica::XPath::XPathValue<std::string>& key,
@@ -148,7 +145,7 @@ protected:
void assign(const Arabica::DOM::Text<std::string>& key,
const Arabica::XPath::NodeSet<std::string>& value,
const Arabica::DOM::Element<std::string>& assignElem);
-
+
NodeSetVariableResolver _varResolver;
XPathFunctionResolver _funcResolver;
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 1d6394e..c8d86fa 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -86,7 +86,11 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) {
reqEvent.name = value;
} else {
reqEvent.data.compound[key] = value;
+ reqEvent.params.insert(std::make_pair(key, value));
}
+ } else {
+ // this is most likely wrong
+ reqEvent.content = evhttp_decode_uri(term.c_str());
}
}
} else {