コード例 #1
0
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++) {
		Node<std::string> t = enabledTransitions[i];
		if (!isTargetless(t)) {
			for (unsigned int j = 0; j < filteredTransitions.size(); j++) {
				if (j == i)
					continue;
				Node<std::string> t2 = filteredTransitions[j];
				if (isPreemptingTransition(t2, t)) {
#if 0
					std::cout << "#####" << std::endl << "Transition " << std::endl
					          << t2 << std::endl << " preempts " << std::endl << t << std::endl << "#####" << std::endl;
#endif
					goto LOOP;
				}
			}
		}
#if 0
		std::cout << "----" << "Enabling Transition " << std::endl << t << std::endl;
#endif

		filteredTransitions.push_back(t);
LOOP:
		;
	}
	return filteredTransitions;
}
コード例 #2
0
void InterpreterDraft6::microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
#if VERBOSE
	std::cout << "Transitions: ";
	for (int i = 0; i < enabledTransitions.size(); i++) {
		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 << "    " << ((Element<std::string>)targetSet[j]).getAttribute("id") << std::endl;
		}
	}
	std::cout << std::endl;
#endif

	// --- MONITOR: beforeMicroStep ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->beforeMicroStep(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(beforeMicroStep)
	}

	exitStates(enabledTransitions);

	monIter_t monIter;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		Element<std::string> transition(enabledTransitions[i]);

		// --- MONITOR: beforeTakingTransitions ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeTakingTransitions)
		}

		executeContent(transition);

		// --- MONITOR: afterTakingTransitions ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->afterTakingTransition(shared_from_this(), transition, (i + 1 < enabledTransitions.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(afterTakingTransitions)
		}
	}

	enterStates(enabledTransitions);

	// --- MONITOR: afterMicroStep ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->afterMicroStep(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(afterMicroStep)
	}

}
コード例 #3
0
// setup / fetch the documents initial transitions
NodeSet<std::string> InterpreterDraft6::getDocumentInitialTransitions() {
	NodeSet<std::string> initialTransitions;
	
	if (_userDefinedStartConfiguration.size() > 0) {
		// we emulate entering a given configuration by creating a pseudo deep history
		Element<std::string> initHistory = _document.createElementNS(_nsInfo.nsURL, "history");
		_nsInfo.setPrefix(initHistory);
		
		initHistory.setAttribute("id", UUID::getUUID());
		initHistory.setAttribute("type", "deep");
		_scxml.insertBefore(initHistory, _scxml.getFirstChild());
		
		std::string histId = ATTR(initHistory, "id");
		NodeSet<std::string> histStates;
		for (int i = 0; i < _userDefinedStartConfiguration.size(); i++) {
			histStates.push_back(getState(_userDefinedStartConfiguration[i]));
		}
		_historyValue[histId] = histStates;
		
		Element<std::string> initialElem = _document.createElementNS(_nsInfo.nsURL, "initial");
		_nsInfo.setPrefix(initialElem);
		
		initialElem.setAttribute("generated", "true");
		Element<std::string> transitionElem = _document.createElementNS(_nsInfo.nsURL, "transition");
		_nsInfo.setPrefix(transitionElem);
		
		transitionElem.setAttribute("target", histId);
		initialElem.appendChild(transitionElem);
		_scxml.appendChild(initialElem);
		initialTransitions.push_back(transitionElem);
		
	} else {
		// try to get initial transition from initial element
		initialTransitions = _xpath.evaluate("/" + _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", _scxml).asNodeSet();
		if (initialTransitions.size() == 0) {
			Arabica::XPath::NodeSet<std::string> initialStates;
			// fetch per draft
			initialStates = getInitialStates();
			assert(initialStates.size() > 0);
			for (int i = 0; i < initialStates.size(); i++) {
				Element<std::string> initialElem = _document.createElementNS(_nsInfo.nsURL, "initial");
				_nsInfo.setPrefix(initialElem);
				
				initialElem.setAttribute("generated", "true");
				Element<std::string> transitionElem = _document.createElementNS(_nsInfo.nsURL, "transition");
				_nsInfo.setPrefix(transitionElem);
				
				transitionElem.setAttribute("target", ATTR(initialStates[i], "id"));
				initialElem.appendChild(transitionElem);
				_scxml.appendChild(initialElem);
				initialTransitions.push_back(transitionElem);
			}
		}
	}
	return initialTransitions;
}
コード例 #4
0
 virtual void beforeEnteringStates(uscxml::Interpreter* interpreter, const Arabica::XPath::NodeSet<std::string>& statesToEnter) {
   std::cout << "Entering states: ";
   for (int i = 0; i < statesToEnter.size(); i++) {
     std::cout << ATTR(statesToEnter[i], "id") << ", ";
   }
   std::cout << std::endl;
 }
コード例 #5
0
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;
		for (int j = 0; j < states.size(); j++) {
			if (!isDescendant(states[j], ancestors[i]) && (states[j] != ancestors[i]))
				goto NEXT_ANCESTOR;
		}
		ancestor = ancestors[i];
		break;
NEXT_ANCESTOR:
		;
	}
	return ancestor;
}
コード例 #6
0
	void printConfig(const Arabica::XPath::NodeSet<std::string>& config) {
		std::string seperator;
		std::cerr << "Config: {";
		for (int i = 0; i < config.size(); i++) {
			std::cerr << seperator << ATTR_CAST(config[i], "id");
			seperator = ", ";
		}
		std::cerr << "}" << std::endl;
	}
コード例 #7
0
ファイル: test-w3c.cpp プロジェクト: bjqiwei/uscxml
	void beforeCompletion(uscxml::Interpreter interpreter) {
		Arabica::XPath::NodeSet<std::string> config = interpreter.getConfiguration();
		if (config.size() == 1 && boost::iequals(ATTR(config[0], "id"), "pass")) {
			std::cout << "TEST SUCCEEDED" << std::endl;
			exit(EXIT_SUCCESS);
		}
		std::cout << "TEST FAILED" << std::endl;
		exit(EXIT_FAILURE);
	}
