diff options
Diffstat (limited to 'src/uscxml/Interpreter.h')
-rw-r--r-- | src/uscxml/Interpreter.h | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h new file mode 100644 index 0000000..fb913d1 --- /dev/null +++ b/src/uscxml/Interpreter.h @@ -0,0 +1,314 @@ +#ifndef RUNTIME_H_SQ1MBKGN +#define RUNTIME_H_SQ1MBKGN + +#include <boost/uuid/uuid_generators.hpp> +#include <boost/algorithm/string.hpp> + +#include <iostream> +#include <set> +#include <map> + +#include <XPath/XPath.hpp> +#include <DOM/Document.hpp> + +#include <DOM/SAX2DOM/SAX2DOM.hpp> +#include <SAX/helpers/CatchErrorHandler.hpp> + +#include "uscxml/concurrency/tinythread.h" +#include "uscxml/concurrency/BlockingQueue.h" +#include "uscxml/Message.h" +#include "uscxml/Factory.h" + +namespace uscxml { + + class Interpreter { + public: + enum Binding { + EARLY = 0, + LATE = 1 + }; + + Interpreter(const std::string& url); + virtual ~Interpreter(); + + void start(); + void stop(); + static void run(void*); + + void interpret(); + bool validate(); + + void waitForStabilization(); + + void receive(Event& event) { _externalQueue.push(event); } + void receiveInternal(Event& event) { _internalQueue.push_back(event); } + Arabica::XPath::NodeSet<std::string> getConfiguration() { return _configuration; } + Arabica::DOM::Node<std::string> getState(const std::string& stateId); + + const std::string& getName() { return _name; } + const std::string& getSessionId() { return _sessionId; } + + static bool isMember(const Arabica::DOM::Node<std::string>& node, const Arabica::XPath::NodeSet<std::string>& set); + + void dump(); + static void dump(const Arabica::DOM::Node<std::string>& node, int lvl = 0); + + protected: + void normalize(const Arabica::DOM::Node<std::string>& node); + void setupIOProcessors(); + + void mainEventLoop(); + + bool _stable; + tthread::thread* _thread; + tthread::mutex _mutex; + tthread::condition_variable _stabilized; + + std::string _url; + Arabica::DOM::Document<std::string> _doc; + Arabica::DOM::Element<std::string> _scxml; + Arabica::XPath::XPath<std::string> _xpath; + Arabica::XPath::StandardNamespaceContext<std::string> _nsContext; + std::string _nsPrefix; + + bool _running; + Binding _binding; + Arabica::XPath::NodeSet<std::string> _configuration; + Arabica::XPath::NodeSet<std::string> _statesToInvoke; + + DataModel* _dataModel; + std::map<std::string, Arabica::XPath::NodeSet<std::string> > _historyValue; + + std::list<Event > _internalQueue; + uscxml::concurrency::BlockingQueue<Event> _externalQueue; + + void microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); + void exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); + void enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); + void executeTransitionContent(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); + void executeContent(const Arabica::DOM::Node<std::string>& content); + void executeContent(const Arabica::DOM::NodeList<std::string>& content); + void initializeData(const Arabica::DOM::Node<std::string>& data); + void exitInterpreter(); + + void addStatesToEnter(const Arabica::DOM::Node<std::string>& state, + Arabica::XPath::NodeSet<std::string>& statesToEnter, + Arabica::XPath::NodeSet<std::string>& statesForDefaultEntry); + + Arabica::XPath::NodeSet<std::string> selectEventlessTransitions(); + Arabica::XPath::NodeSet<std::string> selectTransitions(const std::string& event); + Arabica::XPath::NodeSet<std::string> getTargetStates(const Arabica::DOM::Node<std::string>& transition); + Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state); + Arabica::DOM::Node<std::string> getInitialState(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()); + Arabica::DOM::Node<std::string> getSourceState(const Arabica::DOM::Node<std::string>& transition); + Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states); + static Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2); + + + void send(const std::string invokeId, Event& event); + void send(const Arabica::DOM::Node<std::string>& element); + void invoke(const Arabica::DOM::Node<std::string>& element); + void cancelInvoke(const Arabica::DOM::Node<std::string>& content); + void returnDoneEvent(const Arabica::DOM::Node<std::string>& state); + + static bool nameMatch(const std::string& transitionEvent, const std::string& event); + Arabica::XPath::NodeSet<std::string> filterPreempted(const Arabica::XPath::NodeSet<std::string>& enabledTransitions); + bool hasConditionMatch(const Arabica::DOM::Node<std::string>& conditional); + bool isPreemptingTransition(const Arabica::DOM::Node<std::string>& t1, const Arabica::DOM::Node<std::string>& t2); + bool isInFinalState(const Arabica::DOM::Node<std::string>& state); + bool isWithinSameChild(const Arabica::DOM::Node<std::string>& transition); + bool parentIsScxmlState(Arabica::DOM::Node<std::string> state); + + static bool isState(const Arabica::DOM::Node<std::string>& state); + static bool isPseudoState(const Arabica::DOM::Node<std::string>& state); + static bool isTransitionTarget(const Arabica::DOM::Node<std::string>& elem); + static bool isTargetless(const Arabica::DOM::Node<std::string>& transition); + static bool isAtomic(const Arabica::DOM::Node<std::string>& state); + static bool isFinal(const Arabica::DOM::Node<std::string>& state); + static bool isHistory(const Arabica::DOM::Node<std::string>& state); + static bool isParallel(const Arabica::DOM::Node<std::string>& state); + static bool isCompound(const Arabica::DOM::Node<std::string>& state); + static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2); + + static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs); + + static boost::uuids::random_generator uuidGen; + static const std::string getUUID(); + + std::string _name; + std::string _sessionId; + + IOProcessor* getIOProcessor(const std::string& type); + IOProcessor* getIOProcessorForId(const std::string& sendId); + + std::map<std::string, IOProcessor*> _ioProcessorsIds; + std::map<std::string, IOProcessor*> _ioProcessors; + + }; + +#if 0 + class SCXMLParseHandler : + public Arabica::SAX::EntityResolver<std::string>, + public Arabica::SAX::DTDHandler<std::string>, + public Arabica::SAX::ContentHandler<std::string>, + public Arabica::SAX::CatchErrorHandler<std::string>, + public Arabica::SAX::LexicalHandler<std::string>, + public Arabica::SAX::DeclHandler<std::string> + { + public: + SCXMLParseHandler() { } + virtual ~SCXMLParseHandler() { } + + // EntityResolver + virtual InputSourceT resolveEntity(const std::string& publicId , const std::string& systemId) { + return InputSourceT(); + } + + // DTDHandler + virtual void notationDecl(const std::string& name, + const std::string& publicId, + const std::string& systemId) { + std::cout << "notationDecl" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " publicId:" << publicId << std::endl; + std::cout << " systemId:" << systemId << std::endl; + } + virtual void unparsedEntityDecl(const std::string& name, + const std::string& publicId, + const std::string& systemId, + const std::string& notationName) { + std::cout << "unparsedEntityDecl" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " publicId:" << publicId << std::endl; + std::cout << " systemId:" << systemId << std::endl; + std::cout << " notationName:" << notationName << std::endl; + } + + // ContentHandler + virtual void setDocumentLocator(const LocatorT& locator) { + std::cout << "setDocumentLocator" << std::endl; + } + virtual void startDocument() { + std::cout << "startDocument" << std::endl; + } + virtual void endDocument() { + std::cout << "endDocument" << std::endl; + } + virtual void startPrefixMapping(const std::string& prefix, const std::string& uri) { + std::cout << "startPrefixMapping" << std::endl; + std::cout << " prefix:" << prefix << std::endl; + std::cout << " uri:" << uri << std::endl; + } + virtual void endPrefixMapping(const std::string& prefix) { + std::cout << "endPrefixMapping" << std::endl; + std::cout << " prefix:" << prefix << std::endl; + } + virtual void startElement(const std::string& namespaceURI, const std::string& localName, + const std::string& qName, const AttributesT& atts) { + std::cout << "startElement" << std::endl; + std::cout << " namespaceURI:" << namespaceURI << std::endl; + std::cout << " localName:" << localName << std::endl; + std::cout << " qName:" << qName << std::endl; + std::cout << " atts:" << atts.getLength() << std::endl; + } + virtual void endElement(const std::string& namespaceURI, const std::string& localName, + const std::string& qName) { + std::cout << "endElement" << std::endl; + std::cout << " namespaceURI:" << namespaceURI << std::endl; + std::cout << " localName:" << localName << std::endl; + std::cout << " qName:" << qName << std::endl; + } + virtual void characters(const std::string& ch) { + std::cout << "characters" << std::endl; + std::cout << " ch:" << ch << std::endl; + } + virtual void ignorableWhitespace(const std::string& ch) { + std::cout << "ignorableWhitespace" << std::endl; + std::cout << " ch:" << ch << std::endl; + } + virtual void processingInstruction(const std::string& target, const std::string& data) { + std::cout << "processingInstruction" << std::endl; + std::cout << " target:" << target << std::endl; + std::cout << " data:" << data << std::endl; + } + virtual void skippedEntity(const std::string& name) { + std::cout << "skippedEntity" << std::endl; + std::cout << " name:" << name << std::endl; + } + + // ErrorHandler + virtual void warning(const SAXParseExceptionT& e) { Arabica::SAX::CatchErrorHandler<std::string>::warning(e); } + virtual void error(const SAXParseExceptionT& e) { Arabica::SAX::CatchErrorHandler<std::string>::error(e); } + virtual void fatalError(const SAXParseExceptionT& e) { + Arabica::SAX::CatchErrorHandler<std::string>::fatalError(e); + } + + // LexicalHandler + virtual void startDTD(const std::string& name, + const std::string& publicId, + const std::string& systemId) { + std::cout << "startDTD" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " publicId:" << publicId << std::endl; + std::cout << " systemId:" << systemId << std::endl; + } + + virtual void endDTD() { + std::cout << "endDTD" << std::endl; + } + virtual void startEntity(const std::string& name) { + std::cout << "startEntity" << std::endl; + std::cout << " name:" << name << std::endl; + } + virtual void endEntity(const std::string& name) { + std::cout << "endEntity" << std::endl; + std::cout << " name:" << name << std::endl; + } + virtual void startCDATA() { + std::cout << "startCDATA" << std::endl; + } + virtual void endCDATA() { + std::cout << "endCDATA" << std::endl; + } + virtual void comment(const std::string& text) { + std::cout << "comment" << std::endl; + std::cout << " text:" << text << std::endl; + } + + // DeclHandler + virtual void elementDecl(const std::string& name, const std::string& model) { + std::cout << "elementDecl" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " model:" << model << std::endl; + } + virtual void attributeDecl(const std::string& elementName, + const std::string& attributeName, + const std::string& type, + const std::string& valueDefault, + const std::string& value) { + std::cout << "attributeDecl" << std::endl; + std::cout << " elementName:" << elementName << std::endl; + std::cout << " attributeName:" << attributeName << std::endl; + std::cout << " type:" << type << std::endl; + std::cout << " valueDefault:" << valueDefault << std::endl; + std::cout << " value:" << value << std::endl; + } + virtual void internalEntityDecl(const std::string& name, const std::string& value) { + std::cout << "internalEntityDecl" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " value:" << value << std::endl; + } + virtual void externalEntityDecl(const std::string& name, + const std::string& publicId, + const std::string& systemId) { + std::cout << "externalEntityDecl" << std::endl; + std::cout << " name:" << name << std::endl; + std::cout << " publicId:" << publicId << std::endl; + std::cout << " systemId:" << systemId << std::endl; + } + + }; +#endif +} + +#endif |