summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/uscxml/Interpreter.cpp235
-rw-r--r--src/uscxml/Interpreter.h5
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp206
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.h1
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp5
-rw-r--r--test/samples/w3c/tests/test552.txt1
-rw-r--r--test/samples/w3c/tests/test557.txt4
-rw-r--r--test/samples/w3c/tests/test558.txt3
8 files changed, 261 insertions, 199 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index e252d54..85c2e04 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -31,7 +31,7 @@ catch (Event e) {\
} else {\
e.name = "error.execution";\
e.type = Event::PLATFORM;\
- _internalQueue.push_back(e);\
+ receiveInternal(e);\
}\
}
@@ -296,6 +296,114 @@ void Interpreter::init() {
_isInitialized = true;
}
+/**
+ * Called with a single data element from the topmost datamodel element.
+ */
+void Interpreter::initializeData(const Node<std::string>& data) {
+ if (!_dataModel) {
+ LOG(ERROR) << "Cannot initialize data when no datamodel is given!";
+ return;
+ }
+
+ if (!HAS_ATTR(data, "id")) {
+ LOG(ERROR) << "Data element has no id!";
+ return;
+ }
+
+ /// test 240 - initialize from invoke request
+ if (_invokeReq.params.find(ATTR(data, "id")) != _invokeReq.params.end()) {
+ try {
+ _dataModel.assign(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;
+ receiveInternal(e);
+ }
+ return;
+ }
+ if (_invokeReq.namelist.find(ATTR(data, "id")) != _invokeReq.namelist.end()) {
+ try {
+ _dataModel.assign(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;
+ receiveInternal(e);
+ }
+ return;
+ }
+
+ try {
+ std::string contentToProcess;
+ if (HAS_ATTR(data, "expr")) {
+ // expression given directly
+ std::string value = ATTR(data, "expr");
+ _dataModel.assign(ATTR(data, "id"), value);
+ } else if (HAS_ATTR(data, "src")) {
+ // fetch us some string and proess below
+ URL srcURL(ATTR(data, "src"));
+ if (!srcURL.isAbsolute())
+ toAbsoluteURI(srcURL);
+
+ std::stringstream ss;
+ if (_cachedURLs.find(srcURL.asString()) != _cachedURLs.end()) {
+ ss << _cachedURLs[srcURL.asString()];
+ } else {
+ ss << srcURL;
+ _cachedURLs[srcURL.asString()] = srcURL;
+ }
+ contentToProcess = ss.str();
+ } else if (data.hasChildNodes()) {
+ bool presentAsDom = false;
+ Node<std::string> contentChild = data.getFirstChild();
+ while(contentChild) {
+ if (contentChild.getNodeType() == Node_base::TEXT_NODE) {
+ break;
+ }
+ if (contentChild.getNodeType() == Node_base::ELEMENT_NODE) {
+ presentAsDom = true;
+ break;
+ }
+ contentChild = contentChild.getNextSibling();
+ }
+
+ if (contentChild && presentAsDom) {
+ LOG(ERROR) << "Passing DOM in data is TODO.";
+ } else if (contentChild) {
+ // get first child and process below
+ contentToProcess = contentChild.getNodeValue();
+ } else {
+ LOG(ERROR) << "content element has no text or element children.";
+ }
+ }
+ if (contentToProcess.length() > 0) {
+ /// try to interpret as JSON
+ try {
+ _dataModel.assign(ATTR(data, "id"), contentToProcess);
+ } catch(Event e) {
+ /// create space normalized string if that failed
+ /// test 558
+ std::istringstream iss(contentToProcess);
+ std::stringstream spaceNormalized;
+ std::string seperator;
+ do {
+ std::string token;
+ iss >> token;
+ if (token.length() > 0) {
+ spaceNormalized << seperator << token;
+ seperator = " ";
+ }
+ } while (iss);
+ _dataModel.assign(ATTR(data, "id"), Data(spaceNormalized.str(), Data::VERBATIM));
+ }
+ } else {
+ _dataModel.assign(ATTR(data, "id"), "undefined");
+ }
+
+ } catch (Event e) {
+ LOG(ERROR) << "Syntax error in data element:" << std::endl << e << std::endl;
+ /// test 487
+ receiveInternal(e);
+ }
+}
+
void Interpreter::normalize(Arabica::DOM::Element<std::string>& scxml) {
// make sure every state has an id and set isFirstEntry to true
Arabica::XPath::NodeSet<std::string> states = _xpath.evaluate("//" + _xpathPrefix + "state", _scxml).asNodeSet();
@@ -354,6 +462,11 @@ void Interpreter::normalize(Arabica::DOM::Element<std::string>& scxml) {
std::cout << _scxml <<std::endl;
#endif
}
+
+void Interpreter::receiveInternal(const Event& event) {
+ std::cout << "receiveInternal: " << event.name << std::endl;
+ _internalQueue.push_back(event);
+}
void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state) {
@@ -377,61 +490,66 @@ void Interpreter::internalDoneSend(const Arabica::DOM::Node<std::string>& state)
}
event.name = "done.state." + ATTR(stateElem.getParentNode(), "id"); // parent?!
- _internalQueue.push_back(event);
+ receiveInternal(event);
}
void Interpreter::processContentElement(const Arabica::DOM::Node<std::string>& content, Arabica::DOM::Document<std::string>& dom, std::string& text) {
- if (HAS_ATTR(content, "expr")) {
- if (_dataModel) {
- /// this is out of spec
- std::string contentValue = _dataModel.evalAsString(ATTR(content, "expr"));
- text = contentValue;
- // 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<std::string> contentChilds = content.getChildNodes();
- for (int i = 0; i < contentChilds.getLength(); i++) {
- if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) {
- presentAsDOM = true;
- break;
+ try {
+ if (HAS_ATTR(content, "expr")) {
+ if (_dataModel) {
+ /// this is out of spec
+ std::string contentValue = _dataModel.evalAsString(ATTR(content, "expr"));
+ text = contentValue;
+ // sendReq.data.atom = contentValue;
+ // sendReq.data.type = Data::VERBATIM;
+ } else {
+ LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
}
- }
- if (presentAsDOM) {
- // use the whole dom
- Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- dom = domFactory.createDocument(content.getNamespaceURI(), "", 0);
- Node<std::string> newNode = dom.importNode(content, true);
- dom.appendChild(newNode);
- } else {
- Node<std::string> textChild = content.getFirstChild();
- while(textChild && textChild.getNodeType() != Node_base::TEXT_NODE) {
- textChild = textChild.getNextSibling();
+ } else if (content.hasChildNodes()) {
+ bool presentAsDOM = false;
+ NodeList<std::string> contentChilds = content.getChildNodes();
+ for (int i = 0; i < contentChilds.getLength(); i++) {
+ if (contentChilds.item(i).getNodeType() == Node_base::ELEMENT_NODE) {
+ presentAsDOM = true;
+ break;
+ }
}
- 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();
+ if (presentAsDOM) {
+ // use the whole dom
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ dom = domFactory.createDocument(content.getNamespaceURI(), "", 0);
+ Node<std::string> newNode = dom.importNode(content, true);
+ dom.appendChild(newNode);
} else {
- LOG(ERROR) << "content element has neither text nor element children.";
+ Node<std::string> 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.";
+ }
}
+ } else {
+ LOG(ERROR) << "content element does not specify any content.";
}
- } else {
- LOG(ERROR) << "content element does not specify any content.";
+ } catch (Event e) {
+ e.name = "error.execution";
+ receiveInternal(e);
}
}
@@ -463,7 +581,7 @@ void Interpreter::processParamChilds(const Arabica::DOM::Node<std::string>& elem
params.erase(paramIter++);
}
e.name = "error.execution";
- _internalQueue.push_back(e);
+ receiveInternal(e);
}
}
@@ -634,7 +752,7 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) {
LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl;
}
} else if (boost::iequals(sendReq.target, "#_internal")) {
- INSTANCE->_internalQueue.push_back(sendReq);
+ INSTANCE->receiveInternal(sendReq);
} else if (sendReq.target.find_first_of("#_") == 0) {
// send to invoker
std::string invokeId = sendReq.target.substr(2, sendReq.target.length() - 2);
@@ -647,6 +765,8 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) {
}
} else {
LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl;
+ Event e("error.communication", Event::PLATFORM);
+ INSTANCE->receiveInternal(e);
}
} else if (sendReq.target.length() == 0 &&
(sendReq.type.length() == 0 ||
@@ -672,7 +792,7 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) {
exceptionEvent.name = "error.execution";
exceptionEvent.type = Event::PLATFORM;
exceptionEvent.sendid = sendReq.sendid;
- INSTANCE->_internalQueue.push_back(exceptionEvent);
+ INSTANCE->receiveInternal(exceptionEvent);
}
}
assert(INSTANCE->_sendIds.find(sendReq.sendid) != INSTANCE->_sendIds.end());
@@ -688,8 +808,6 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
invokeReq.type = _dataModel.evalAsString(ATTR(element, "typeexpr"));
} else if (HAS_ATTR(element, "type")) {
invokeReq.type = ATTR(element, "type");
- } else {
- LOG(ERROR) << "invoke element is missing expr or typeexpr or no datamodel is specified";
}
// src
@@ -756,6 +874,10 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
return;
}
+ // test 422
+ if (invokeReq.type.size() == 0)
+ invokeReq.type = "http://www.w3.org/TR/scxml/";
+
Invoker invoker(Factory::createInvoker(invokeReq.type, this));
if (invoker) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
@@ -812,13 +934,14 @@ void Interpreter::cancelInvoke(const Arabica::DOM::Node<std::string>& element) {
} else {
LOG(ERROR) << "Cannot cancel invoke for id " << invokeId << ": no soch invokation";
}
+ //receiveInternal(Event("done.invoke." + invokeId, Event::PLATFORM));
}
// see: http://www.w3.org/TR/scxml/#EventDescriptors
bool Interpreter::nameMatch(const std::string& transitionEvent, const std::string& event) {
- assert(transitionEvent.size() > 0);
- assert(event.size() > 0);
+ if(transitionEvent.length() == 0 || event.length() == 0)
+ return false;
// naive case of single descriptor and exact match
if (boost::equals(transitionEvent, event))
@@ -870,7 +993,7 @@ bool Interpreter::hasConditionMatch(const Arabica::DOM::Node<std::string>& condi
} catch (Event e) {
LOG(ERROR) << "Syntax error in cond attribute of " << TAGNAME(conditional) << " element:" << std::endl << e << std::endl;
e.name = "error.execution";
- _internalQueue.push_back(e);
+ receiveInternal(e);
return false;
}
}
@@ -911,7 +1034,7 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content,
} else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "raise")) {
// --- RAISE --------------------------
if (HAS_ATTR(content, "event")) {
- _internalQueue.push_back(Event(ATTR(content, "event")));
+ receiveInternal(Event(ATTR(content, "event")));
}
} else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "if")) {
// --- IF / ELSEIF / ELSE --------------
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 0352f2b..c2e24fa 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -156,6 +156,7 @@ public:
return "";
}
+ void inline receiveInternal(const Event& event);
void receive(const Event& event, bool toFront = false) {
if (toFront) {
_externalQueue.push_front(event);
@@ -163,9 +164,6 @@ public:
_externalQueue.push(event);
}
}
- void receiveInternal(const Event& event) {
- _internalQueue.push_back(event);
- }
Event getCurrentEvent() {
return _currEvent;
@@ -243,6 +241,7 @@ protected:
void init();
void normalize(Arabica::DOM::Element<std::string>& scxml);
+ void initializeData(const Arabica::DOM::Node<std::string>& data);
void setupIOProcessors();
bool _stable;
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index d8e8296..453e64f 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -84,9 +84,9 @@ void InterpreterDraft6::interpret() {
assert(initialStates.size() > 0);
for (int i = 0; i < initialStates.size(); i++) {
- Arabica::DOM::Element<std::string> initialElem = _document.createElementNS(_nsURL, "initial");
+ Element<std::string> initialElem = _document.createElementNS(_nsURL, "initial");
initialElem.setAttribute("generated", "true");
- Arabica::DOM::Element<std::string> transitionElem = _document.createElementNS(_nsURL, "transition");
+ Element<std::string> transitionElem = _document.createElementNS(_nsURL, "transition");
transitionElem.setAttribute("target", ATTR(initialStates[i], "id"));
initialElem.appendChild(transitionElem);
_scxml.appendChild(initialElem);
@@ -114,74 +114,6 @@ void InterpreterDraft6::interpret() {
}
-/**
- * Called with a single data element from the topmost datamodel element.
- */
-void InterpreterDraft6::initializeData(const Arabica::DOM::Node<std::string>& data) {
- if (!_dataModel) {
- LOG(ERROR) << "Cannot initialize data when no datamodel is given!";
- return;
- }
-
- if (!HAS_ATTR(data, "id")) {
- LOG(ERROR) << "Data element has no id!";
- return;
- }
-
- /// test 240
- if (_invokeReq.params.find(ATTR(data, "id")) != _invokeReq.params.end()) {
- try {
- _dataModel.assign(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;
- }
- return;
- }
- if (_invokeReq.namelist.find(ATTR(data, "id")) != _invokeReq.namelist.end()) {
- try {
- _dataModel.assign(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;
- }
- return;
- }
-
- try {
- if (HAS_ATTR(data, "expr")) {
- std::string value = ATTR(data, "expr");
- _dataModel.assign(ATTR(data, "id"), value);
- } else if (HAS_ATTR(data, "src")) {
- URL srcURL(ATTR(data, "src"));
- if (!srcURL.isAbsolute())
- toAbsoluteURI(srcURL);
-
- std::stringstream ss;
- if (_cachedURLs.find(srcURL.asString()) != _cachedURLs.end()) {
- ss << _cachedURLs[srcURL.asString()];
- } else {
- ss << srcURL;
- _cachedURLs[srcURL.asString()] = srcURL;
- }
- _dataModel.assign(ATTR(data, "id"), ss.str());
-
- } else if (data.hasChildNodes()) {
- // search for the text node with the actual script
- NodeList<std::string> dataChilds = data.getChildNodes();
- for (int i = 0; i < dataChilds.getLength(); i++) {
- if (dataChilds.item(i).getNodeType() == Node_base::TEXT_NODE) {
- Data value = Data(dataChilds.item(i).getNodeValue());
- _dataModel.assign(ATTR(data, "id"), value);
- break;
- }
- }
- } else {
- _dataModel.assign(ATTR(data, "id"), "undefined");
- }
-
- } catch (Event e) {
- LOG(ERROR) << "Syntax error in data element:" << std::endl << e << std::endl;
- }
-}
void InterpreterDraft6::mainEventLoop() {
std::set<InterpreterMonitor*>::iterator monIter;
@@ -298,7 +230,7 @@ void InterpreterDraft6::mainEventLoop() {
for (unsigned int i = 0; i < _configuration.size(); i++) {
NodeSet<std::string> invokes = filterChildElements(_xmlNSPrefix + "invoke", _configuration[i]);
for (unsigned int j = 0; j < invokes.size(); j++) {
- Arabica::DOM::Element<std::string> invokeElem = (Arabica::DOM::Element<std::string>)invokes[j];
+ Element<std::string> invokeElem = (Element<std::string>)invokes[j];
std::string invokeId;
if (HAS_ATTR(invokeElem, "id")) {
invokeId = ATTR(invokeElem, "id");
@@ -316,7 +248,7 @@ void InterpreterDraft6::mainEventLoop() {
Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_xmlNSPrefix + "finalize", invokeElem);
for (int k = 0; k < finalizes.size(); k++) {
- Arabica::DOM::Element<std::string> finalizeElem = Arabica::DOM::Element<std::string>(finalizes[k]);
+ Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
executeContent(finalizeElem);
}
@@ -425,7 +357,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const
return enabledTransitions;
}
-bool InterpreterDraft6::isEnabledTransition(const Arabica::DOM::Node<std::string>& transition, const std::string& event) {
+bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition, const std::string& event) {
std::string eventName;
if (HAS_ATTR(transition, "event")) {
eventName = ATTR(transition, "event");
@@ -440,10 +372,16 @@ bool InterpreterDraft6::isEnabledTransition(const Arabica::DOM::Node<std::string
return false;
}
- if (eventName.length() > 0 &&
- nameMatch(eventName, event) &&
- hasConditionMatch(transition)) {
- return true;
+ std::vector<std::string> eventNames = tokenizeIdRefs(eventName);
+
+ if (eventNames.size() > 0 && hasConditionMatch(transition)) {
+ std::vector<std::string>::iterator eventIter = eventNames.begin();
+ while(eventIter != eventNames.end()) {
+ if(nameMatch(*eventIter, event)) {
+ return true;
+ }
+ eventIter++;
+ }
}
return false;
}
@@ -502,12 +440,12 @@ Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitio
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::filterPreempted(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
Arabica::XPath::NodeSet<std::string> filteredTransitions;
for (unsigned int i = 0; i < enabledTransitions.size(); i++) {
- Arabica::DOM::Node<std::string> t = enabledTransitions[i];
+ Node<std::string> t = enabledTransitions[i];
if (!isTargetless(t)) {
for (unsigned int j = 0; j < filteredTransitions.size(); j++) {
if (j == i)
continue;
- Arabica::DOM::Node<std::string> t2 = filteredTransitions[j];
+ Node<std::string> t2 = filteredTransitions[j];
if (isPreemptingTransition(t2, t)) {
#if 0
std::cout << "#####" << std::endl << "Transition " << std::endl
@@ -531,7 +469,7 @@ LOOP:
/**
* Is t1 preempting t2?
*/
-bool InterpreterDraft6::isPreemptingTransition(const Arabica::DOM::Node<std::string>& t1, const Arabica::DOM::Node<std::string>& t2) {
+bool InterpreterDraft6::isPreemptingTransition(const Node<std::string>& t1, const Node<std::string>& t2) {
assert(t1);
assert(t2);
@@ -551,13 +489,13 @@ bool InterpreterDraft6::isPreemptingTransition(const Arabica::DOM::Node<std::str
return false;
}
-bool InterpreterDraft6::isCrossingBounds(const Arabica::DOM::Node<std::string>& transition) {
+bool InterpreterDraft6::isCrossingBounds(const Node<std::string>& transition) {
if (!isTargetless(transition) && !isWithinParallel(transition))
return true;
return false;
}
-bool InterpreterDraft6::isWithinParallel(const Arabica::DOM::Node<std::string>& transition) {
+bool InterpreterDraft6::isWithinParallel(const Node<std::string>& transition) {
if (isTargetless(transition))
return false;
@@ -570,13 +508,13 @@ bool InterpreterDraft6::isWithinParallel(const Arabica::DOM::Node<std::string>&
NodeSet<std::string> targets = getTargetStates(transition);
targets.push_back(source);
- Arabica::DOM::Node<std::string> lcpa = findLCPA(targets);
+ Node<std::string> lcpa = findLCPA(targets);
return lcpa;
}
-Arabica::DOM::Node<std::string> InterpreterDraft6::findLCPA(const Arabica::XPath::NodeSet<std::string>& states) {
- Arabica::XPath::NodeSet<std::string> ancestors = getProperAncestors(states[0], Arabica::DOM::Node<std::string>());
- Arabica::DOM::Node<std::string> ancestor;
+Node<std::string> InterpreterDraft6::findLCPA(const Arabica::XPath::NodeSet<std::string>& states) {
+ Arabica::XPath::NodeSet<std::string> ancestors = getProperAncestors(states[0], Node<std::string>());
+ Node<std::string> ancestor;
for (int i = 0; i < ancestors.size(); i++) {
if (!isParallel(ancestors[i]))
continue;
@@ -596,10 +534,10 @@ void InterpreterDraft6::microstep(const Arabica::XPath::NodeSet<std::string>& en
#if 0
std::cout << "Transitions: ";
for (int i = 0; i < enabledTransitions.size(); i++) {
- std::cout << ((Arabica::DOM::Element<std::string>)getSourceState(enabledTransitions[i])).getAttribute("id") << " -> " << std::endl;
+ std::cout << ((Element<std::string>)getSourceState(enabledTransitions[i])).getAttribute("id") << " -> " << std::endl;
NodeSet<std::string> targetSet = getTargetStates(enabledTransitions[i]);
for (int j = 0; j < targetSet.size(); j++) {
- std::cout << " " << ((Arabica::DOM::Element<std::string>)targetSet[j]).getAttribute("id") << std::endl;
+ std::cout << " " << ((Element<std::string>)targetSet[j]).getAttribute("id") << std::endl;
}
}
std::cout << std::endl;
@@ -612,8 +550,8 @@ void InterpreterDraft6::microstep(const Arabica::XPath::NodeSet<std::string>& en
void InterpreterDraft6::exitInterpreter() {
NodeSet<std::string> statesToExit = _configuration;
- statesToExit.to_document_order();
- statesToExit.reverse();
+ statesToExit.forward(false);
+ statesToExit.sort();
for (int i = 0; i < statesToExit.size(); i++) {
Arabica::XPath::NodeSet<std::string> onExitElems = filterChildElements(_xmlNSPrefix + "onexit", statesToExit[i]);
@@ -645,13 +583,12 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
#endif
for (int i = 0; i < enabledTransitions.size(); i++) {
- Arabica::DOM::Element<std::string> transition = ((Arabica::DOM::Element<std::string>)enabledTransitions[i]);
- if (!isTargetless(transition)) {
- std::string transitionType = (boost::iequals(transition.getAttribute("type"), "internal") ? "internal" : "external");
- NodeSet<std::string> tStates = getTargetStates(transition);
- Arabica::DOM::Node<std::string> ancestor;
- Arabica::DOM::Node<std::string> source = getSourceState(transition);
-
+ Element<std::string> t = ((Element<std::string>)enabledTransitions[i]);
+ if (!isTargetless(t)) {
+ Node<std::string> ancestor;
+ Node<std::string> source = getSourceState(t);
+ NodeSet<std::string> tStates = getTargetStates(t);
+ bool isInternal = (HAS_ATTR(t, "type") && boost::iequals(ATTR(t, "type"), "internal")); // external is default
bool allDescendants = true;
for (int j = 0; j < tStates.size(); j++) {
if (!isDescendant(tStates[j], source)) {
@@ -659,15 +596,12 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
break;
}
}
- if (boost::iequals(transitionType, "internal") &&
- isCompound(source) &&
- allDescendants) {
+ if (isInternal && allDescendants && isCompound(source)) {
ancestor = source;
} else {
NodeSet<std::string> tmpStates;
tmpStates.push_back(source);
tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end());
-
#if VERBOSE
std::cout << "tmpStates: ";
for (int i = 0; i < tmpStates.size(); i++) {
@@ -677,29 +611,17 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
#endif
ancestor = findLCCA(tmpStates);
}
-
#if VERBOSE
std::cout << "Ancestor: " << ATTR(ancestor, "id") << std::endl;;
#endif
-
for (int j = 0; j < _configuration.size(); j++) {
if (isDescendant(_configuration[j], ancestor))
statesToExit.push_back(_configuration[j]);
- }
+ }
}
}
-
-#if VERBOSE
- std::cout << "States to exit: ";
- for (int i = 0; i < statesToExit.size(); i++) {
- std::cout << LOCALNAME(statesToExit[i]) << ":" << ATTR(statesToExit[i], "id") << ", ";
- }
- std::cout << std::endl;
-
-#endif
-
// remove statesToExit from _statesToInvoke
- std::list<Arabica::DOM::Node<std::string> > tmp;
+ std::list<Node<std::string> > tmp;
for (int i = 0; i < _statesToInvoke.size(); i++) {
if (!isMember(_statesToInvoke[i], statesToExit)) {
tmp.push_back(_statesToInvoke[i]);
@@ -708,9 +630,17 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
_statesToInvoke = NodeSet<std::string>();
_statesToInvoke.insert(_statesToInvoke.end(), tmp.begin(), tmp.end());
- statesToExit.to_document_order();
- statesToExit.reverse();
+ statesToExit.forward(false);
+ statesToExit.sort();
+#if VERBOSE
+ std::cout << "States to exit: ";
+ for (int i = 0; i < statesToExit.size(); i++) {
+ std::cout << LOCALNAME(statesToExit[i]) << ":" << ATTR(statesToExit[i], "id") << ", ";
+ }
+ std::cout << std::endl;
+#endif
+
monIter = _monitors.begin();
while(monIter != _monitors.end()) {
try {
@@ -726,7 +656,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
for (int i = 0; i < statesToExit.size(); i++) {
NodeSet<std::string> histories = filterChildElements(_xmlNSPrefix + "history", statesToExit[i]);
for (int j = 0; j < histories.size(); j++) {
- Arabica::DOM::Element<std::string> historyElem = (Arabica::DOM::Element<std::string>)histories[j];
+ Element<std::string> historyElem = (Element<std::string>)histories[j];
std::string historyType = (historyElem.hasAttribute("type") ? historyElem.getAttribute("type") : "shallow");
NodeSet<std::string> historyNodes;
for (int k = 0; k < _configuration.size(); k++) {
@@ -745,7 +675,6 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
std::cout << ATTR(historyNodes[i], "id") << ", ";
}
std::cout << std::endl;
-
#endif
}
@@ -754,25 +683,24 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e
for (int i = 0; i < statesToExit.size(); i++) {
NodeSet<std::string> onExits = filterChildElements(_xmlNSPrefix + "onExit", statesToExit[i]);
for (int j = 0; j < onExits.size(); j++) {
- Arabica::DOM::Element<std::string> onExitElem = (Arabica::DOM::Element<std::string>)onExits[j];
+ Element<std::string> onExitElem = (Element<std::string>)onExits[j];
executeContent(onExitElem);
}
NodeSet<std::string> invokes = filterChildElements(_xmlNSPrefix + "invoke", statesToExit[i]);
for (int j = 0; j < invokes.size(); j++) {
- Arabica::DOM::Element<std::string> invokeElem = (Arabica::DOM::Element<std::string>)invokes[j];
+ Element<std::string> invokeElem = (Element<std::string>)invokes[j];
cancelInvoke(invokeElem);
}
- }
-
- // remove statesToExit from _configuration
- tmp.clear();
- for (int i = 0; i < _configuration.size(); i++) {
- if (!isMember(_configuration[i], statesToExit)) {
- tmp.push_back(_configuration[i]);
+ // remove statesToExit[i] from _configuration - test409
+ tmp.clear();
+ for (int j = 0; j < _configuration.size(); j++) {
+ if (_configuration[j] != statesToExit[i]) {
+ tmp.push_back(_configuration[j]);
+ }
}
+ _configuration = NodeSet<std::string>();
+ _configuration.insert(_configuration.end(), tmp.begin(), tmp.end());
}
- _configuration = NodeSet<std::string>();
- _configuration.insert(_configuration.end(), tmp.begin(), tmp.end());
monIter = _monitors.begin();
while(monIter != _monitors.end()) {
@@ -802,7 +730,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
#endif
for (int i = 0; i < enabledTransitions.size(); i++) {
- Arabica::DOM::Element<std::string> transition = ((Arabica::DOM::Element<std::string>)enabledTransitions[i]);
+ Element<std::string> transition = ((Element<std::string>)enabledTransitions[i]);
if (!isTargetless(transition)) {
std::string transitionType = (boost::iequals(transition.getAttribute("type"), "internal") ? "internal" : "external");
NodeSet<std::string> tStates = getTargetStates(transition);
@@ -815,8 +743,8 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
std::cout << std::endl;
#endif
- Arabica::DOM::Node<std::string> ancestor;
- Arabica::DOM::Node<std::string> source = getSourceState(transition);
+ Node<std::string> ancestor;
+ Node<std::string> source = getSourceState(transition);
#if VERBOSE
std::cout << "Source States: " << ATTR(source, "id") << std::endl;
#endif
@@ -904,7 +832,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
}
for (int i = 0; i < statesToEnter.size(); i++) {
- Arabica::DOM::Element<std::string> stateElem = (Arabica::DOM::Element<std::string>)statesToEnter[i];
+ Element<std::string> stateElem = (Element<std::string>)statesToEnter[i];
_configuration.push_back(stateElem);
_statesToInvoke.push_back(stateElem);
if (_binding == LATE && stateElem.getAttribute("isFirstEntry").size() > 0) {
@@ -931,10 +859,10 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
if (isFinal(stateElem)) {
internalDoneSend(stateElem);
- Arabica::DOM::Element<std::string> parent = (Arabica::DOM::Element<std::string>)stateElem.getParentNode();
+ Element<std::string> parent = (Element<std::string>)stateElem.getParentNode();
if (isParallel(parent.getParentNode())) {
- Arabica::DOM::Element<std::string> grandParent = (Arabica::DOM::Element<std::string>)parent.getParentNode();
+ Element<std::string> grandParent = (Element<std::string>)parent.getParentNode();
Arabica::XPath::NodeSet<std::string> childs = getChildStates(grandParent);
bool inFinalState = true;
@@ -951,7 +879,7 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
}
}
for (int i = 0; i < _configuration.size(); i++) {
- Arabica::DOM::Element<std::string> stateElem = (Arabica::DOM::Element<std::string>)_configuration[i];
+ Element<std::string> stateElem = (Element<std::string>)_configuration[i];
if (isFinal(stateElem) && parentIsScxmlState(stateElem)) {
_running = false;
_done = true;
@@ -972,10 +900,10 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
}
-void InterpreterDraft6::addStatesToEnter(const Arabica::DOM::Node<std::string>& state,
+void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state,
Arabica::XPath::NodeSet<std::string>& statesToEnter,
Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry) {
- std::string stateId = ((Arabica::DOM::Element<std::string>)state).getAttribute("id");
+ std::string stateId = ((Element<std::string>)state).getAttribute("id");
#if VERBOSE
std::cout << "Adding state to enter: " << stateId << std::endl;
diff --git a/src/uscxml/interpreter/InterpreterDraft6.h b/src/uscxml/interpreter/InterpreterDraft6.h
index c0af7dc..9ecfd3b 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.h
+++ b/src/uscxml/interpreter/InterpreterDraft6.h
@@ -10,7 +10,6 @@ protected:
void interpret();
void mainEventLoop();
- void initializeData(const Arabica::DOM::Node<std::string>& data);
void microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions);
void enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions);
void addStatesToEnter(const Arabica::DOM::Node<std::string>& state,
diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
index 7ad528d..bbd2538 100644
--- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
@@ -48,6 +48,8 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) {
_invokedInterpreter = Interpreter::fromURI(req.src);
} else if (req.dom) {
_invokedInterpreter = Interpreter::fromDOM(req.dom);
+ } else if (req.content.size() > 0) {
+ LOG(ERROR) << "Instantiating nested SCXML interpreter by content not supported yet";
} else {
LOG(ERROR) << "Cannot invoke nested SCXML interpreter, neither src attribute nor DOM is given";
}
@@ -73,6 +75,9 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) {
_invokedInterpreter->setInvokeRequest(req);
_invokedInterpreter->start();
+ } else {
+ /// test 530
+ _parentInterpreter->receive(Event("done.invoke." + _invokeId, Event::PLATFORM));
}
}
diff --git a/test/samples/w3c/tests/test552.txt b/test/samples/w3c/tests/test552.txt
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/test/samples/w3c/tests/test552.txt
@@ -0,0 +1 @@
+2
diff --git a/test/samples/w3c/tests/test557.txt b/test/samples/w3c/tests/test557.txt
new file mode 100644
index 0000000..a8e51da
--- /dev/null
+++ b/test/samples/w3c/tests/test557.txt
@@ -0,0 +1,4 @@
+<books xmlns="">
+ <book title="title1"/>
+ <book title="title2"/>
+ </books> \ No newline at end of file
diff --git a/test/samples/w3c/tests/test558.txt b/test/samples/w3c/tests/test558.txt
new file mode 100644
index 0000000..bb2bcc7
--- /dev/null
+++ b/test/samples/w3c/tests/test558.txt
@@ -0,0 +1,3 @@
+
+this is
+a string \ No newline at end of file