コード例 #8
0
 virtual void beforeExitingStates(uscxml::Interpreter* interpreter, const Arabica::XPath::NodeSet<std::string>& statesToExit) {
   std::cout << "Configuration: ";
   for (int i = 0; i < interpreter->getConfiguration().size(); i++) {
     std::cout << ATTR(interpreter->getConfiguration()[i], "id") << ", ";
   }
   std::cout << std::endl;
   std::cout << "Exiting states: ";
   for (int i = 0; i < statesToExit.size(); i++) {
     std::cout << ATTR(statesToExit[i], "id") << ", ";
   }
   std::cout << std::endl;
 }
コード例 #9
0
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const std::string& event) {
	Arabica::XPath::NodeSet<std::string> enabledTransitions;

	NodeSet<std::string> states;
	for (unsigned int i = 0; i < _configuration.size(); i++) {
		if (isAtomic(_configuration[i]))
			states.push_back(_configuration[i]);
	}
	states.to_document_order();

#if 0
	std::cout << "Atomic states: " << std::endl;
	for (int i = 0; i < states.size(); i++) {
		std::cout << states[i] << std::endl << "----" << std::endl;
	}
	std::cout << std::endl;
#endif

	unsigned int index = 0;
	while(states.size() > index) {
		bool foundTransition = false;
		NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", states[index]);
		for (unsigned int k = 0; k < transitions.size(); k++) {
			if (isEnabledTransition(transitions[k], event)) {
				enabledTransitions.push_back(transitions[k]);
				foundTransition = true;
				goto LOOP;
			}
		}
		if (!foundTransition) {
			Node<std::string> parent = states[index].getParentNode();
			if (parent) {
				states.push_back(parent);
			}
		}
LOOP:
		index++;
	}

	enabledTransitions = filterPreempted(enabledTransitions);

#if 0
	std::cout << "Enabled transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << DOMUtils::xPathForNode(enabledTransitions[i]) << std::endl;
	}
	std::cout << std::endl;
#endif

	return enabledTransitions;
}
コード例 #10
0
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitions() {
	Arabica::XPath::NodeSet<std::string> enabledTransitions;

	NodeSet<std::string> states;
	for (unsigned int i = 0; i < _configuration.size(); i++) {
		if (isAtomic(_configuration[i]))
			states.push_back(_configuration[i]);
	}
	states.to_document_order();

#if 0
	std::cout << "Atomic States: ";
	for (int i = 0; i < atomicStates.size(); i++) {
		std::cout << ATTR(atomicStates[i], "id") << ", ";
	}
	std::cout << std::endl;
#endif

	unsigned int index = 0;
	while(states.size() > index) {
		bool foundTransition = false;
		NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", states[index]);
		for (unsigned int k = 0; k < transitions.size(); k++) {
			if (!HAS_ATTR(transitions[k], "event") && hasConditionMatch(transitions[k])) {
				enabledTransitions.push_back(transitions[k]);
				foundTransition = true;
				goto LOOP;
			}
		}
		if (!foundTransition) {
			Node<std::string> parent = states[index].getParentNode();
			if (parent) {
				states.push_back(parent);
			}
		}
LOOP:
		index++;
	}

#if 0
	std::cout << "Enabled eventless transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << enabledTransitions[i] << std::endl << "----" << std::endl;
	}
	std::cout << std::endl;
#endif

	enabledTransitions = filterPreempted(enabledTransitions);
	return enabledTransitions;
}
コード例 #11
0
void InterpreterDraft6::exitInterpreter() {
#if VERBOSE
	std::cout << "Exiting interpreter " << _name << std::endl;
#endif
	NodeSet<std::string> statesToExit = _configuration;
	statesToExit.forward(false);
	statesToExit.sort();

	for (int i = 0; i < statesToExit.size(); i++) {
		Arabica::XPath::NodeSet<std::string> onExitElems = filterChildElements(_nsInfo.xmlNSPrefix + "onexit", statesToExit[i]);
		for (int j = 0; j < onExitElems.size(); j++) {
			executeContent(onExitElems[j]);
		}
		Arabica::XPath::NodeSet<std::string> invokeElems = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]);
		// TODO: we ought to cancel all remaining invokers just to be sure with the persist extension
		for (int j = 0; j < invokeElems.size(); j++) {
			cancelInvoke(invokeElems[j]);
		}
		if (isFinal(statesToExit[i]) && parentIsScxmlState(statesToExit[i])) {
			returnDoneEvent(statesToExit[i]);
		}
	}
	_configuration = NodeSet<std::string>();
}
コード例 #12
0
  virtual std::string doEvaluate(const DOM::Node<std::string>& context, 
                                 const Arabica::XPath::ExecutionContext<std::string>& executionContext) const
  {
    DOM::Node<std::string> node;
    if(baseT::argCount() == 0)
      node = context;
    else
    {
      Arabica::XPath::NodeSet<std::string> ns = baseT::argAsNodeSet(0, context, executionContext);
      if(ns.size() == 0)
        return "";
      node = ns.top();
    } // if ...

    std::ostringstream os;
    os << node.underlying_impl();
    return os.str();
  } // doEvaluate
コード例 #13
0
ファイル: Debugger.cpp プロジェクト: juehv/uscxml
std::list<Breakpoint> getQualifiedTransBreakpoints(Interpreter interpreter, const Arabica::DOM::Element<std::string>& transition, Breakpoint breakpointTemplate) {
	std::list<Breakpoint> breakpoints;

	Arabica::DOM::Element<std::string> source(interpreter.getImpl()->getSourceState(transition));
	Arabica::XPath::NodeSet<std::string> targets = interpreter.getImpl()->getTargetStates(transition);

	for (size_t j = 0; j < targets.size(); j++) {
		Arabica::DOM::Element<std::string> target(targets[j]);

		Breakpoint bp = breakpointTemplate; // copy base as template
		bp.element = transition;
		bp.transSourceId = ATTR(source, "id");
		bp.transTargetId = ATTR(target, "id");
		bp.subject = Breakpoint::TRANSITION;

		breakpoints.push_back(bp);
	}

	return breakpoints;
}
コード例 #14
0
  virtual void onStableConfiguration(uscxml::Interpreter* interpreter) {
    Arabica::XPath::NodeSet<std::string> configuration = interpreter->getConfiguration();

    uscxml::Data reply;
    reply.compound["sessionToken"] = uscxml::Data(interpreter->getName());
    std::string seperator;
    for (size_t i = 0; i < configuration.size(); i++) {
      if (uscxml::Interpreter::isAtomic(configuration[i]))
        reply.compound["nextConfiguration"].array.push_back(uscxml::Data(ATTR(configuration[i], "id"), uscxml::Data::VERBATIM));
    }
    
    std::cout << "---- reply:" << std::endl;
    std::cout << reply << std::endl;
    
    std::stringstream replyString;
    replyString << reply;
    
    struct evbuffer *databuf = evbuffer_new();
    evbuffer_add(databuf, replyString.str().c_str(), replyString.str().length());
    evhttp_send_reply(_interpreters[interpreter->getName()].second, 200, "OK", databuf);
    evbuffer_free(databuf);

  }
