diff options
Diffstat (limited to 'src/uscxml/debug/InterpreterIssue.cpp')
-rw-r--r-- | src/uscxml/debug/InterpreterIssue.cpp | 601 |
1 files changed, 349 insertions, 252 deletions
diff --git a/src/uscxml/debug/InterpreterIssue.cpp b/src/uscxml/debug/InterpreterIssue.cpp index 1bb14f6..ce61af6 100644 --- a/src/uscxml/debug/InterpreterIssue.cpp +++ b/src/uscxml/debug/InterpreterIssue.cpp @@ -20,67 +20,128 @@ #include <string> #include "InterpreterIssue.h" -#include "uscxml/dom/DOMUtils.h" -#include "uscxml/debug/Complexity.h" +#include "uscxml/util/DOM.h" +#include "uscxml/util/String.h" +#include "uscxml/util/Predicates.h" +//#include "uscxml/debug/Complexity.h" #include "uscxml/Interpreter.h" -#include "uscxml/Factory.h" +#include "uscxml/plugins/Factory.h" -#include <XPath/XPath.hpp> -#include <DOM/Document.hpp> +#include <xercesc/dom/DOMDocument.hpp> namespace uscxml { -using namespace Arabica::XPath; -using namespace Arabica::DOM; +using namespace xercesc; -InterpreterIssue::InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity, const std::string& specRef) : message(msg), node(node), severity(severity), specRef(specRef) { +InterpreterIssue::InterpreterIssue(const std::string& msg, DOMNode* node, IssueSeverity severity, const std::string& specRef) : message(msg), node(node), severity(severity), specRef(specRef) { if (node) xPath = DOMUtils::xPathForNode(node); } // find all elements in the SCXML namespace in one traversal -void assembleNodeSets(const std::string nsPrefix, const Node<std::string>& node, std::map<std::string, NodeSet<std::string> >& sets) { - NodeList<std::string> childs = node.getChildNodes(); - for (unsigned int i = 0; i < childs.getLength(); i++) { - if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE) +void assembleNodeSets(const std::string nsPrefix, DOMNode* node, std::map<std::string, std::list<DOMElement*> >& sets) { + DOMNodeList* childs = node->getChildNodes(); + for (unsigned int i = 0; i < childs->getLength(); i++) { + if (childs->item(i)->getNodeType() != DOMNode::ELEMENT_NODE) continue; // std::cout << TAGNAME(childs.item(i)) << std::endl; - if (TAGNAME_CAST(childs.item(i)).find(nsPrefix) == 0) { + if (TAGNAME_CAST(childs->item(i)).find(nsPrefix) == 0) { // correct namespace, insert via localname - sets[LOCALNAME_CAST(childs.item(i))].push_back(childs.item(i)); + sets[LOCALNAME_CAST(childs->item(i))].push_back(static_cast<DOMElement*>(childs->item(i))); } - assembleNodeSets(nsPrefix, childs.item(i), sets); + assembleNodeSets(nsPrefix, childs->item(i), sets); } } +std::list<std::set<const DOMElement* > > getAllConfigurations(const DOMElement* root) { + std::list<std::set<const DOMElement* > > allConfigurations; + std::string nsPrefix = X(root->getPrefix()); + std::string localName = X(root->getLocalName()); + bool isAtomic = true; + + std::cout << *root; + + DOMNodeList* children = root->getChildNodes(); + for (size_t i = 0; i < children->getLength(); i++) { + if (children->item(i)->getNodeType() != DOMNode::ELEMENT_NODE) + continue; + DOMElement* childElem = static_cast<DOMElement*>(children->item(i)); + std::cout << *childElem; + + if (XMLString::compareIString(childElem->getTagName(), X(nsPrefix + "state")) == 0 || + XMLString::compareIString(childElem->getTagName(), X(nsPrefix + "parallel")) == 0 || + XMLString::compareIString(childElem->getTagName(), X(nsPrefix + "final")) == 0) { + // nested child state + std::list<std::set<const DOMElement*> > nestedConfigurations = getAllConfigurations(childElem); + isAtomic = false; + if (localName == "parallel" && allConfigurations.size() > 0) { + // for every nested configuration, every new nested is valid + std::list<std::set<const DOMElement*> > combinedConfigurations; + for (auto existIter = allConfigurations.begin(); existIter != allConfigurations.end(); existIter++) { + std::set<const DOMElement*> existingConfig = *existIter; + + for (auto newIter = nestedConfigurations.begin(); newIter != nestedConfigurations.end(); newIter++) { + + std::set<const DOMElement*> newConfig = *newIter; + std::set<const DOMElement*> combinedSet; + combinedSet.insert(existingConfig.begin(), existingConfig.end()); + combinedSet.insert(newConfig.begin(), newConfig.end()); + + combinedConfigurations.push_back(combinedSet); + } + } + allConfigurations = combinedConfigurations; + } else { + // just add nested configurations and this + for (auto newIter = nestedConfigurations.begin(); newIter != nestedConfigurations.end(); newIter++) { + std::set<const DOMElement*> newConfig = *newIter; + if (localName != "scxml") + newConfig.insert(root); + allConfigurations.push_back(newConfig); + } + } + } + } + + if (isAtomic) { + std::set<const DOMElement*> soleConfig; + soleConfig.insert(root); + allConfigurations.push_back(soleConfig); + } + return allConfigurations; + +} /** * Can the given states ever appear in an active configuration? */ -bool hasLegalCompletion(const NodeSet<std::string>& states) { +bool hasLegalCompletion(const std::list<DOMElement*>& states) { if (states.size() < 2) return true; // iterate every pair - for (unsigned int outer = 0; outer < states.size() - 1; outer++) { - Element<std::string> s1(states[outer]); - for (unsigned int inner = outer + 1; inner < states.size(); inner++) { - Element<std::string> s2(states[inner]); - Node<std::string> parent; + for (auto outer = states.begin(); outer != states.end(); outer++) { + DOMElement* s1 = *outer; + for (auto inner = outer; inner != states.end(); inner++) { + if (inner == outer) + continue; + + DOMElement* s2 = *inner; + DOMNode* parent; // ok to be directly ancestorally related - if (InterpreterImpl::isDescendant(s1, s2) || InterpreterImpl::isDescendant(s2, s1)) + if (DOMUtils::isDescendant(s1, s2) || DOMUtils::isDescendant(s2, s1)) goto NEXT_PAIR; // find least common ancestor - parent = s1.getParentNode(); - while(parent && parent.getNodeType() == Node_base::ELEMENT_NODE) { - if (InterpreterImpl::isDescendant(s2, parent)) { - if (InterpreterImpl::isParallel(Element<std::string>(parent))) + parent = s1->getParentNode(); + while(parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) { + if (DOMUtils::isDescendant(s2, parent)) { + if (isParallel(static_cast<DOMElement*>(parent))) goto NEXT_PAIR; } - parent = parent.getParentNode(); + parent = parent->getParentNode(); } return false; @@ -100,91 +161,90 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in std::list<InterpreterIssue> issues; if (!interpreter->_scxml) { - InterpreterIssue issue("No SCXML element to be found", Node<std::string>(), InterpreterIssue::USCXML_ISSUE_FATAL); + InterpreterIssue issue("No SCXML element to be found", NULL, InterpreterIssue::USCXML_ISSUE_FATAL); issues.push_back(issue); return issues; } - std::map<std::string, Arabica::DOM::Element<std::string> > seenStates; + std::map<std::string, DOMElement* > seenStates; // get some aliases - Element<std::string>& _scxml = interpreter->_scxml; - NameSpaceInfo& _nsInfo = interpreter->_nsInfo; + DOMElement* _scxml = interpreter->_scxml; Factory* _factory = interpreter->_factory; DataModel& _dataModel = interpreter->_dataModel; + std::string xmlNSPrefix = interpreter->_xmlPrefix; + std::map<std::string, std::list<DOMElement*> > nodeSets; + assembleNodeSets(xmlNSPrefix, _scxml, nodeSets); - std::map<std::string, NodeSet<std::string> > nodeSets; - assembleNodeSets(_nsInfo.xmlNSPrefix, _scxml, nodeSets); - - NodeSet<std::string> scxmls = nodeSets["scxml"]; + std::list<DOMElement*> scxmls = nodeSets["scxml"]; scxmls.push_back(_scxml); - NodeSet<std::string> reachable = interpreter->getReachableStates(); - - NodeSet<std::string>& states = nodeSets["state"]; - NodeSet<std::string>& parallels = nodeSets["parallel"]; - NodeSet<std::string>& transitions = nodeSets["transition"]; - NodeSet<std::string>& initials = nodeSets["initial"]; - NodeSet<std::string>& finals = nodeSets["final"]; - NodeSet<std::string>& onEntries = nodeSets["onentry"]; - NodeSet<std::string>& onExits = nodeSets["onexit"]; - NodeSet<std::string>& histories = nodeSets["history"]; - - NodeSet<std::string>& raises = nodeSets["raise"]; - NodeSet<std::string>& ifs = nodeSets["if"]; - NodeSet<std::string>& elseIfs = nodeSets["elseif"]; - NodeSet<std::string>& elses = nodeSets["else"]; - NodeSet<std::string>& foreachs = nodeSets["foreach"]; - NodeSet<std::string>& logs = nodeSets["log"]; - - NodeSet<std::string>& dataModels = nodeSets["datamodel"]; - NodeSet<std::string>& datas = nodeSets["data"]; - NodeSet<std::string>& assigns = nodeSets["assign"]; - NodeSet<std::string>& doneDatas = nodeSets["donedata"]; - NodeSet<std::string>& contents = nodeSets["content"]; - NodeSet<std::string>& params = nodeSets["param"]; - NodeSet<std::string>& scripts = nodeSets["script"]; - - NodeSet<std::string>& sends = nodeSets["send"]; - NodeSet<std::string>& cancels = nodeSets["cancel"]; - NodeSet<std::string>& invokes = nodeSets["invoke"]; - NodeSet<std::string>& finalizes = nodeSets["finalize"]; - - NodeSet<std::string> allStates; - allStates.push_back(states); - allStates.push_back(parallels); - allStates.push_back(histories); - allStates.push_back(finals); - - NodeSet<std::string> allExecContents; - allExecContents.push_back(raises); - allExecContents.push_back(ifs); - allExecContents.push_back(elseIfs); - allExecContents.push_back(elses); - allExecContents.push_back(foreachs); - allExecContents.push_back(logs); - allExecContents.push_back(sends); - allExecContents.push_back(assigns); - allExecContents.push_back(scripts); - allExecContents.push_back(cancels); - - NodeSet<std::string> allElements; - allElements.push_back(scxmls); - allElements.push_back(allStates); - allElements.push_back(allExecContents); - allElements.push_back(transitions); - allElements.push_back(initials); - allElements.push_back(onEntries); - allElements.push_back(onExits); - allElements.push_back(dataModels); - allElements.push_back(datas); - allElements.push_back(doneDatas); - allElements.push_back(contents); - allElements.push_back(params); - allElements.push_back(invokes); - allElements.push_back(finalizes); + std::list<xercesc::DOMElement*> reachable = getReachableStates(_scxml); + + std::list<DOMElement*>& states = nodeSets["state"]; + std::list<DOMElement*>& parallels = nodeSets["parallel"]; + std::list<DOMElement*>& transitions = nodeSets["transition"]; + std::list<DOMElement*>& initials = nodeSets["initial"]; + std::list<DOMElement*>& finals = nodeSets["final"]; + std::list<DOMElement*>& onEntries = nodeSets["onentry"]; + std::list<DOMElement*>& onExits = nodeSets["onexit"]; + std::list<DOMElement*>& histories = nodeSets["history"]; + + std::list<DOMElement*>& raises = nodeSets["raise"]; + std::list<DOMElement*>& ifs = nodeSets["if"]; + std::list<DOMElement*>& elseIfs = nodeSets["elseif"]; + std::list<DOMElement*>& elses = nodeSets["else"]; + std::list<DOMElement*>& foreachs = nodeSets["foreach"]; + std::list<DOMElement*>& logs = nodeSets["log"]; + + std::list<DOMElement*>& dataModels = nodeSets["datamodel"]; + std::list<DOMElement*>& datas = nodeSets["data"]; + std::list<DOMElement*>& assigns = nodeSets["assign"]; + std::list<DOMElement*>& doneDatas = nodeSets["donedata"]; + std::list<DOMElement*>& contents = nodeSets["content"]; + std::list<DOMElement*>& params = nodeSets["param"]; + std::list<DOMElement*>& scripts = nodeSets["script"]; + + std::list<DOMElement*>& sends = nodeSets["send"]; + std::list<DOMElement*>& cancels = nodeSets["cancel"]; + std::list<DOMElement*>& invokes = nodeSets["invoke"]; + std::list<DOMElement*>& finalizes = nodeSets["finalize"]; + + std::list<DOMElement*> allStates; + allStates.insert(allStates.end(), states.begin(), states.end()); + allStates.insert(allStates.end(), parallels.begin(), parallels.end()); + allStates.insert(allStates.end(), histories.begin(), histories.end()); + allStates.insert(allStates.end(), finals.begin(), finals.end()); + + std::list<DOMElement*> allExecContents; + allExecContents.insert(allExecContents.end(), raises.begin(), raises.end()); + allExecContents.insert(allExecContents.end(), ifs.begin(), ifs.end()); + allExecContents.insert(allExecContents.end(), elseIfs.begin(), elseIfs.end()); + allExecContents.insert(allExecContents.end(), elses.begin(), elses.end()); + allExecContents.insert(allExecContents.end(), foreachs.begin(), foreachs.end()); + allExecContents.insert(allExecContents.end(), logs.begin(), logs.end()); + allExecContents.insert(allExecContents.end(), sends.begin(), sends.end()); + allExecContents.insert(allExecContents.end(), assigns.begin(), assigns.end()); + allExecContents.insert(allExecContents.end(), scripts.begin(), scripts.end()); + allExecContents.insert(allExecContents.end(), cancels.begin(), cancels.end()); + + std::list<DOMElement*> allElements; + allElements.insert(allElements.end(), scxmls.begin(), scxmls.end()); + allElements.insert(allElements.end(), allStates.begin(), allStates.end()); + allElements.insert(allElements.end(), allExecContents.begin(), allExecContents.end()); + allElements.insert(allElements.end(), transitions.begin(), transitions.end()); + allElements.insert(allElements.end(), initials.begin(), initials.end()); + allElements.insert(allElements.end(), onEntries.begin(), onEntries.end()); + allElements.insert(allElements.end(), onExits.begin(), onExits.end()); + allElements.insert(allElements.end(), dataModels.begin(), dataModels.end()); + allElements.insert(allElements.end(), datas.begin(), datas.end()); + allElements.insert(allElements.end(), doneDatas.begin(), doneDatas.end()); + allElements.insert(allElements.end(), contents.begin(), contents.end()); + allElements.insert(allElements.end(), params.begin(), params.end()); + allElements.insert(allElements.end(), invokes.begin(), invokes.end()); + allElements.insert(allElements.end(), finalizes.begin(), finalizes.end()); std::set<std::string> execContentSet; @@ -278,10 +338,10 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in } - for (size_t i = 0; i < allStates.size(); i++) { - Element<std::string> state = Element<std::string>(allStates[i]); + for (auto stateIter = allStates.begin(); stateIter != allStates.end(); stateIter++) { + DOMElement* state = static_cast<DOMElement*>(*stateIter); - if (InterpreterImpl::isMember(state, finals) && !HAS_ATTR(state, "id")) // id is not required for finals + if (DOMUtils::isMember(state, finals) && !HAS_ATTR(state, "id")) // id is not required for finals continue; // check for existance of id attribute - this not actually required! @@ -299,13 +359,13 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in // check for valid transition with history states if (LOCALNAME(state) == "history") { - NodeSet<std::string> transitions = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", state, false); + std::list<DOMElement*> transitions = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "transition", state, false); if (transitions.size() > 1) { issues.push_back(InterpreterIssue("History pseudo-state with id '" + stateId + "' has multiple transitions", state, InterpreterIssue::USCXML_ISSUE_FATAL)); } else if (transitions.size() == 0) { issues.push_back(InterpreterIssue("History pseudo-state with id '" + stateId + "' has no default transition", state, InterpreterIssue::USCXML_ISSUE_FATAL)); } else { - Element<std::string> transition = Element<std::string>(transitions[0]); + DOMElement* transition = static_cast<DOMElement*>(transitions.front()); if (HAS_ATTR(transition, "cond")) { issues.push_back(InterpreterIssue("Transition in history pseudo-state '" + stateId + "' must not have a condition", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } @@ -315,16 +375,16 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in if (!HAS_ATTR(transition, "target")) { issues.push_back(InterpreterIssue("Transition in history pseudo-state '" + stateId + "' has no target", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } else { - NodeSet<std::string> targetStates = interpreter->getTargetStates(transition); - for (size_t j = 0; j < targetStates.size(); j++) { - Element<std::string> target = Element<std::string>(targetStates[j]); + std::list<DOMElement*> targetStates = getTargetStates(transition, _scxml); + for (auto tIter = targetStates.begin(); tIter != targetStates.end(); tIter++) { + DOMElement* target = *tIter; if (HAS_ATTR(state, "type") && ATTR(state, "type") == "deep") { - if (!InterpreterImpl::isDescendant(target, state.getParentNode())) { - issues.push_back(InterpreterIssue("Transition in deep history pseudo-state '" + stateId + "' has invalid target state '" + ATTR(target, "id") + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); + if (!DOMUtils::isDescendant(target, state->getParentNode())) { + issues.push_back(InterpreterIssue("Transition in deep history pseudo-state '" + stateId + "' has illegal target state '" + ATTR(target, "id") + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } } else { - if (target.getParentNode() != state.getParentNode()) { - issues.push_back(InterpreterIssue("Transition in shallow history pseudo-state '" + stateId + "' has invalid target state '" + ATTR(target, "id") + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); + if (target->getParentNode() != state->getParentNode()) { + issues.push_back(InterpreterIssue("Transition in shallow history pseudo-state '" + stateId + "' has illegal target state '" + ATTR(target, "id") + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } } } @@ -333,7 +393,7 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in } // check whether state is reachable - if (!InterpreterImpl::isMember(state, reachable) && !InterpreterImpl::isInEmbeddedDocument(state)) { + if (!DOMUtils::isMember(state, reachable) && !isInEmbeddedDocument(state)) { issues.push_back(InterpreterIssue("State with id '" + stateId + "' is unreachable", state, InterpreterIssue::USCXML_ISSUE_FATAL)); } @@ -345,8 +405,8 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in seenStates[ATTR(state, "id")] = state; } - for (size_t i = 0; i < transitions.size(); i++) { - Element<std::string> transition = Element<std::string>(transitions[i]); + for (auto tIter = transitions.begin(); tIter != transitions.end(); tIter++) { + DOMElement* transition = *tIter; // check for valid target if (HAS_ATTR(transition, "target")) { @@ -365,16 +425,14 @@ std::list<InterpreterIssue> InterpreterIssue::forInterpreter(InterpreterImpl* in } // check for redundancy of transition - for (size_t i = 0; i < allStates.size(); i++) { - Element<std::string> state = Element<std::string>(allStates[i]); - NodeSet<std::string> transitions = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", state, false); - - transitions.to_document_order(); + for (auto stateIter = allStates.begin(); stateIter != allStates.end(); stateIter++) { + DOMElement* state = *stateIter; + std::list<DOMElement*> transitions = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "transition", state, false); - for (size_t j = 1; j < transitions.size(); j++) { - Element<std::string> transition = Element<std::string>(transitions[j]); - for (size_t k = 0; k < j; k++) { - Element<std::string> earlierTransition = Element<std::string>(transitions[k]); + for (auto tIter = transitions.begin(); tIter != transitions.end(); tIter++) { + DOMElement* transition = *tIter; + for (auto t2Iter = transitions.begin(); t2Iter != tIter; t2Iter++) { + DOMElement* earlierTransition = *t2Iter; // will the earlier transition always be enabled when the later is? if (!HAS_ATTR(earlierTransition, "cond")) { @@ -410,16 +468,18 @@ NEXT_TRANSITION: // check for useless history elements { - for (size_t i = 0; i < histories.size(); i++) { - Element<std::string> history = Element<std::string>(histories[i]); - if (!history.getParentNode() || history.getParentNode().getNodeType() != Node_base::ELEMENT_NODE) + for (auto histIter = histories.begin(); histIter != histories.end(); histIter++) { + DOMElement* history = *histIter; + + if (!history->getParentNode() || history->getParentNode()->getNodeType() != DOMNode::ELEMENT_NODE) continue; // syntax check will have catched this - Element<std::string> parent(history.getParentNode()); - if (InterpreterImpl::isAtomic(parent)) { + + DOMElement* parent = static_cast<DOMElement*>(history->getParentNode()); + if (isAtomic(parent)) { issues.push_back(InterpreterIssue("Useless history '" + ATTR(history, "id") + "' in atomic state", history, InterpreterIssue::USCXML_ISSUE_INFO)); continue; } - std::list<std::set<Arabica::DOM::Element<std::string> > > configs = Complexity::getAllConfigurations(parent); + std::list<std::set<const DOMElement* > > configs = getAllConfigurations(parent); if (configs.size() <= 1) { issues.push_back(InterpreterIssue("Useless history '" + ATTR(history, "id") + "' in state with single legal configuration", history, InterpreterIssue::USCXML_ISSUE_INFO)); continue; @@ -429,19 +489,24 @@ NEXT_TRANSITION: // check for valid initial attribute { - NodeSet<std::string> withInitialAttr; - withInitialAttr.push_back(allStates); + std::list<DOMElement*> withInitialAttr; + withInitialAttr.insert(withInitialAttr.end(), allStates.begin(), allStates.end()); withInitialAttr.push_back(_scxml); - for (size_t i = 0; i < withInitialAttr.size(); i++) { - Element<std::string> state = Element<std::string>(withInitialAttr[i]); + for (auto stateIter = withInitialAttr.begin(); stateIter != withInitialAttr.end(); stateIter++) { + DOMElement* state = *stateIter; if (HAS_ATTR(state, "initial")) { - NodeSet<std::string> childs; - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "state", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "parallel", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "final", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "history", state, true)); + std::list<DOMElement*> childs; + std::list<DOMElement*> tmp; + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "state", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "parallel", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "final", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "history", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); std::list<std::string> intials = tokenize(ATTR(state, "initial")); for (std::list<std::string>::iterator initIter = intials.begin(); initIter != intials.end(); initIter++) { @@ -450,7 +515,7 @@ NEXT_TRANSITION: continue; } // value of the 'initial' attribute [..] must be descendants of the containing <state> or <parallel> element - if (!InterpreterImpl::isMember(seenStates[*initIter], childs)) { + if (!DOMUtils::isMember(seenStates[*initIter], childs)) { issues.push_back(InterpreterIssue("Initial attribute references non-child state '" + *initIter + "'", state, InterpreterIssue::USCXML_ISSUE_FATAL)); } } @@ -460,37 +525,37 @@ NEXT_TRANSITION: // check for legal configuration of target sets { - std::map<Element<std::string>, std::string > targetIdSets; - for (size_t i = 0; i < transitions.size(); i++) { - Element<std::string> transition = Element<std::string>(transitions[i]); + std::map<DOMElement*, std::string > targetIdSets; + for (auto iter = transitions.begin(); iter != transitions.end(); iter++) { + DOMElement* transition = *iter; if (HAS_ATTR(transition, "target")) { targetIdSets[transition] = ATTR(transition, "target"); } } - for (size_t i = 0; i < initials.size(); i++) { - Element<std::string> initial = Element<std::string>(initials[i]); + for (auto iter = initials.begin(); iter != initials.end(); iter++) { + DOMElement* initial = *iter; if (HAS_ATTR(initial, "target")) { targetIdSets[initial] = ATTR(initial, "target"); } } - for (size_t i = 0; i < allStates.size(); i++) { - Element<std::string> state = Element<std::string>(allStates[i]); + for (auto iter = allStates.begin(); iter != allStates.end(); iter++) { + DOMElement* state = *iter; if (HAS_ATTR(state, "initial")) { targetIdSets[state] = ATTR(state, "initial"); } } - for (std::map<Element<std::string>, std::string >::iterator setIter = targetIdSets.begin(); + for (auto setIter = targetIdSets.begin(); setIter != targetIdSets.end(); setIter++) { - NodeSet<std::string> targets; + std::list<DOMElement*> targets; std::list<std::string> targetIds = tokenize(setIter->second); - for (std::list<std::string>::iterator tgtIter = targetIds.begin(); tgtIter != targetIds.end(); tgtIter++) { + for (auto tgtIter = targetIds.begin(); tgtIter != targetIds.end(); tgtIter++) { if (seenStates.find(*tgtIter) == seenStates.end()) goto NEXT_SET; targets.push_back(seenStates[*tgtIter]); @@ -505,21 +570,21 @@ NEXT_SET: // check for valid initial transition { - NodeSet<std::string> initTrans; -// initTrans.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", histories, true)); + std::list<DOMElement*> initTrans; + + for (auto iter = initials.begin(); iter != initials.end(); iter++) { + DOMElement* initial = *iter; - for (size_t i = 0; i < initials.size(); i++) { - Element<std::string> initial = Element<std::string>(initials[i]); - NodeSet<std::string> initTransitions = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial, true); + std::list<DOMElement*> initTransitions = DOMUtils::filterChildElements(XML_PREFIX(initial).str() + "transition", initial, true); if (initTransitions.size() != 1) { issues.push_back(InterpreterIssue("Initial element must define exactly one transition", initial, InterpreterIssue::USCXML_ISSUE_FATAL)); } - initTrans.push_back(initTransitions); + initTrans.insert(initTrans.end(), initTransitions.begin(), initTransitions.end()); } - for (size_t i = 0; i < initTrans.size(); i++) { - Element<std::string> transition = Element<std::string>(initTrans[i]); + for (auto iter = initTrans.begin(); iter != initTrans.end(); iter++) { + DOMElement* transition = *iter; /* In a conformant SCXML document, this transition must not contain 'cond' or 'event' attributes, and must specify a non-null 'target' * whose value is a valid state specification consisting solely of descendants of the containing state @@ -532,22 +597,29 @@ NEXT_SET: issues.push_back(InterpreterIssue("Initial transition cannot be eventful", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } - if (!transition.getParentNode() || !transition.getParentNode().getParentNode() || transition.getParentNode().getParentNode().getNodeType() != Node_base::ELEMENT_NODE) + if (!transition->getParentNode() || + !transition->getParentNode()->getParentNode() || + transition->getParentNode()->getParentNode()->getNodeType() != DOMNode::ELEMENT_NODE) continue; // syntax will catch this one - Element<std::string> state(transition.getParentNode().getParentNode()); - if (!InterpreterImpl::isState(state)) + DOMElement* state = static_cast<DOMElement*>(transition->getParentNode()->getParentNode()); + if (!isState(state)) continue; // syntax will catch this one - NodeSet<std::string> childs; - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "state", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "parallel", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "final", state, true)); - childs.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "history", state, true)); + std::list<DOMElement*> childs; + std::list<DOMElement*> tmp; + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "state", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "parallel", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "final", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); + tmp = DOMUtils::filterChildElements(XML_PREFIX(state).str() + "history", state, true); + childs.insert(childs.end(), tmp.begin(), tmp.end()); std::list<std::string> intials = tokenize(ATTR(transition, "target")); for (std::list<std::string>::iterator initIter = intials.begin(); initIter != intials.end(); initIter++) { // the 'target' of a <transition> inside an <initial> or <history> element: all the states must be descendants of the containing <state> or <parallel> element - if (!InterpreterImpl::isMember(seenStates[*initIter], childs)) { + if (!DOMUtils::isMember(seenStates[*initIter], childs)) { issues.push_back(InterpreterIssue("Target of initial transition references non-child state '" + *initIter + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); } } @@ -557,8 +629,8 @@ NEXT_SET: // check that all invokers exists { - for (size_t i = 0; i < invokes.size(); i++) { - Element<std::string> invoke = Element<std::string>(invokes[i]); + for (auto iter = invokes.begin(); iter != invokes.end(); iter++) { + DOMElement* invoke = *iter; if (HAS_ATTR(invoke, "type") && !_factory->hasInvoker(ATTR(invoke, "type"))) { // unknown at factory - adhoc extension? if (HAS_ATTR(invoke, "id") && interpreter->_invokers.find(ATTR(invoke, "id")) != interpreter->_invokers.end()) @@ -580,10 +652,10 @@ NEXT_SET: // check that all io processors exists { - for (size_t i = 0; i < sends.size(); i++) { - Element<std::string> send = Element<std::string>(sends[i]); + for (auto iter = sends.begin(); iter != sends.end(); iter++) { + DOMElement* send = *iter; if (HAS_ATTR(send, "type") && !_factory->hasIOProcessor(ATTR(send, "type"))) { - if (interpreter->_ioProcessors.find(ATTR(send, "type")) != interpreter->_ioProcessors.end()) + if (interpreter->_ioProcs.find(ATTR(send, "type")) != interpreter->_ioProcs.end()) continue; // not an issue, available ad-hoc issues.push_back(InterpreterIssue("Send to unknown IO Processor '" + ATTR(send, "type") + "'", send, InterpreterIssue::USCXML_ISSUE_FATAL)); @@ -594,23 +666,24 @@ NEXT_SET: // check that all custom executable content is known { - NodeSet<std::string> allExecContentContainers; - allExecContentContainers.push_back(onEntries); - allExecContentContainers.push_back(onExits); - allExecContentContainers.push_back(transitions); - allExecContentContainers.push_back(finalizes); - - for (size_t i = 0; i < allExecContentContainers.size(); i++) { - Element<std::string> block = Element<std::string>(allExecContentContainers[i]); - NodeSet<std::string> execContents = DOMUtils::filterChildType(Node_base::ELEMENT_NODE, block); - for (size_t j = 0; j < execContents.size(); j++) { - Element<std::string> execContent = Element<std::string>(execContents[j]); + std::list<DOMElement*> allExecContentContainers; + allExecContentContainers.insert(allExecContentContainers.end(), onEntries.begin(), onEntries.end()); + allExecContentContainers.insert(allExecContentContainers.end(), onExits.begin(), onExits.end()); + allExecContentContainers.insert(allExecContentContainers.end(), transitions.begin(), transitions.end()); + allExecContentContainers.insert(allExecContentContainers.end(), finalizes.begin(), finalizes.end()); + + for (auto bIter = allExecContentContainers.begin(); bIter != allExecContentContainers.end(); bIter++) { + DOMElement* block = *bIter; + std::list<DOMNode*> execContents = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, block); + for (auto ecIter = execContents.begin(); ecIter != execContents.end(); ecIter++) { + DOMElement* execContent = static_cast<DOMElement*>(*ecIter); // SCXML specific executable content, always available - if (InterpreterImpl::isMember(execContent, allExecContents)) { + if (DOMUtils::isMember(execContent, allExecContents)) { continue; } - if (!_factory->hasExecutableContent(execContent.getLocalName(), execContent.getNamespaceURI())) { - issues.push_back(InterpreterIssue("Executable content element '" + execContent.getLocalName() + "' in namespace '" + execContent.getNamespaceURI() + "' unknown", execContent, InterpreterIssue::USCXML_ISSUE_FATAL)); + + if (!_factory->hasExecutableContent(X(execContent->getLocalName()), X(execContent->getNamespaceURI()))) { + issues.push_back(InterpreterIssue("Executable content element '" + (std::string)X(execContent->getLocalName()) + "' in namespace '" + (std::string)X(execContent->getNamespaceURI()) + "' unknown", execContent, InterpreterIssue::USCXML_ISSUE_FATAL)); continue; } } @@ -619,8 +692,8 @@ NEXT_SET: // check that all SCXML elements have valid parents and required attributes { - for (size_t i = 0; i < allElements.size(); i++) { - Element<std::string> element = Element<std::string>(allElements[i]); + for (auto iter = allElements.begin(); iter != allElements.end(); iter++) { + DOMElement* element = *iter; std::string localName = LOCALNAME(element); if (reqAttr.find(localName) != reqAttr.end()) { @@ -638,12 +711,12 @@ NEXT_SET: if (localName == "scxml") // can be anywhere: <assign>, <content>, <other:embed> continue; - if (!element.getParentNode() || element.getParentNode().getNodeType() != Node_base::ELEMENT_NODE) { + if (!element->getParentNode() || element->getParentNode()->getNodeType() != DOMNode::ELEMENT_NODE) { issues.push_back(InterpreterIssue("Parent of " + localName + " is no element", element, InterpreterIssue::USCXML_ISSUE_WARNING)); continue; } - Element<std::string> parent = Element<std::string>(element.getParentNode()); + DOMElement* parent = static_cast<DOMElement*>(element->getParentNode()); std::string parentName = LOCALNAME(parent); if (validParents[localName].find(parentName) == validParents[localName].end()) { @@ -655,55 +728,55 @@ NEXT_SET: // check attribute constraints { - for (size_t i = 0; i < initials.size(); i++) { - Element<std::string> initial = Element<std::string>(initials[i]); - if (initial.getParentNode() && initial.getParentNode().getNodeType() == Node_base::ELEMENT_NODE) { - Element<std::string> state(initial.getParentNode()); + for (auto iter = initials.begin(); iter != initials.end(); iter++) { + DOMElement* initial = *iter; + if (initial->getParentNode() && initial->getParentNode()->getNodeType() == DOMNode::ELEMENT_NODE) { + DOMElement* state = static_cast<DOMElement*>(initial->getParentNode()); if (HAS_ATTR(state, "initial")) { issues.push_back(InterpreterIssue("State with initial attribute cannot have <initial> child ", state, InterpreterIssue::USCXML_ISSUE_WARNING)); } - if (InterpreterImpl::isAtomic(state)) { + if (isAtomic(state)) { issues.push_back(InterpreterIssue("Atomic state cannot have <initial> child ", state, InterpreterIssue::USCXML_ISSUE_WARNING)); } } } - for (size_t i = 0; i < allStates.size(); i++) { - Element<std::string> state = Element<std::string>(allStates[i]); - if (InterpreterImpl::isAtomic(state) && HAS_ATTR(state, "initial")) { + for (auto iter = allStates.begin(); iter != allStates.end(); iter++) { + DOMElement* state = *iter; + if (isAtomic(state) && HAS_ATTR(state, "initial")) { issues.push_back(InterpreterIssue("Atomic state cannot have initial attribute ", state, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < assigns.size(); i++) { - Element<std::string> assign = Element<std::string>(assigns[i]); - if (HAS_ATTR(assign, "expr") && assign.getChildNodes().getLength() > 0) { + for (auto iter = assigns.begin(); iter != assigns.end(); iter++) { + DOMElement* assign = *iter; + if (HAS_ATTR(assign, "expr") && assign->getChildNodes()->getLength() > 0) { issues.push_back(InterpreterIssue("Assign element cannot have expr attribute and children", assign, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < contents.size(); i++) { - Element<std::string> content = Element<std::string>(contents[i]); - if (HAS_ATTR(content, "expr") && content.getChildNodes().getLength() > 0) { + for (auto iter = contents.begin(); iter != contents.end(); iter++) { + DOMElement* content = *iter; + if (HAS_ATTR(content, "expr") && content->getChildNodes()->getLength() > 0) { issues.push_back(InterpreterIssue("Content element cannot have expr attribute and children", content, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < params.size(); i++) { - Element<std::string> param = Element<std::string>(params[i]); + for (auto iter = params.begin(); iter != params.end(); iter++) { + DOMElement* param = *iter; if (HAS_ATTR(param, "expr") && HAS_ATTR(param, "location")) { issues.push_back(InterpreterIssue("Param element cannot have both expr and location attribute", param, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < scripts.size(); i++) { - Element<std::string> script = Element<std::string>(scripts[i]); - if (HAS_ATTR(script, "src") && script.getChildNodes().getLength() > 0) { + for (auto iter = scripts.begin(); iter != scripts.end(); iter++) { + DOMElement* script = *iter; + if (HAS_ATTR(script, "src") && script->getChildNodes()->getLength() > 0) { issues.push_back(InterpreterIssue("Script element cannot have src attribute and children", script, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < sends.size(); i++) { - Element<std::string> send = Element<std::string>(sends[i]); + for (auto iter = sends.begin(); iter != sends.end(); iter++) { + DOMElement* send = *iter; if (HAS_ATTR(send, "event") && HAS_ATTR(send, "eventexpr")) { issues.push_back(InterpreterIssue("Send element cannot have both event and eventexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING)); } @@ -723,8 +796,8 @@ NEXT_SET: issues.push_back(InterpreterIssue("Send element cannot have delay with target _internal", send, InterpreterIssue::USCXML_ISSUE_WARNING)); } - NodeSet<std::string> contentChilds = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "content", send, false); - NodeSet<std::string> paramChilds = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "param", send, false); + std::list<DOMElement*> contentChilds = DOMUtils::filterChildElements(XML_PREFIX(send).str() + "content", send, false); + std::list<DOMElement*> paramChilds = DOMUtils::filterChildElements(XML_PREFIX(send).str() + "param", send, false); if (HAS_ATTR(send, "namelist") && contentChilds.size() > 0) { issues.push_back(InterpreterIssue("Send element cannot have namelist attribute and content child", send, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -735,15 +808,15 @@ NEXT_SET: } } - for (size_t i = 0; i < cancels.size(); i++) { - Element<std::string> cancel = Element<std::string>(cancels[i]); + for (auto iter = cancels.begin(); iter != cancels.end(); iter++) { + DOMElement* cancel = *iter; if (HAS_ATTR(cancel, "sendid") && HAS_ATTR(cancel, "sendidexpr")) { issues.push_back(InterpreterIssue("Cancel element cannot have both sendid and eventexpr sendidexpr", cancel, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < invokes.size(); i++) { - Element<std::string> invoke = Element<std::string>(invokes[i]); + for (auto iter = invokes.begin(); iter != invokes.end(); iter++) { + DOMElement* invoke = *iter; if (HAS_ATTR(invoke, "type") && HAS_ATTR(invoke, "typeexpr")) { issues.push_back(InterpreterIssue("Invoke element cannot have both type and typeexpr attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); } @@ -753,18 +826,18 @@ NEXT_SET: if (HAS_ATTR(invoke, "id") && HAS_ATTR(invoke, "idlocation")) { issues.push_back(InterpreterIssue("Invoke element cannot have both id and idlocation attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); } - if (HAS_ATTR(invoke, "namelist") && DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "param", invoke, false).size() > 0) { + if (HAS_ATTR(invoke, "namelist") && DOMUtils::filterChildElements(XML_PREFIX(invoke).str() + "param", invoke, false).size() > 0) { issues.push_back(InterpreterIssue("Invoke element cannot have namelist attribute and param child", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); } - if (HAS_ATTR(invoke, "src") && DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "content", invoke, false).size() > 0) { + if (HAS_ATTR(invoke, "src") && DOMUtils::filterChildElements(XML_PREFIX(invoke).str() + "content", invoke, false).size() > 0) { issues.push_back(InterpreterIssue("Invoke element cannot have src attribute and content child", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); } } - for (size_t i = 0; i < doneDatas.size(); i++) { - Element<std::string> donedata = Element<std::string>(doneDatas[i]); - if (DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "content", donedata, false).size() > 0 && - DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "param", donedata, false).size() > 0) { + for (auto iter = doneDatas.begin(); iter != doneDatas.end(); iter++) { + DOMElement* donedata = *iter; + if (DOMUtils::filterChildElements(XML_PREFIX(donedata).str() + "content", donedata, false).size() > 0 && + DOMUtils::filterChildElements(XML_PREFIX(donedata).str() + "param", donedata, false).size() > 0) { issues.push_back(InterpreterIssue("Donedata element cannot have param child and content child", donedata, InterpreterIssue::USCXML_ISSUE_WARNING)); } @@ -798,15 +871,15 @@ NEXT_SET: // test all scripts for valid syntax { - for (size_t i = 0; i < scripts.size(); i++) { - Element<std::string> script = Element<std::string>(scripts[i]); + for (auto iter = scripts.begin(); iter != scripts.end(); iter++) { + DOMElement* script = *iter; - if (script.hasChildNodes()) { + if (script->hasChildNodes()) { // search for the text node with the actual script std::string scriptContent; - for (Node<std::string> child = script.getFirstChild(); child; child = child.getNextSibling()) { - if (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE) - scriptContent += child.getNodeValue(); + for (DOMNode* child = script->getFirstChild(); child; child = child->getNextSibling()) { + if (child->getNodeType() == DOMNode::TEXT_NODE || child->getNodeType() == DOMNode::CDATA_SECTION_NODE) + scriptContent += (std::string)X(child->getNodeValue()); } if (!_dataModel.isValidSyntax(scriptContent)) { @@ -818,13 +891,13 @@ NEXT_SET: // test the various attributes with datamodel expressions for valid syntax { - NodeSet<std::string> withCondAttrs; - withCondAttrs.push_back(transitions); - withCondAttrs.push_back(ifs); - withCondAttrs.push_back(elseIfs); + std::list<DOMElement*> withCondAttrs; + withCondAttrs.insert(withCondAttrs.end(), transitions.begin(), transitions.end()); + withCondAttrs.insert(withCondAttrs.end(), ifs.begin(), ifs.end()); + withCondAttrs.insert(withCondAttrs.end(), elseIfs.begin(), elseIfs.end()); - for (size_t i = 0; i < withCondAttrs.size(); i++) { - Element<std::string> condAttr = Element<std::string>(withCondAttrs[i]); + for (auto iter = withCondAttrs.begin(); iter != withCondAttrs.end(); iter++) { + DOMElement* condAttr = *iter; if (HAS_ATTR(condAttr, "cond")) { if (!_dataModel.isValidSyntax(ATTR(condAttr, "cond"))) { issues.push_back(InterpreterIssue("Syntax error in cond attribute", condAttr, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -835,17 +908,17 @@ NEXT_SET: } { - NodeSet<std::string> withExprAttrs; - withExprAttrs.push_back(logs); - withExprAttrs.push_back(datas); - withExprAttrs.push_back(assigns); - withExprAttrs.push_back(contents); - withExprAttrs.push_back(params); - - for (size_t i = 0; i < withExprAttrs.size(); i++) { - Element<std::string> withExprAttr = Element<std::string>(withExprAttrs[i]); + std::list<DOMElement*> withExprAttrs; + withExprAttrs.insert(withExprAttrs.end(), logs.begin(), logs.end()); + withExprAttrs.insert(withExprAttrs.end(), datas.begin(), datas.end()); + withExprAttrs.insert(withExprAttrs.end(), assigns.begin(), assigns.end()); + withExprAttrs.insert(withExprAttrs.end(), contents.begin(), contents.end()); + withExprAttrs.insert(withExprAttrs.end(), params.begin(), params.end()); + + for (auto iter = withExprAttrs.begin(); iter != withExprAttrs.end(); iter++) { + DOMElement* withExprAttr = *iter; if (HAS_ATTR(withExprAttr, "expr")) { - if (InterpreterImpl::isMember(withExprAttr, datas) || InterpreterImpl::isMember(withExprAttr, assigns)) { + if (DOMUtils::isMember(withExprAttr, datas) || DOMUtils::isMember(withExprAttr, assigns)) { if (!_dataModel.isValidSyntax("foo = " + ATTR(withExprAttr, "expr"))) { // TODO: this is ECMAScripty! issues.push_back(InterpreterIssue("Syntax error in expr attribute", withExprAttr, InterpreterIssue::USCXML_ISSUE_WARNING)); continue; @@ -861,8 +934,8 @@ NEXT_SET: } { - for (size_t i = 0; i < foreachs.size(); i++) { - Element<std::string> foreach = Element<std::string>(foreachs[i]); + for (auto iter = foreachs.begin(); iter != foreachs.end(); iter++) { + DOMElement* foreach = *iter; if (HAS_ATTR(foreach, "array")) { if (!_dataModel.isValidSyntax(ATTR(foreach, "array"))) { issues.push_back(InterpreterIssue("Syntax error in array attribute", foreach, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -882,8 +955,8 @@ NEXT_SET: } { - for (size_t i = 0; i < sends.size(); i++) { - Element<std::string> send = Element<std::string>(sends[i]); + for (auto iter = sends.begin(); iter != sends.end(); iter++) { + DOMElement* send = *iter; if (HAS_ATTR(send, "eventexpr")) { if (!_dataModel.isValidSyntax(ATTR(send, "eventexpr"))) { issues.push_back(InterpreterIssue("Syntax error in eventexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -914,8 +987,8 @@ NEXT_SET: } { - for (size_t i = 0; i < invokes.size(); i++) { - Element<std::string> invoke = Element<std::string>(invokes[i]); + for (auto iter = invokes.begin(); iter != invokes.end(); iter++) { + DOMElement* invoke = *iter; if (HAS_ATTR(invoke, "typeexpr")) { if (!_dataModel.isValidSyntax(ATTR(invoke, "typeexpr"))) { issues.push_back(InterpreterIssue("Syntax error in typeexpr attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -938,8 +1011,8 @@ NEXT_SET: } { - for (size_t i = 0; i < cancels.size(); i++) { - Element<std::string> cancel = Element<std::string>(cancels[i]); + for (auto iter = cancels.begin(); iter != cancels.end(); iter++) { + DOMElement* cancel = *iter; if (HAS_ATTR(cancel, "sendidexpr")) { if (!_dataModel.isValidSyntax(ATTR(cancel, "sendidexpr"))) { issues.push_back(InterpreterIssue("Syntax error in sendidexpr attribute", cancel, InterpreterIssue::USCXML_ISSUE_WARNING)); @@ -955,5 +1028,29 @@ NEXT_SET: return issues; } +std::ostream& operator<< (std::ostream& os, const InterpreterIssue& issue) { + switch (issue.severity) { + case InterpreterIssue::USCXML_ISSUE_FATAL: + os << "Issue (FATAL) "; + break; + case InterpreterIssue::USCXML_ISSUE_WARNING: + os << "Issue (WARNING) "; + break; + case InterpreterIssue::USCXML_ISSUE_INFO: + os << "Issue (INFO) "; + break; + default: + break; + } + + if (issue.xPath.size() > 0) { + os << "at " << issue.xPath << ": "; + } else { + os << ": "; + } + os << issue.message; + return os; +} + }
\ No newline at end of file |