diff options
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | apps/samples/vrml/viewer.css | 157 | ||||
-rw-r--r-- | apps/samples/vrml/viewer.html | 5 | ||||
-rw-r--r-- | apps/samples/vrml/viewer.js | 63 | ||||
-rw-r--r-- | contrib/ctest/CTestCustom.ctest.in | 12 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 6 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp | 437 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/xpath/XPathDataModel.h | 27 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp | 12 | ||||
-rw-r--r-- | test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/samples/w3c/ecma/test568.scxml | 2 |
11 files changed, 443 insertions, 288 deletions
@@ -59,14 +59,6 @@ uSCXML still fails the following tests: <td>"test that any attempt to change the value of a system variable causes error.execution to be raised"</td> <td>Same issue as above: we allow writing to <tt>_event</tt>.</td> </tr> - <tr> - <td><tt><a hreaf="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test488.scxml">488</a></tt></td> - <td><tt>Failed</tt></td> - <td>"test that illegal expr in <param> produces error.execution and empty event.data"</td> - <td>The actual meaning of <emph>empty</emph> is still ambiguous - in - <a href="https://github.com/tklab-tud/uscxml/blob/master/test/samples/w3c/ecma/test343.scxml">test 343</a> - it is assumed to be <tt>undefined</tt>. This is a bug in the tests and was raised on the ML.</td> - </tr> </table> ## License diff --git a/apps/samples/vrml/viewer.css b/apps/samples/vrml/viewer.css new file mode 100644 index 0000000..089d29a --- /dev/null +++ b/apps/samples/vrml/viewer.css @@ -0,0 +1,157 @@ +/* Progress Indicator */ +.mblProgressIndicator { + position: relative; + top: 0px; +} +.mblHeading .mblProgressIndicator { + margin: 5px; + float: left; +} +.mblProgContainer { + position: absolute; + width: 100%; + height: 100%; +} +.mblProgressIndicatorCenter { + position: absolute; + top: 180px; + left: 50%; +} +.mblProgressIndicatorCenter .mblProgContainer { + left: -50%; + -webkit-transform-origin: 50% 0; + -moz-transform-origin: 50% 0; +} +.mblProg { + position: absolute; + left: 2px; + top: 0px; + width: 11px; + font-size: 1px; + height: 4px; + overflow: hidden; + -webkit-transform-origin: 0 2px; + -moz-transform-origin: 0 2px; + background-color: #c0c0c0; + border-radius: 2px; +} +.mblProg0 { + -webkit-transform: translate(18px, 10px) rotate(-90.1deg); + -moz-transform: translate(18px, 10px) rotate(-90.1deg); +} +.mblProg1 { + -webkit-transform: translate(22px, 11px) rotate(-60deg); + -moz-transform: translate(22px, 11px) rotate(-60deg); +} +.mblProg2 { + -webkit-transform: translate(25px, 14px) rotate(-30deg); + -moz-transform: translate(25px, 14px) rotate(-30deg); +} +.mblProg3 { + -webkit-transform: translate(26px, 18px) rotate(0deg); + -moz-transform: translate(26px, 18px) rotate(0deg); +} +.mblProg4 { + -webkit-transform: translate(25px, 22px) rotate(30deg); + -moz-transform: translate(25px, 22px) rotate(30deg); +} +.mblProg5 { + -webkit-transform: translate(22px, 25px) rotate(60deg); + -moz-transform: translate(22px, 25px) rotate(60deg); +} +.mblProg6 { + -webkit-transform: translate(18px, 26px) rotate(90.1deg); + -moz-transform: translate(18px, 26px) rotate(90.1deg); +} +.mblProg7 { + -webkit-transform: translate(14px, 25px) rotate(120deg); + -moz-transform: translate(14px, 25px) rotate(120deg); +} +.mblProg8 { + -webkit-transform: translate(11px, 22px) rotate(150deg); + -moz-transform: translate(11px, 22px) rotate(150deg); +} +.mblProg9 { + -webkit-transform: translate(10px, 18px) rotate(180deg); + -moz-transform: translate(10px, 18px) rotate(180deg); +} +.mblProg10 { + -webkit-transform: translate(11px, 14px) rotate(210deg); + -moz-transform: translate(11px, 14px) rotate(210deg); +} +.mblProg11 { + -webkit-transform: translate(14px, 11px) rotate(240deg); + -moz-transform: translate(14px, 11px) rotate(240deg); +} +.mblProg0Color { + background-color: #c0c0c0; +} +.mblProg1Color { + background-color: #c0c0c0; +} +.mblProg2Color { + background-color: #c0c0c0; +} +.mblProg3Color { + background-color: #c0c0c0; +} +.mblProg4Color { + background-color: #c0c0c0; +} +.mblProg5Color { + background-color: #c0c0c0; +} +.mblProg6Color { + background-color: #b8b9b8; +} +.mblProg7Color { + background-color: #aeafae; +} +.mblProg8Color { + background-color: #a4a5a4; +} +.mblProg9Color { + background-color: #9a9a9a; +} +.mblProg10Color { + background-color: #8e8e8e; +} +.mblProg11Color { + background-color: #838383; +} +.mblProgWhite .mblProg0Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg1Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg2Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg3Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg4Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg5Color { + background-color: #adb9c9; +} +.mblProgWhite .mblProg6Color { + background-color: #acb9cb; +} +.mblProgWhite .mblProg7Color { + background-color: #b7c2d2; +} +.mblProgWhite .mblProg8Color { + background-color: #c4cdda; +} +.mblProgWhite .mblProg9Color { + background-color: #d1d8e2; +} +.mblProgWhite .mblProg10Color { + background-color: #dee3ea; +} +.mblProgWhite .mblProg11Color { + background-color: #eceff3; +} diff --git a/apps/samples/vrml/viewer.html b/apps/samples/vrml/viewer.html index 977eeeb..52b0f66 100644 --- a/apps/samples/vrml/viewer.html +++ b/apps/samples/vrml/viewer.html @@ -5,12 +5,13 @@ <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/tundra/tundra.css"> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/FloatingPane.css"> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/ResizeHandle.css"> + <link rel="stylesheet" href="viewer.css"> <style type="text/css"> .alternateDock { position:absolute; - background-color:#ededed; - right:0px; top:0px; + background-color:#ededed; + right:0px; top:0px; border-left:1px solid #ccc; height:100%; diff --git a/apps/samples/vrml/viewer.js b/apps/samples/vrml/viewer.js index dedeb44..c897917 100644 --- a/apps/samples/vrml/viewer.js +++ b/apps/samples/vrml/viewer.js @@ -41,6 +41,7 @@ function VRMLViewer(element, params) { "dijit/form/VerticalRuleLabels", "dijit/form/VerticalRule", "dijit/form/HorizontalSlider", + "dojox/mobile/ProgressIndicator", "dojo/ready"], function(domConst, xhr, @@ -58,19 +59,23 @@ function VRMLViewer(element, params) { VerticalRuleLabels, VerticalRule, HorizontalSlider, + ProgressIndicator, ready) { + ready(function() { if (typeof(element) === 'string') { element = dom.byId(element); } + self.element = element; self.xhr = xhr; + self.progress = new ProgressIndicator({size:40, center:false}); self.localStorage = dojox.storage.manager.getProvider(); self.localStorage.initialize(); // establish our dom element.appendChild(domConst.toDom('\ - <div id="floatPane">\ + <div class="floatPane">\ <div style="text-align: right"><div class="server" /></div><button type="button" class="browseButton"></button></div>\ <div style="height: 100%; overflow: auto" class="fileList"></div>\ </div>\ @@ -79,6 +84,9 @@ function VRMLViewer(element, params) { <td valign="top">\ <div style="position: relative; padding: 0px">\ <img class="model" style="z-index: -1; min-width: ' + self.pose.width + 'px; min-height: ' + self.pose.height + 'px"></img>\ + <div style="z-index: 1; position: absolute; right: 45%; top: 45%">\ + <div class="progress"></div>\ + </div>\ <div style="position: absolute; left: 10px; top: 7%; height: 100%">\ <div class="pitchSlide"></div>\ </div>\ @@ -127,13 +135,15 @@ function VRMLViewer(element, params) { self.rollSlideElem = dojo.query("div.rollSlide", element)[0]; self.yawSlideElem = dojo.query("div.yawSlide", element)[0]; self.zoomSlideElem = dojo.query("div.zoomSlide", element)[0]; + self.progressElem = dojo.query("div.progress", element)[0]; + self.floatPaneElem = dojo.query("div.floatPane", element)[0]; self.floatPane = new FloatingPane({ title: "VRML Viewer", resizable: true, dockable: false, closable: false, style: "position:absolute;top:10;left:10;width:250px;height:300px;z-index: 2", id: "floatPane", - }, dojo.byId("floatPane")); + }, self.floatPaneElem); self.floatPane.startup(); // setup fileStore for tree list @@ -206,7 +216,9 @@ function VRMLViewer(element, params) { self.yawSlide.attr('value',0); self.zoomSlide.attr('value',1); - self.floatPane.startup(); + self.floatPane.domNode.style.top = "10px"; + self.floatPane.domNode.style.left = "10px"; +// self.floatPane.startup(); self.floatPane.show(); } }, self.resetButtonElem); @@ -344,32 +356,41 @@ function VRMLViewer(element, params) { this.refreshServer = function(server) { self.serverURL = server; self.localStorage.put("vrmlServer", self.serverURL, null); + self.progressElem.appendChild(self.progress.domNode); + self.progress.start(); self.xhr.get({ - // The URL to request - url: server, - handleAs:"json", - headers:{"X-Requested-With":null}, - load: function(result) { - (function fillstore(tree, parentId) { - for (key in tree) { - if ('url' in tree[key]) { - self.fileStore.add({id:parentId+key, name:key, url:self.serverURL + tree[key].path, parent:parentId}); + // The URL to request + url: server, + handleAs:"json", + headers:{"X-Requested-With":null}, + load: function(result) { + self.progress.stop(); + for (id in self.fileStore.query) { + self.fileStore.remove(id); + } + (function fillstore(tree, parentId) { + for (key in tree) { + if ('url' in tree[key]) { + self.fileStore.add({id:parentId+key, name:key, url:self.serverURL + tree[key].path, parent:parentId}); // self.messageBox.innerHTML += '<pre>' + self.serverURL + tree[key].path + '</pre>'; // self.messageBox.innerHTML += '<pre>' + tree[key].url + '?width=200&height=150</pre>' + '<img src="' + tree[key].url + '?width=200&height=150" />'; - } else { - self.fileStore.add({id:parentId+key, name:key, parent:parentId}); - fillstore(tree[key], parentId+key); - } - } - } (result.models, "root", "")); - } + } else { + self.fileStore.add({id:parentId+key, name:key, parent:parentId}); + fillstore(tree[key], parentId+key); + } + } + } (result.models, "root", "")); + } }); } - this.setPose = function(imageURL, pose) { + this.setPose = function(imageURL, pose, serverURL) { + if (serverURL && serverURL != self.serverURL) { + refreshServer(serverURL); + } self.imageURL = imageURL; self.pose = pose; - + self.batchChanges = true; // self.fileList.set('item', imageURL); self.xSpinner.set('value',pose.x); diff --git a/contrib/ctest/CTestCustom.ctest.in b/contrib/ctest/CTestCustom.ctest.in index d90a6b6..098e4e2 100644 --- a/contrib/ctest/CTestCustom.ctest.in +++ b/contrib/ctest/CTestCustom.ctest.in @@ -8,12 +8,12 @@ # skip xpath datamodel tests set(CTEST_CUSTOM_TESTS_IGNORE - "test178.scxml" - "test230.scxml" - "test250.scxml" - "test307.scxml" - "test313.scxml" - "test314.scxml" + "ecma/test178.scxml" + "ecma/test230.scxml" + "ecma/test250.scxml" + "ecma/test307.scxml" + "ecma/test313.scxml" + "ecma/test314.scxml" ) diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 87eae11..bec2a2a 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -502,7 +502,8 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no if (child && child.getNodeType() == Node_base::ELEMENT_NODE) { DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); dom = domFactory.createDocument(child.getNamespaceURI(), "", 0); - Node<std::string> newNode = dom.importNode(child, true); + // we need to import the parent - to support xpath test150 + Node<std::string> newNode = dom.importNode(child.getParentNode(), true); dom.appendChild(newNode); } else if(child && child.getNodeType() == Node_base::TEXT_NODE) { text = child.getNodeValue(); @@ -1032,6 +1033,9 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont CATCH_AND_DISTRIBUTE("Syntax error in array attribute of foreach element:") try { _dataModel.pushContext(); // copy old and enter new context + if (!_dataModel.isDeclared(item)) { + _dataModel.init(item, Data()); + } for (uint32_t iteration = 0; iteration < iterations; iteration++) { { // assign array element to item diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index 8f7e5e9..179fded 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -169,6 +169,18 @@ bool XPathDataModel::validate(const std::string& location, const std::string& sc } uint32_t XPathDataModel::getLength(const std::string& expr) { + std::cout << _datamodel << std::endl; + XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc); + switch(result.type()) { + case NUMBER: + return result.asNumber(); + break; + case NODE_SET: + return result.asNodeSet().size(); + break; + default: + throw Event("error.execution", Event::PLATFORM); + } return 0; } @@ -177,7 +189,11 @@ void XPathDataModel::eval(const std::string& expr) { } bool XPathDataModel::isDeclared(const std::string& expr) { - return true; + try { + return evalAsBool(expr); + } catch(...) { + return false; + } } bool XPathDataModel::evalAsBool(const std::string& expr) { @@ -188,16 +204,16 @@ bool XPathDataModel::evalAsBool(const std::string& expr) { std::string XPathDataModel::evalAsString(const std::string& expr) { XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc); switch (result.type()) { - case Arabica::XPath::STRING: + case STRING: return result.asString(); break; - case Arabica::XPath::BOOL: + case BOOL: return (result.asBool() ? "true" : "false"); break; - case Arabica::XPath::NUMBER: + case NUMBER: return toStr(result.asNumber()); break; - case Arabica::XPath::NODE_SET: { + case NODE_SET: { NodeSet<std::string> nodeSet = result.asNodeSet(); std::stringstream ss; for (int i = 0; i < nodeSet.size(); i++) { @@ -206,7 +222,7 @@ std::string XPathDataModel::evalAsString(const std::string& expr) { return ss.str(); break; } - case Arabica::XPath::ANY: + case ANY: throw Event("error.execution", Event::PLATFORM); break; } @@ -218,8 +234,8 @@ double XPathDataModel::evalAsNumber(const std::string& expr) { return result.asNumber(); } -void XPathDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem, - const Arabica::DOM::Document<std::string>& doc, +void XPathDataModel::assign(const Element<std::string>& assignElem, + const Document<std::string>& doc, const std::string& content) { std::string location; if (HAS_ATTR(assignElem, "id")) { @@ -251,8 +267,8 @@ void XPathDataModel::assign(const std::string& location, const Data& data) { } -void XPathDataModel::init(const Arabica::DOM::Element<std::string>& dataElem, - const Arabica::DOM::Document<std::string>& doc, +void XPathDataModel::init(const Element<std::string>& dataElem, + const Document<std::string>& doc, const std::string& content) { std::string location; if (HAS_ATTR(dataElem, "id")) { @@ -264,10 +280,13 @@ void XPathDataModel::init(const Arabica::DOM::Element<std::string>& dataElem, Element<std::string> container = _doc.createElement("data"); container.setAttribute("id", location); if (doc) { - Element<std::string> data = doc.getDocumentElement(); - if (data.hasChildNodes()) { - Node<std::string> dataClone = _doc.importNode(data, true); - container.appendChild(dataClone); + if (doc.getDocumentElement()) { + Node<std::string> data = doc.getDocumentElement().getFirstChild(); + while (data) { + Node<std::string> dataClone = _doc.importNode(data, true); + container.appendChild(dataClone); + data = data.getNextSibling(); + } } } else if (content.length() > 0) { Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(content)); @@ -288,259 +307,199 @@ void XPathDataModel::init(const Arabica::DOM::Element<std::string>& dataElem, nodeSet.push_back(container); _varResolver.setVariable(location, nodeSet); -// std::cout << _datamodel << std::endl; + std::cout << _datamodel << std::endl; } void XPathDataModel::init(const std::string& location, const Data& data) { - -} - -#if 0 -void XPathDataModel::assign(const std::string& location, - const Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { - XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); - NodeSet<std::string> nodeSet; - nodeSet.push_back(doc.getDocumentElement()); - assign(key, nodeSet, dataElem); -} - -void XPathDataModel::assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { -// assert(false); -// std::cout << location << " = " << data << std::endl; -} - -void XPathDataModel::assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { - std::string realExpr = (HAS_ATTR(dataElem, "expr") ? ATTR(dataElem, "expr") : expr); - XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); - XPathValue<std::string> value = _xpath.evaluate_expr(realExpr, _doc); - assign(key, value, dataElem); -} - -void XPathDataModel::init(const std::string& location, - const Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { - Element<std::string> container = _doc.createElement("data"); - container.setAttribute("id", location); - Element<std::string> data = doc.getDocumentElement(); - if (data.hasChildNodes()) { - Node<std::string> dataClone = _doc.importNode(data, true); - container.appendChild(dataClone); - } - _datamodel.appendChild(container); - - // put data element into nodeset and bind to xpath variable NodeSet<std::string> nodeSet; - nodeSet.push_back(container); _varResolver.setVariable(location, nodeSet); } -void XPathDataModel::init(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { - Element<std::string> data = _doc.createElement("data"); - data.setAttribute("id", location); - if (expr.length() > 0) { - Text<std::string> textNode = _doc.createTextNode(expr.c_str()); - data.appendChild(textNode); - _datamodel.appendChild(data); +void XPathDataModel::assign(const XPathValue<std::string>& key, + const XPathValue<std::string>& value, + const Element<std::string>& assignElem) { + switch (key.type()) { + case NODE_SET: { + switch (value.type()) { + case STRING: + assign(key.asNodeSet(), value.asString(), assignElem); + break; + case BOOL: + assign(key.asNodeSet(), value.asBool(), assignElem); + break; + case NUMBER: + assign(key.asNodeSet(), value.asNumber(), assignElem); + break; + case NODE_SET: + assign(key.asNodeSet(), value.asNodeSet(), assignElem); + break; + case ANY: + throw Event("error.execution", Event::PLATFORM); + } + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); } - - // put data element into nodeset and bind to xpath variable - NodeSet<std::string> nodeSet; - nodeSet.push_back(data); - _varResolver.setVariable(location, nodeSet); } -void XPathDataModel::init(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { -// XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); - init(location, data.atom, dataElem); -} -#endif - -void XPathDataModel::assign(XPathValue<std::string>& key, - const XPathValue<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem) { - switch (value.type()) { - case Arabica::XPath::STRING: - assign(key, value.asString(), assignElem); - break; - case Arabica::XPath::BOOL: - assign(key, value.asBool(), assignElem); - break; - case Arabica::XPath::NUMBER: - assign(key, value.asNumber(), assignElem); - break; - case Arabica::XPath::NODE_SET: - assign(key, value.asNodeSet(), assignElem); - break; - case Arabica::XPath::ANY: - throw Event("error.execution", Event::PLATFORM); +void XPathDataModel::assign(const XPathValue<std::string>& key, + const NodeSet<std::string>& value, + const Element<std::string>& assignElem) { + switch (key.type()) { + case NODE_SET: { + assign(key.asNodeSet(), value, assignElem); + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); } } -void XPathDataModel::assign(XPathValue<std::string>& key, +void XPathDataModel::assign(const NodeSet<std::string>& key, const std::string& value, - const Arabica::DOM::Element<std::string>& assignElem) { - switch (key.type()) { - case Arabica::XPath::NODE_SET: { - if (key.asNodeSet().size() == 0) - return; - for (int i = 0; i < key.asNodeSet().size(); i++) { - Node<std::string> node = key.asNodeSet()[i]; - switch (node.getNodeType()) { - case Node_base::ATTRIBUTE_NODE: { - Attr<std::string> attr(node); - attr.setValue(value); - break; - } - case Node_base::TEXT_NODE: { - Text<std::string> text(node); - text.setNodeValue(value); - break; - } - case Node_base::ELEMENT_NODE: { - Element<std::string> element(node); - if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "addattribute")) { - // addattribute: Add an attribute with the name specified by 'attr' - // and value specified by 'expr' to the node specified by 'location'. - if (!HAS_ATTR(assignElem, "attr")) - throw Event("error.execution", Event::PLATFORM); - element.setAttribute(ATTR(assignElem, "attr"), value); - } else { - /// test 547 - while(element.hasChildNodes()) - element.removeChild(element.getChildNodes().item(0)); - Text<std::string> text = _doc.createTextNode(value); - element.appendChild(text); - } - break; - } - default: - throw Event("error.execution", Event::PLATFORM); - break; + const Element<std::string>& assignElem) { + if (key.size() == 0) + return; + for (int i = 0; i < key.size(); i++) { + Node<std::string> node = key[i]; + switch (node.getNodeType()) { + case Node_base::ATTRIBUTE_NODE: { + Attr<std::string> attr(node); + attr.setValue(value); + break; + } + case Node_base::TEXT_NODE: { + Text<std::string> text(node); + text.setNodeValue(value); + break; + } + case Node_base::ELEMENT_NODE: { + Element<std::string> element(node); + if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "addattribute")) { + // addattribute: Add an attribute with the name specified by 'attr' + // and value specified by 'expr' to the node specified by 'location'. + if (!HAS_ATTR(assignElem, "attr")) + throw Event("error.execution", Event::PLATFORM); + element.setAttribute(ATTR(assignElem, "attr"), value); + } else { + /// test 547 + while(element.hasChildNodes()) + element.removeChild(element.getChildNodes().item(0)); + Text<std::string> text = _doc.createTextNode(value); + element.appendChild(text); } + break; + } + default: + throw Event("error.execution", Event::PLATFORM); + break; } - break; - } - case Arabica::XPath::STRING: - case Arabica::XPath::BOOL: - case Arabica::XPath::NUMBER: - case Arabica::XPath::ANY: - throw Event("error.execution", Event::PLATFORM); - break; - default: - break; } } - -void XPathDataModel::assign(XPathValue<std::string>& key, + +void XPathDataModel::assign(const NodeSet<std::string>& key, const double value, - const Arabica::DOM::Element<std::string>& assignElem) { + const Element<std::string>& assignElem) { assign(key, toStr(value), assignElem); } -void XPathDataModel::assign(XPathValue<std::string>& key, +void XPathDataModel::assign(const NodeSet<std::string>& key, const bool value, - const Arabica::DOM::Element<std::string>& assignElem) { + const Element<std::string>& assignElem) { } -void XPathDataModel::assign(XPathValue<std::string>& key, +void XPathDataModel::assign(const NodeSet<std::string>& key, const NodeSet<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem) { - switch (key.type()) { - case Arabica::XPath::NODE_SET: { - if (key.asNodeSet().size() == 0) - return; - for (int i = 0; i < key.asNodeSet().size(); i++) { - Node<std::string> node = key.asNodeSet()[i]; - switch (node.getNodeType()) { - case Node_base::ELEMENT_NODE: { - Element<std::string> element(node); - if (false) { - } else if (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); - element.insertBefore(importedNode, element.getFirstChild()); - } - } else if (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); - element.appendChild(importedNode); - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { - // previoussibling: Insert the value specified by 'expr' before the - // node specified by 'location', keeping the same parent. - Node<std::string> parent = element.getParentNode(); - 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); - parent.insertBefore(importedNode, element); - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { - // nextsibling: Insert the value specified by 'expr' after the node - // specified by 'location', keeping the same parent. - Node<std::string> parent = element.getParentNode(); - 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> nextSibling = element.getNextSibling(); - if (nextSibling) { - parent.insertBefore(importedNode, element.getNextSibling()); - } else { - parent.appendChild(importedNode); - } - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { - // replace: Replace the node specified by 'location' by the value specified by 'expr'. - Node<std::string> parent = element.getParentNode(); - if (!parent) - 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); - parent.replaceChild(importedNode, element); - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { - // delete: Delete the node specified by 'location'. ('expr' is ignored.). - Node<std::string> parent = element.getParentNode(); - if (!parent) - throw Event("error.execution", Event::PLATFORM); - parent.removeChild(element); - } else { - // replacechildren: Replace all the children at 'location' with the value specified by 'expr'. - 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); - element.appendChild(importedNode); - } - } - break; - } - default: - throw Event("error.execution", Event::PLATFORM); - break; - } + const Element<std::string>& assignElem) { + if (key.size() == 0) + return; + + for (int i = 0; i < key.size(); i++) { + switch (key[i].getNodeType()) { + case Node_base::ELEMENT_NODE: { + assign(Element<std::string>(key[i]), value, assignElem); + break; + } + default: + throw Event("error.execution", Event::PLATFORM); + break; } - break; } - case Arabica::XPath::STRING: - case Arabica::XPath::BOOL: - case Arabica::XPath::NUMBER: - case Arabica::XPath::ANY: - throw Event("error.execution", Event::PLATFORM); - break; +} + +void XPathDataModel::assign(const Element<std::string>& key, + const NodeSet<std::string>& value, + const Element<std::string>& assignElem) { + Element<std::string> element(key); + if (false) { + } else if (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); + element.insertBefore(importedNode, element.getFirstChild()); + } + } else if (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); + element.appendChild(importedNode); + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { + // previoussibling: Insert the value specified by 'expr' before the + // node specified by 'location', keeping the same parent. + Node<std::string> parent = element.getParentNode(); + 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); + parent.insertBefore(importedNode, element); + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { + // nextsibling: Insert the value specified by 'expr' after the node + // specified by 'location', keeping the same parent. + Node<std::string> parent = element.getParentNode(); + 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> nextSibling = element.getNextSibling(); + if (nextSibling) { + parent.insertBefore(importedNode, element.getNextSibling()); + } else { + parent.appendChild(importedNode); + } + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { + // replace: Replace the node specified by 'location' by the value specified by 'expr'. + Node<std::string> parent = element.getParentNode(); + if (!parent) + 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); + parent.replaceChild(importedNode, element); + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { + // delete: Delete the node specified by 'location'. ('expr' is ignored.). + Node<std::string> parent = element.getParentNode(); + if (!parent) + throw Event("error.execution", Event::PLATFORM); + parent.removeChild(element); + } else { + // replacechildren: Replace all the children at 'location' with the value specified by 'expr'. + 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); + element.appendChild(importedNode); + } } } @@ -574,7 +533,7 @@ bool XPathFunctionIn::doEvaluate(const Node<std::string>& context, const ExecutionContext<std::string>& executionContext) const { for (int i = 0; i < argCount(); i++) { XPathValue<std::string> stateName = arg(i, context, executionContext); - if (stateName.type() == Arabica::XPath::STRING) { + if (stateName.type() == STRING) { if (!Interpreter::isMember(_interpreter->getState(stateName.asString()), _interpreter->getConfiguration())) { return false; } diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h index 7df3918..391af0b 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h @@ -55,9 +55,13 @@ public: 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(); + } + private: std::map<std::string, Arabica::XPath::NodeSet<std::string> > _variables; + friend class XPathDataModel; }; class XPathDataModel : public DataModelImpl { @@ -105,19 +109,30 @@ protected: Arabica::DOM::Element<std::string> _datamodel; Arabica::DOM::Document<std::string> _doc; - void assign(Arabica::XPath::XPathValue<std::string>& key, + // resolve value to its type + void assign(const Arabica::XPath::XPathValue<std::string>& key, const Arabica::XPath::XPathValue<std::string>& value, const Arabica::DOM::Element<std::string>& assignElem); - void assign(Arabica::XPath::XPathValue<std::string>& key, + void assign(const Arabica::XPath::XPathValue<std::string>& key, + const Arabica::XPath::NodeSet<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem); + + // assign value to a nodeset key + void assign(const Arabica::XPath::NodeSet<std::string>& key, const std::string& value, const Arabica::DOM::Element<std::string>& assignElem); - void assign(Arabica::XPath::XPathValue<std::string>& key, + void assign(const Arabica::XPath::NodeSet<std::string>& key, const double value, const Arabica::DOM::Element<std::string>& assignElem); - void assign(Arabica::XPath::XPathValue<std::string>& key, + void assign(const Arabica::XPath::NodeSet<std::string>& key, const bool value, const Arabica::DOM::Element<std::string>& assignElem); - void assign(Arabica::XPath::XPathValue<std::string>& key, + void assign(const Arabica::XPath::NodeSet<std::string>& key, + const Arabica::XPath::NodeSet<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem); + + // assign value to an element key (from nodeset) + void assign(const Arabica::DOM::Element<std::string>& key, const Arabica::XPath::NodeSet<std::string>& value, const Arabica::DOM::Element<std::string>& assignElem); diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index 7564f1d..09195bf 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -104,8 +104,9 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { } #endif + /// test532 if (reqEvent.name.length() == 0) - reqEvent.name = req.type; + reqEvent.name = "http." + req.data.compound.at("type").atom; if (!scxmlStructFound) { // get content into event @@ -117,10 +118,15 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { } void BasicHTTPIOProcessor::send(const SendRequest& req) { - + + if (req.target.length() == 0) { + _interpreter->receiveInternal(Event("error.communication", Event::PLATFORM)); + return; + } + bool isLocal = false; std::string target; - if (req.target.length() > 0 && !boost::equals(req.target, _url)) { + if (!boost::equals(req.target, _url)) { target = req.target; } else { isLocal = true; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 96797b8..51bce49 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -85,7 +85,7 @@ if (RUN_W3C_TESTS) foreach( W3C_TEST ${W3C_TESTS} ) string(REGEX MATCH "[^//]+/[^//]+.scxml" TEST_NAME ${W3C_TEST}) - message("TEST_NAME: ${TEST_NAME}") + #message("TEST_NAME: ${TEST_NAME}") if (NOT TEST_NAME MATCHES ".*sub.*") add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST}) endif() diff --git a/test/samples/w3c/ecma/test568.scxml b/test/samples/w3c/ecma/test568.scxml index e8b888f..17bc380 100644 --- a/test/samples/w3c/ecma/test568.scxml +++ b/test/samples/w3c/ecma/test568.scxml @@ -4,7 +4,7 @@ send events. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http: <state id="s0"> - <transition cond="$_ioprocessors/[@name='http://www.w3.org/TR/scxml/#SCXMLEventProcessor']/location/text()" target="pass"/> + <transition cond="$_ioprocessors/processor[@name='http://www.w3.org/TR/scxml/#SCXMLEventProcessor']/location/text()" target="pass"/> <transition target="fail"/> </state> |