コード例 #15
0
ファイル: ChartToTex.cpp プロジェクト: juehv/uscxml
void ChartToTex::writeTex(std::ostream& stream) {
	_keepInvalidTransitions = true;
	if (_start == NULL) {
		interpret();
	}

	bool wroteRowStart = false;
	std::string seperator;

	for (std::map<std::string, GlobalState*>::iterator stateIter = _globalConf.begin(); stateIter != _globalConf.end(); stateIter++) {
		assert(_indexToState.find(stateIter->second->index) == _indexToState.end());
		_indexToState[stateIter->second->index] = stateIter->second;
	}

	stream << "% " << _sourceURL.asString() << std::endl;

	stream << "%<*provideCommand>" << std::endl;
	stream << "\\providecommand{\\globalStateListCell}[2][c]{%" << std::endl;
	stream << "  \\begin{tabular}[#1]{@{}l@{}}#2\\end{tabular}}" << std::endl;
	stream << "%</provideCommand>" << std::endl;


	stream << std::endl;

//	stream << "\\begin{table}[H]" << std::endl;
//	stream << "\\centering" << std::endl;
//	stream << "\\begin{tabular}{r | l | L{12em} | l}" << std::endl;

	stream << "\\begin{longtable}{| r | l | l | l |}" << std::endl;

	for (std::map<unsigned long, GlobalState*>::iterator stateIter = _indexToState.begin(); stateIter != _indexToState.end(); stateIter++) {
		GlobalState* currState = stateIter->second;

		stream << "\\hline" << std::endl;

		if (!wroteRowStart) {
			stream << "%<*tableRows>" << std::endl;
			wroteRowStart = true;
		}

		stream << "%<*globalState" << currState->index << ">" << std::endl;

		// state index
		stream << "\\tikzmark{statename_" << currState->index << "}" << "$\\widetilde{s}(" << currState->index << ")$ & ";

		// members in active configuration
		FlatStateIdentifier flatId(currState->stateId);
		stream << "\\globalStateListCell[t]{";
		stream << "\\tikzmark{active_" << currState->index << "}";
		stream << "$\\widetilde{s}_a(" << currState->index << ")$: " << stateListToTex(flatId.getFlatActive(), flatId.getActive().size() == 0) << "\\\\";

		// already visited states
		stream << "\\tikzmark{visited_" << currState->index << "}";
		stream << "$\\widetilde{s}_d(" << currState->index << ")$: " << stateListToTex(flatId.getFlatVisited(), flatId.getVisited().size() == 0) << "\\\\";

		// history assignments
		stream << "\\tikzmark{history_" << currState->index << "}";
		stream << "$\\widetilde{s}_h(" << currState->index << ")$: " << stateListToTex(flatId.getFlatHistory(), flatId.getHistory().size() == 0) << "} & ";

		// all transitions
		std::set<std::string> origTransitions;
		for (std::list<GlobalTransition*>::iterator transIter = stateIter->second->sortedOutgoing.begin(); transIter != stateIter->second->sortedOutgoing.end(); transIter++) {
			GlobalTransition* currTrans = *transIter;
			Arabica::XPath::NodeSet<std::string> members = currTrans->getTransitions();
			for (size_t i = 0; i < members.size(); i++) {
				Element<std::string> transElem(members[i]);
				if (HAS_ATTR(transElem, "priority")) {
					origTransitions.insert(ATTR(transElem, "priority"));
				} else {
					origTransitions.insert("initial");
				}
			}
		}

		if (origTransitions.size() > 0) {
			stream << "$\\{ ";
			seperator = "";
			for (std::set<std::string>::reverse_iterator transIter = origTransitions.rbegin(); transIter != origTransitions.rend(); transIter++) {
				stream << seperator << "t_{" << *transIter << "}";
				seperator = ", ";
			}
			stream << " \\}$";
		} else {
			stream << "$\\emptyset$";
		}
		stream << "\\tikzmark{transitions_" << currState->index << "}";
		stream << "  & \\\\ \\hline" << std::endl;

		if (stateIter->second->sortedOutgoing.size() > 0) {
			stream << "$\\widetilde{\\mathcal{T}}(" << currState->index << ")$" << std::endl;

			size_t ecIndex = 0;
			for (std::list<GlobalTransition*>::iterator transIter = stateIter->second->sortedOutgoing.begin(); transIter != stateIter->second->sortedOutgoing.end(); transIter++, ecIndex++) {
				GlobalTransition* currTrans = *transIter;
				stream << "& ";
				stream << "\\tikzmark{trans_set" << currState->index << "_" << ecIndex << "}";

				if (!currTrans->isValid)
					stream << "\\sout{";

				Arabica::XPath::NodeSet<std::string> members = currTrans->getTransitions();
				if (members.size() > 0) {
					stream << "$\\{ ";
					seperator = "";
					for (size_t i = 0; i < members.size(); i++) {
						Element<std::string> transElem(members[i]);
						if (HAS_ATTR(transElem, "priority")) {
							stream << seperator << "t_{" << ATTR(transElem, "priority") << "}";
						} else {
							stream << seperator << "t_{initial}";
						}
						seperator = ", ";
					}
					stream << " \\}$";
				} else {
					stream << "$\\emptyset$";
				}
				//			stream << "& \\sout{$\\{ t_2, t_0 \\}$}, & \\emph{$Inv_4$: nested source states} \\\\" << std::endl;
				//			stream << "& $\\{ t_2 \\}$ &  & $\\widetilde{s}(2)$ \\\\" << std::endl;
				//			stream << "& $\\{ t_0 \\}$ &  & $\\widetilde{s}(4)$ \\\\" << std::endl;

				if (!currTrans->isValid) {
#if 1
					stream << " } & \\emph{";
					switch(currTrans->invalidReason) {
					case GlobalTransition::NO_COMMON_EVENT:
						stream << "$Inv_1$: ";
						break;
					case GlobalTransition::MIXES_EVENT_SPONTANEOUS:
						stream << "$Inv_2$: ";
						break;
					case GlobalTransition::SAME_SOURCE_STATE:
						stream << "$Inv_3$: ";
						break;
					case GlobalTransition::CHILD_ENABLED:
						stream << "$Inv_4$: ";
						break;
					case GlobalTransition::PREEMPTING_MEMBERS:
						stream << "$Inv_5$: ";
						break;
					case GlobalTransition::UNCONDITIONAL_MATCH:
						stream << "$Opt_1$: ";
						break;
					case GlobalTransition::UNCONDITIONAL_SUPERSET:
						stream << "$Opt_2$: ";
						break;
					}
					stream << currTrans->invalidMsg << "} ";
#endif
					stream << "\\tikzmark{exec_content" << currState->index << "_" << ecIndex << "}";
					stream << " & ";
				} else {
					stream << " & ";
					std::stringstream execContentSS;

					seperator = "";
					for (std::list<GlobalTransition::Action>::iterator actionIter = currTrans->actions.begin(); actionIter != currTrans->actions.end(); actionIter++) {
						Element<std::string> execContent;

						if (actionIter->onEntry)
							execContent = actionIter->onEntry;

						if (actionIter->raiseDone)
							execContent = actionIter->raiseDone;

						if (actionIter->onExit)
							execContent = actionIter->onExit;

						if (actionIter->transition)
							execContent = actionIter->transition;

						if (execContent) {
							if (HAS_ATTR(execContent, "line_start") && HAS_ATTR(execContent, "line_end")) {
								size_t lineStart = strTo<size_t>(ATTR(execContent, "line_start"));
								size_t lineEnd = strTo<size_t>(ATTR(execContent, "line_end"));
								lineStart++;
								lineEnd--;
								if (lineStart == lineEnd) {
									execContentSS << seperator << "l_{" << lineStart << "}";
								} else {
									execContentSS << seperator << "l_{" << lineStart << "-" << lineEnd << "}";
								}
							}
							seperator = ", ";
						}
					}

					if (execContentSS.str().size() > 0) {
						stream << "$\\mathcal{X} := (" << execContentSS.str() << ")$";
					} else {
						stream << "$\\emptyset$";
					}
					stream << "\\tikzmark{exec_content" << currState->index << "_" << ecIndex << "}";

					stream << " & $\\widetilde{s}(" << _globalConf[currTrans->destination]->index << ")$ ";
					stream << "\\tikzmark{target" << currState->index << "_" << ecIndex << "}";
				}

				stream << "\\\\" << std::endl;
			}
			if (stateIter->second->sortedOutgoing.size() == 0) {
				stream << " &  &  & \\\\" << std::endl;
			}

			stream << "\\hline" << std::endl;
		}
		stream << "%</globalState" << currState->index << ">" << std::endl;

	}
	if (wroteRowStart) {
		stream << "%</tableRows>" << std::endl;
	}

//	stream << "\\end{tabular}" << std::endl;
//	stream << "\\end{table}" << std::endl << std::endl;
	stream << "\\end{longtable}" << std::endl << std::endl;

}
コード例 #16
0
ファイル: RespondElement.cpp プロジェクト: sradomski/uscxml
void RespondElement::enterElement(const Arabica::DOM::Element<std::string>& node) {
	// try to get the request id
	if (!HAS_ATTR(node, "to")) {
		LOG(ERROR) << "Respond element requires to attribute";
		return;
	}
	if (HAS_ATTR(node, "to") && !_interpreter->getDataModel()) {
		LOG(ERROR) << "Respond element with to requires datamodel";
		return;
	}
	std::string requestId = _interpreter->getDataModel().evalAsString(ATTR(node, "to"));

	// try to get the request object
	InterpreterHTTPServlet* servlet = _interpreter->getHTTPServlet();
	tthread::lock_guard<tthread::recursive_mutex> lock(servlet->getMutex());

	if (servlet->getRequests().find(requestId) == servlet->getRequests().end()) {
		LOG(ERROR) << "No matching HTTP request for respond element";
		return;
	}

	assert(servlet->getRequests().find(requestId) != servlet->getRequests().end());
	HTTPServer::Request httpReq = servlet->getRequests()[requestId];
	assert(httpReq.evhttpReq != NULL);
	HTTPServer::Reply httpReply(httpReq);
	servlet->getRequests().erase(requestId);

	// get the status or default to 200
	std::string statusStr = (HAS_ATTR(node, "status") ? ATTR(node, "status") : "200");
	if (!isNumeric(statusStr.c_str(), 10)) {
		LOG(ERROR) << "Respond element with non-numeric status " << statusStr;
		return;
	}
	httpReply.status = strTo<int>(statusStr);;

	// extract the content
	Arabica::XPath::NodeSet<std::string> contents = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "content", node);
	if (contents.size() > 0) {
		Arabica::DOM::Element<std::string> contentElem = Arabica::DOM::Element<std::string>(contents[0]);
		if (HAS_ATTR(contentElem, "expr")) { // -- content is evaluated string from datamodel ------
			if (_interpreter->getDataModel()) {
				try {
					Data contentData = _interpreter->getDataModel().getStringAsData(ATTR(contentElem, "expr"));
					if (contentData.atom.length() > 0) {
						httpReply.content = contentData.atom;
						httpReply.headers["Content-Type"] = "text/plain";
					} else if (contentData.binary) {
						httpReply.content = std::string(contentData.binary.getData(), contentData.binary.getSize());
						httpReply.headers["Content-Type"] = contentData.binary.getMimeType();
					} else if (contentData.node) {
						std::stringstream ss;
						ss << contentData.node;
						httpReply.content = ss.str();;
						httpReply.headers["Content-Type"] = "application/xml";
					} else {
						httpReply.content = Data::toJSON(contentData);
						httpReply.headers["Content-Type"] = "application/json";
					}
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with expr in content child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
				return;
			}
		} else if (HAS_ATTR(contentElem, "file") || HAS_ATTR(contentElem, "fileexpr")) { // -- content is from file ------
			URL file;
			if (HAS_ATTR(contentElem, "fileexpr")) {
				if (_interpreter->getDataModel()) {
					try {
						file = "file://" + _interpreter->getDataModel().evalAsString(ATTR(contentElem, "fileexpr"));
					} catch (Event e) {
						LOG(ERROR) << "Syntax error with fileexpr in content child of Respond element:" << std::endl << e << std::endl;
						return;
					}
				}
			} else {
				file = "file://" + ATTR(contentElem, "fileexpr");
			}
			if (file) {
				httpReply.content = file.getInContent();
				size_t lastDot;
				if ((lastDot = file.path().find_last_of(".")) != std::string::npos) {
					std::string extension = file.path().substr(lastDot + 1);
					std::string mimeType = URL::getMimeType(extension);
					if (mimeType.length() > 0) {
						httpReply.headers["Content-Type"] = mimeType;
					}
				}
			}
		} else if (contents[0].hasChildNodes()) {  // -- content embedded as child nodes ------
			httpReply.content = contents[0].getFirstChild().getNodeValue();
		} else {
			LOG(ERROR) << "content element does not specify any content.";
			return;
		}
	}

	// process headers
	Arabica::XPath::NodeSet<std::string> headers = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "header", node);
	for (int i = 0; i < headers.size(); i++) {
		Arabica::DOM::Element<std::string> headerElem = Arabica::DOM::Element<std::string>(headers[i]);

		std::string name;
		if (HAS_ATTR(headerElem, "name")) {
			name = ATTR(headerElem, "name");
		} else if(HAS_ATTR(headerElem, "nameexpr")) {
			if (_interpreter->getDataModel()) {
				try {
					name = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "nameexpr"));
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with nameexpr in header child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "header element has nameexpr attribute but no datamodel is specified.";
				return;
			}
		} else {
			LOG(ERROR) << "header element has no name or nameexpr attribute.";
			return;
		}

		std::string value;
		if (HAS_ATTR(headerElem, "value")) {
			value = ATTR(headerElem, "value");
		} else if(HAS_ATTR(headerElem, "valueexpr")) {
			if (_interpreter->getDataModel()) {
				try {
					value = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "valueexpr"));
				} catch (Event e) {
					LOG(ERROR) << "Syntax error with valueexpr in header child of Respond element:" << std::endl << e << std::endl;
					return;
				}
			} else {
				LOG(ERROR) << "header element has valueexpr attribute but no datamodel is specified.";
				return;
			}
		} else {
			LOG(ERROR) << "header element has no value or valueexpr attribute.";
			return;
		}

		httpReply.headers[name] = value;
	}

	// send the reply
	HTTPServer::reply(httpReply);
	servlet->getRequests().erase(requestId);
}
コード例 #17
0
void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
	NodeSet<std::string> statesToEnter;
	NodeSet<std::string> statesForDefaultEntry;
	monIter_t monIter;

#if VERBOSE
	std::cout << _name << ": Enabled enter transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << "\t" << enabledTransitions[i] << std::endl;
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < enabledTransitions.size(); i++) {
		Element<std::string> transition = ((Element<std::string>)enabledTransitions[i]);
		if (!isTargetless(transition)) {
			std::string transitionType = (iequals(transition.getAttribute("type"), "internal") ? "internal" : "external");
			NodeSet<std::string> tStates = getTargetStates(transition);

#if VERBOSE
			std::cout << _name << ": Target States: ";
			for (int i = 0; i < tStates.size(); i++) {
				std::cout << ATTR(tStates[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			Node<std::string> ancestor;
			Node<std::string> source = getSourceState(transition);
#if VERBOSE
			std::cout << _name << ": Source States: " << ATTR(source, "id") << std::endl;
#endif
			assert(source);

			bool allDescendants = true;
			for (int j = 0; j < tStates.size(); j++) {
				if (!isDescendant(tStates[j], source)) {
					allDescendants = false;
					break;
				}
			}
			if (iequals(transitionType, "internal") &&
			        isCompound(source) &&
			        allDescendants) {
				ancestor = source;
			} else {
				NodeSet<std::string> tmpStates;
				tmpStates.push_back(source);
				tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end());

				ancestor = findLCCA(tmpStates);
			}

#if VERBOSE
			std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl;
#endif

			for (int j = 0; j < tStates.size(); j++) {
				addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry);
			}

#if VERBOSE
			std::cout << _name << ": States to enter: ";
			for (int i = 0; i < statesToEnter.size(); i++) {
				std::cout << LOCALNAME(statesToEnter[i]) << ":" << ATTR(statesToEnter[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			for (int j = 0; j < tStates.size(); j++) {
				NodeSet<std::string> ancestors = getProperAncestors(tStates[j], ancestor);

#if VERBOSE
				std::cout << _name << ": Proper Ancestors of " << ATTR(tStates[j], "id") << " and " << ATTR(ancestor, "id") << ": ";
				for (int i = 0; i < ancestors.size(); i++) {
					std::cout << ATTR(ancestors[i], "id") << ", ";
				}
				std::cout << std::endl;
#endif

				for (int k = 0; k < ancestors.size(); k++) {
					statesToEnter.push_back(ancestors[k]);
					if(isParallel(ancestors[k])) {
						NodeSet<std::string> childs = getChildStates(ancestors[k]);
						for (int l = 0; l < childs.size(); l++) {
							bool someIsDescendant = false;
							for (int m = 0; m < statesToEnter.size(); m++) {
								if (isDescendant(statesToEnter[m], childs[l])) {
									someIsDescendant = true;
									break;
								}
							}
							if (!someIsDescendant) {
								addStatesToEnter(childs[l], statesToEnter, statesForDefaultEntry);
							}
						}
					}
				}
			}
		}
	}
	statesToEnter.to_document_order();

#if VERBOSE
	std::cout << _name << ": States to enter: ";
	for (int i = 0; i < statesToEnter.size(); i++) {
		std::cout << ATTR(statesToEnter[i], "id") << ", ";
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < statesToEnter.size(); i++) {
		Element<std::string> stateElem = (Element<std::string>)statesToEnter[i];

		// extension for flattened interpreters
		for (unsigned int k = 0; k < statesToEnter.size(); k++) {
			NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToEnter[k]);
			for (unsigned int j = 0; j < invokes.size(); j++) {
				if (HAS_ATTR(invokes[j], "persist") && DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
					invoke(invokes[j]);
				}
			}
		}

		// --- MONITOR: beforeEnteringState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeEnteringState)
		}

		// extension for flattened SCXML documents, we will need an explicit uninvoke element
		NodeSet<std::string> uninvokes = filterChildElements(_nsInfo.xmlNSPrefix + "uninvoke", statesToEnter[i]);
		for (int j = 0; j < uninvokes.size(); j++) {
			Element<std::string> uninvokeElem = (Element<std::string>)uninvokes[j];
			cancelInvoke(uninvokeElem);
		}

		_configuration.push_back(stateElem);
		_statesToInvoke.push_back(stateElem);

//		if (_binding == LATE && stateElem.getAttribute("isFirstEntry").size() > 0) {
		if (_binding == LATE && !isMember(stateElem, _alreadyEntered)) {
			NodeSet<std::string> dataModelElems = filterChildElements(_nsInfo.xmlNSPrefix + "datamodel", stateElem);
			if(dataModelElems.size() > 0 && _dataModel) {
				Arabica::XPath::NodeSet<std::string> dataElems = filterChildElements(_nsInfo.xmlNSPrefix + "data", dataModelElems[0]);
				for (int j = 0; j < dataElems.size(); j++) {
					if (dataElems[j].getNodeType() == Node_base::ELEMENT_NODE)
						initializeData(Element<std::string>(dataElems[j]));
				}
			}
			_alreadyEntered.push_back(stateElem);
//			stateElem.setAttribute("isFirstEntry", "");
		}
		// execute onentry executable content
		NodeSet<std::string> onEntryElems = filterChildElements(_nsInfo.xmlNSPrefix + "onEntry", stateElem);
		executeContent(onEntryElems, false);

		// --- MONITOR: afterEnteringState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->afterEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(afterEnteringState)
		}

		if (isMember(stateElem, statesForDefaultEntry)) {
			// execute initial transition content for compound states
			Arabica::XPath::NodeSet<std::string> transitions = _xpath.evaluate("" + _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", stateElem).asNodeSet();
			for (int j = 0; j < transitions.size(); j++) {
				executeContent(transitions[j]);
			}
		}

		if (isFinal(stateElem)) {
			internalDoneSend(stateElem);
			Element<std::string> parent = (Element<std::string>)stateElem.getParentNode();

			if (isParallel(parent.getParentNode())) {
				Element<std::string> grandParent = (Element<std::string>)parent.getParentNode();

				Arabica::XPath::NodeSet<std::string> childs = getChildStates(grandParent);
				bool inFinalState = true;
				for (int j = 0; j < childs.size(); j++) {
					if (!isInFinalState(childs[j])) {
						inFinalState = false;
						break;
					}
				}
				if (inFinalState) {
					internalDoneSend(parent);
				}
			}
		}
	}
	for (int i = 0; i < _configuration.size(); i++) {
		Element<std::string> stateElem = (Element<std::string>)_configuration[i];
		if (isFinal(stateElem) && parentIsScxmlState(stateElem)) {
			_running = false;
			_done = true;
		}
	}
}
コード例 #18
0
void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) {
	NodeSet<std::string> statesToExit;
	monIter_t monIter;

#if VERBOSE
	std::cout << _name << ": Enabled exit transitions: " << std::endl;
	for (int i = 0; i < enabledTransitions.size(); i++) {
		std::cout << enabledTransitions[i] << std::endl;
	}
	std::cout << std::endl;
#endif

	for (int i = 0; i < enabledTransitions.size(); i++) {
		Element<std::string> t = ((Element<std::string>)enabledTransitions[i]);
		if (!isTargetless(t)) {
			Node<std::string> ancestor;
			Node<std::string> source = getSourceState(t);
//			std::cout << t << std::endl << TAGNAME(t) << std::endl;
			NodeSet<std::string> tStates = getTargetStates(t);
			bool isInternal = (HAS_ATTR(t, "type") && iequals(ATTR(t, "type"), "internal")); // external is default
			bool allDescendants = true;
			for (int j = 0; j < tStates.size(); j++) {
				if (!isDescendant(tStates[j], source)) {
					allDescendants = false;
					break;
				}
			}
			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 << _name << ": tmpStates: ";
				for (int i = 0; i < tmpStates.size(); i++) {
					std::cout << ATTR(tmpStates[i], "id") << ", ";
				}
				std::cout << std::endl;
#endif
				ancestor = findLCCA(tmpStates);
			}
#if VERBOSE
			std::cout << _name << ": 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]);
			}
		}
	}
	// remove statesToExit from _statesToInvoke
	std::list<Node<std::string> > tmp;
	for (int i = 0; i < _statesToInvoke.size(); i++) {
		if (!isMember(_statesToInvoke[i], statesToExit)) {
			tmp.push_back(_statesToInvoke[i]);
		}
	}
	_statesToInvoke = NodeSet<std::string>();
	_statesToInvoke.insert(_statesToInvoke.end(), tmp.begin(), tmp.end());

	statesToExit.forward(false);
	statesToExit.sort();

#if VERBOSE
	std::cout << _name << ": 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

	for (int i = 0; i < statesToExit.size(); i++) {
		NodeSet<std::string> histories = filterChildElements(_nsInfo.xmlNSPrefix + "history", statesToExit[i]);
		for (int j = 0; j < histories.size(); 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++) {
				if (iequals(historyType, "deep")) {
					if (isAtomic(_configuration[k]) && isDescendant(_configuration[k], statesToExit[i]))
						historyNodes.push_back(_configuration[k]);
				} else {
					if (_configuration[k].getParentNode() == statesToExit[i])
						historyNodes.push_back(_configuration[k]);
				}
			}
			_historyValue[historyElem.getAttribute("id")] = historyNodes;
#if VERBOSE
			std::cout << _name << ": History node " << ATTR(historyElem, "id") << " contains: ";
			for (int i = 0; i < historyNodes.size(); i++) {
				std::cout << ATTR(historyNodes[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

		}
	}

	for (int i = 0; i < statesToExit.size(); i++) {
		// --- MONITOR: beforeExitingState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeExitingState)
		}

		NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onExit", statesToExit[i]);
		for (int j = 0; j < onExits.size(); j++) {
			Element<std::string> onExitElem = (Element<std::string>)onExits[j];
			executeContent(onExitElem);
		}

		// --- MONITOR: afterExitingState ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->afterExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size()));
			}
			USCXML_MONITOR_CATCH_BLOCK(afterExitingState)
		}

		NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]);
		for (int j = 0; j < invokes.size(); j++) {
			Element<std::string> invokeElem = (Element<std::string>)invokes[j];
			if (HAS_ATTR(invokeElem, "persist") && DOMUtils::attributeIsTrue(ATTR(invokeElem, "persist"))) {
				// extension for flattened SCXML documents, we will need an explicit uninvoke element
			} else {
				cancelInvoke(invokeElem);
			}
		}

		// 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());
	}
}
コード例 #19
0
void InterpreterDraft6::addStatesToEnter(const Node<std::string>& state,
        Arabica::XPath::NodeSet<std::string>& statesToEnter,
        Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry) {
	std::string stateId = ((Element<std::string>)state).getAttribute("id");

#if VERBOSE
	std::cout << "Adding state to enter: " << stateId << std::endl;
#endif
	if (isHistory(state)) {
		if (_historyValue.find(stateId) != _historyValue.end()) {
			Arabica::XPath::NodeSet<std::string> historyValue = _historyValue[stateId];

#if VERBOSE
			std::cout << "History State " << ATTR(state, "id") << ": ";
			for (int i = 0; i < historyValue.size(); i++) {
				std::cout << ATTR(historyValue[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			for (int i = 0; i < historyValue.size(); i++) {
				addStatesToEnter(historyValue[i], statesToEnter, statesForDefaultEntry);
				NodeSet<std::string> ancestors = getProperAncestors(historyValue[i], state);

#if VERBOSE
				std::cout << "Proper Ancestors: ";
				for (int i = 0; i < ancestors.size(); i++) {
					std::cout << ATTR(ancestors[i], "id") << ", ";
				}
				std::cout << std::endl;
#endif

				for (int j = 0; j < ancestors.size(); j++) {
					statesToEnter.push_back(ancestors[j]);
				}
			}
		} else {
			NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", state);
			for (int i = 0; i < transitions.size(); i++) {
				NodeSet<std::string> targets = getTargetStates(transitions[i]);
				for (int j = 0; j < targets.size(); j++) {
					addStatesToEnter(targets[j], statesToEnter, statesForDefaultEntry);

					// Modifications from chris nuernberger
					NodeSet<std::string> ancestors = getProperAncestors(targets[j], state);
					for (int k = 0; k < ancestors.size(); k++) {
						statesToEnter.push_back(ancestors[k]);
					}
				}
			}
		}
	} else {
		statesToEnter.push_back(state);
		if (isCompound(state)) {
			statesForDefaultEntry.push_back(state);

			NodeSet<std::string> tStates = getInitialStates(state);
			for (int i = 0; i < tStates.size(); i++) {
				addStatesToEnter(tStates[i], statesToEnter, statesForDefaultEntry);
			}

			//			addStatesToEnter(getInitialState(state), statesToEnter, statesForDefaultEntry);
			//      NodeSet<std::string> tStates = getTargetStates(getInitialState(state));

		} else if(isParallel(state)) {
			NodeSet<std::string> childStates = getChildStates(state);
			for (int i = 0; i < childStates.size(); i++) {
				addStatesToEnter(childStates[i], statesToEnter, statesForDefaultEntry);
			}
		}
	}
}
コード例 #20
0
// a macrostep
InterpreterState InterpreterDraft6::step(bool blocking) {
	try {

		monIter_t monIter;
		NodeSet<std::string> enabledTransitions;
		
		// setup document and interpreter
		if (!_isInitialized)
			init();
		
		// if we failed return false
		if (!_isInitialized)
			return INIT_FAILED;
		
		// run initial transitions
		if (!_stable) {
			stabilize();
			// we might only need a single step
			if (!_running)
				goto EXIT_INTERPRETER;
			return INITIALIZED;
		}
		
		if (!_running)
			return FINISHED;
		
		// read an external event and react
		if (blocking) {
			// wait until an event becomes available
			while(_externalQueue.isEmpty()) {
				_condVar.wait(_mutex);
			}
		} else {
			// return immediately if external queue is empty
			if (_externalQueue.isEmpty())
				return NOTHING_TODO;
		}
		_currEvent = _externalQueue.pop();

	#if VERBOSE
		std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
		if (_running && _currEvent.name == "unblock.and.die") {
			std::cout << "Still running " << this << std::endl;
		} else {
			std::cout << "Aborting " << this << std::endl;
		}
	#endif
		_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external

		// when we were blocking on destructor invocation
		if (!_running) {
			goto EXIT_INTERPRETER;
			return INTERRUPTED;
		}
		// --- MONITOR: beforeProcessingEvent ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
		}
		
		if (iequals(_currEvent.name, "cancel.invoke." + _sessionId))
			return INTERRUPTED;
		
		try {
			_dataModel.setEvent(_currEvent);
		} catch (Event e) {
			LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
		}

		for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
				 invokeIter != _invokers.end();
				 invokeIter++) {
			if (iequals(invokeIter->first, _currEvent.invokeid)) {
				Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
				for (int k = 0; k < finalizes.size(); k++) {
					Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
					executeContent(finalizeElem);
				}
			}
			if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
				try {
					// do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
					// Yes do so, see test229!
					// if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
					invokeIter->second.send(_currEvent);
				} catch(...) {
					LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
				}
			}
		}

		
		// run internal processing until we reach a stable configuration again
		enabledTransitions = selectTransitions(_currEvent.name);
		if (!enabledTransitions.empty()) {
			// test 403b
			enabledTransitions.to_document_order();
			microstep(enabledTransitions);
		}

		stabilize();
		return PROCESSED;
		
	EXIT_INTERPRETER:
		if (!_running) {
			// --- MONITOR: beforeCompletion ------------------------------
			for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
				try {
					(*monIter)->beforeCompletion(shared_from_this());
				}
				USCXML_MONITOR_CATCH_BLOCK(beforeCompletion)
			}
			
			exitInterpreter();
			if (_sendQueue) {
				std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
				while(sendIter != _sendIds.end()) {
					_sendQueue->cancelEvent(sendIter->first);
					sendIter++;
				}
			}
			
			// --- MONITOR: afterCompletion ------------------------------
			for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
				try {
					(*monIter)->afterCompletion(shared_from_this());
				}
				USCXML_MONITOR_CATCH_BLOCK(afterCompletion)
			}
			return FINISHED;
		}
		
		assert(hasLegalConfiguration());
		_mutex.unlock();

		// remove datamodel
		if(_dataModel)
			_dataModel = DataModel();

		return PROCESSED;
		
	} catch (boost::bad_weak_ptr e) {
		LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl;
		return INTERRUPTED;
	}
	
	// set datamodel to null from this thread
	if(_dataModel)
		_dataModel = DataModel();

}
コード例 #21
0
void InterpreterDraft6::mainEventLoop() {
	monIter_t monIter;

	while(_running) {
		NodeSet<std::string> enabledTransitions;
		_stable = false;

		// Here we handle eventless transitions and transitions
		// triggered by internal events until machine is stable
		while(_running && !_stable) {
#if VERBOSE
			std::cout << "Configuration: ";
			for (int i = 0; i < _configuration.size(); i++) {
				std::cout << ATTR(_configuration[i], "id") << ", ";
			}
			std::cout << std::endl;
#endif

			enabledTransitions = selectEventlessTransitions();
			if (enabledTransitions.size() == 0) {
				if (_internalQueue.size() == 0) {
					_stable = true;
				} else {
					_currEvent = _internalQueue.front();
					_internalQueue.pop_front();
#if VERBOSE
					std::cout << "Received internal event " << _currEvent.name << std::endl;
#endif

					// --- MONITOR: beforeProcessingEvent ------------------------------
					for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
						try {
							(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
						}
						USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
					}

					if (_dataModel)
						_dataModel.setEvent(_currEvent);
					enabledTransitions = selectTransitions(_currEvent.name);
				}
			}
			if (!enabledTransitions.empty()) {
				// test 403b
				enabledTransitions.to_document_order();
				microstep(enabledTransitions);
			}
		}

		for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
			NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]);
			for (unsigned int j = 0; j < invokes.size(); j++) {
				if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
					invoke(invokes[j]);
				}
			}
		}
		_statesToInvoke = NodeSet<std::string>();

		if (!_internalQueue.empty())
			continue;

		// assume that we have a legal configuration as soon as the internal queue is empty
		assert(hasLegalConfiguration());

		monIter = _monitors.begin();

		// --- MONITOR: onStableConfiguration ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->onStableConfiguration(shared_from_this());
			}
			USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration)
		}

		_mutex.unlock();
		
		// whenever we have a stable configuration, run the mainThread hooks with 200fps
		while(_externalQueue.isEmpty() && _thread == NULL) {
			runOnMainThread(200);
		}
		_mutex.lock();

		while(_externalQueue.isEmpty()) {
			_condVar.wait(_mutex);
		}
		_currEvent = _externalQueue.pop();
#if VERBOSE
		std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
		if (_running && _currEvent.name == "unblock.and.die") {
			std::cout << "Still running " << this << std::endl;
		} else {
			std::cout << "Aborting " << this << std::endl;
		}
#endif
		_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
		if (!_running)
			goto EXIT_INTERPRETER;

		// --- MONITOR: beforeProcessingEvent ------------------------------
		for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
			try {
				(*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent);
			}
			USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent)
		}

		if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId))
			break;

		if (_dataModel) {
			try {
				_dataModel.setEvent(_currEvent);
			} catch (Event e) {
				LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
			}
		}
		for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
		        invokeIter != _invokers.end();
		        invokeIter++) {
			if (iequals(invokeIter->first, _currEvent.invokeid)) {
				Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
				for (int k = 0; k < finalizes.size(); k++) {
					Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
					executeContent(finalizeElem);
				}
			}
			if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
				try {
					// do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
					// Yes do so, see test229!
					// if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
					invokeIter->second.send(_currEvent);
				} catch(...) {
					LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
				}
			}
		}
		enabledTransitions = selectTransitions(_currEvent.name);
		if (!enabledTransitions.empty()) {
			// test 403b
			enabledTransitions.to_document_order();
			microstep(enabledTransitions);
		}
	}

EXIT_INTERPRETER:
	// --- MONITOR: beforeCompletion ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->beforeCompletion(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(beforeCompletion)
	}

	exitInterpreter();
	if (_sendQueue) {
		std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
		while(sendIter != _sendIds.end()) {
			_sendQueue->cancelEvent(sendIter->first);
			sendIter++;
		}
	}

	// --- MONITOR: afterCompletion ------------------------------
	for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) {
		try {
			(*monIter)->afterCompletion(shared_from_this());
		}
		USCXML_MONITOR_CATCH_BLOCK(afterCompletion)
	}

}