summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-09-16 00:12:32 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-09-16 00:12:32 (GMT)
commitd7211d570f8b78442f35bd9c55808053eb18ecc2 (patch)
tree5f670609b6486e8bf4cad19ca0967d51cb0becb4 /src/uscxml
parentaa6c3a1257a29cc5bcf8b94893732ee553f27582 (diff)
downloaduscxml-d7211d570f8b78442f35bd9c55808053eb18ecc2.zip
uscxml-d7211d570f8b78442f35bd9c55808053eb18ecc2.tar.gz
uscxml-d7211d570f8b78442f35bd9c55808053eb18ecc2.tar.bz2
Implemented invoke for nested SCXML instances
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/Factory.cpp17
-rw-r--r--src/uscxml/Factory.h25
-rw-r--r--src/uscxml/Interpreter.cpp257
-rw-r--r--src/uscxml/Interpreter.h39
-rw-r--r--src/uscxml/Message.cpp62
-rw-r--r--src/uscxml/Message.h4
-rw-r--r--src/uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.cpp4
-rw-r--r--src/uscxml/datamodel/ecmascript/v8/V8DataModel.cpp52
-rw-r--r--src/uscxml/datamodel/ecmascript/v8/V8DataModel.h6
-rw-r--r--src/uscxml/invoker/scxml/USCXMLInvoker.cpp48
-rw-r--r--src/uscxml/invoker/scxml/USCXMLInvoker.h29
-rw-r--r--src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.cpp70
-rw-r--r--src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h10
13 files changed, 466 insertions, 157 deletions
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 91da562..ee2a3bd 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -2,13 +2,17 @@
#include "uscxml/datamodel/ecmascript/v8/V8DataModel.h"
//#include "uscxml/ioprocessor/basichttp/pion/PionIOProcessor.h"
#include "uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h"
+#include "uscxml/invoker/scxml/USCXMLInvoker.h"
namespace uscxml {
Factory::Factory() {
_dataModels["ecmascript"] = new V8DataModel();
// _ioProcessors["basichttp"] = new PionIOProcessor();
- _ioProcessors["basichttp"] = new io::libevent::EventIOProcessor();
+ _ioProcessors["basichttp"] = new EventIOProcessor();
+ _ioProcessors["http://www.w3.org/TR/scxml/#SCXMLEventProcessor"] = new EventIOProcessor();
+ _invoker["scxml"] = new USCXMLInvoker();
+ _invoker["http://www.w3.org/TR/scxml/"] = _invoker["scxml"];
}
void Factory::registerIOProcessor(const std::string type, IOProcessor* ioProcessor) {
@@ -23,6 +27,17 @@ namespace uscxml {
getInstance()->_executableContent[tag] = executableContent;
}
+ void Factory::registerInvoker(const std::string type, Invoker* invoker) {
+ getInstance()->_invoker[type] = invoker;
+ }
+
+ Invoker* Factory::getInvoker(const std::string type, Interpreter* interpreter) {
+ if (Factory::getInstance()->_invoker.find(type) != getInstance()->_invoker.end()) {
+ return (Invoker*)getInstance()->_invoker[type]->create(interpreter);
+ }
+ return NULL;
+ }
+
DataModel* Factory::getDataModel(const std::string type, Interpreter* interpreter) {
if (Factory::getInstance()->_dataModels.find(type) != getInstance()->_dataModels.end()) {
return getInstance()->_dataModels[type]->create(interpreter);
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index f1840c6..c5d4598 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -14,26 +14,30 @@ namespace uscxml {
ExecutableContent() {};
virtual ExecutableContent* create(Interpreter* interpreter) = 0;
};
-
+
class IOProcessor {
public:
IOProcessor() {};
virtual ~IOProcessor() {};
virtual IOProcessor* create(Interpreter* interpreter) = 0;
- virtual std::string getURL() = 0;
+ virtual Data getDataModelVariables() = 0;
virtual void send(SendRequest& req) = 0;
+ };
+
+ class Invoker : public IOProcessor {
+ public:
virtual void invoke(InvokeRequest& req) = 0;
- virtual void cancel(const std::string sendId) = 0;
+ virtual void sendToParent(SendRequest& req) = 0;
};
-
+
class DataModel {
public:
virtual DataModel* create(Interpreter* interpreter) = 0;
-
+ virtual ~DataModel() {}
+
virtual bool validate(const std::string& location, const std::string& schema) = 0;
- virtual void setEvent(Event& event) = 0;
- virtual void setData(const std::string& key, Data& event) = 0;
+ virtual void setEvent(const Event& event) = 0;
// foreach
virtual uint32_t getLength(const std::string& expr) = 0;
@@ -43,7 +47,8 @@ namespace uscxml {
virtual void eval(const std::string& expr) = 0;
virtual std::string evalAsString(const std::string& expr) = 0;
virtual bool evalAsBool(const std::string& expr) = 0;
- virtual void assign(const std::string& location, const std::string& expr) = 0;
+ virtual void assign(const std::string& location, const std::string& expr) = 0;
+ virtual void assign(const std::string& location, const Data& data) = 0;
};
class Factory {
@@ -51,14 +56,18 @@ namespace uscxml {
static void registerIOProcessor(const std::string type, IOProcessor* ioProcessor);
static void registerDataModel(const std::string type, DataModel* dataModel);
static void registerExecutableContent(const std::string tag, ExecutableContent* executableContent);
+ static void registerInvoker(const std::string type, Invoker* invoker);
static DataModel* getDataModel(const std::string type, Interpreter* interpreter);
static IOProcessor* getIOProcessor(const std::string type, Interpreter* interpreter);
static ExecutableContent* getExecutableContent(const std::string tag, Interpreter* interpreter);
+ static Invoker* getInvoker(const std::string type, Interpreter* interpreter);
+
static Factory* getInstance();
std::map<std::string, DataModel*> _dataModels;
std::map<std::string, IOProcessor*> _ioProcessors;
+ std::map<std::string, Invoker*> _invoker;
std::map<std::string, ExecutableContent*> _executableContent;
protected:
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 7189f12..267d53f 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -23,30 +23,99 @@ const std::string Interpreter::getUUID() {
return boost::lexical_cast<std::string>(uuidGen());
}
-Interpreter::Interpreter(const std::string& url) {
- _thread = NULL;
- _url = url;
+Interpreter::Interpreter() {
+}
+
+Interpreter* Interpreter::fromDOM(const Arabica::DOM::Node<std::string>& node) {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Interpreter* interpreter = new Interpreter();
+ interpreter->_doc = domFactory.createDocument("http://www.w3.org/2005/07/scxml", "scxml", 0);
+ interpreter->_doc.appendChild(node);
+ interpreter->init();
+
+ return interpreter;
+}
+
+Interpreter* Interpreter::fromXML(const std::string& xml) {
+ std::istringstream is(xml);
+ Arabica::SAX::InputSource<std::string> inputSource;
+ return fromInputSource(inputSource);
+}
+
+Interpreter* Interpreter::fromURI(const std::string& uri) {
+ Arabica::SAX::InputSource<std::string> inputSource(uri);
+ Interpreter* interpreter = fromInputSource(inputSource);
+
+ // try to establish URI root for relative src attributes in document
+ interpreter->_baseURI = toBaseURI(Arabica::io::URI(uri));
+ return interpreter;
+}
- LOG(INFO) << "runtime started with " << _url;
- Arabica::SAX::InputSource<std::string> inputSource(_url);
+Arabica::io::URI Interpreter::toBaseURI(const Arabica::io::URI& uri) {
+ std::stringstream ssBaseURI;
+ if (uri.scheme().size() > 0)
+ ssBaseURI << uri.scheme() << "://";
+ if (uri.host().size() > 0) {
+ ssBaseURI << uri.host();
+ if (!boost::iequals(uri.port(), "0"))
+ ssBaseURI << ":" << uri.port();
+ }
+ if (uri.path().size() > 0) {
+ std::string uriPath = uri.path();
+ uriPath = uriPath.substr(0, uriPath.find_last_of("/\\"));
+ ssBaseURI << uriPath;
+ }
+ return Arabica::io::URI(ssBaseURI.str());
+}
+
+Arabica::io::URI Interpreter::toAbsoluteURI(const Arabica::io::URI& uri, const Arabica::io::URI& baseURI) {
+ if (baseURI.as_string().size() > 0) {
+ std::stringstream ssAbsoluteURI;
+ if (baseURI.scheme().size() > 0)
+ ssAbsoluteURI << baseURI.scheme() << "://";
+ if (baseURI.host().size() > 0) {
+ ssAbsoluteURI << baseURI.host();
+ if (!boost::iequals(baseURI.port(), "0"))
+ ssAbsoluteURI << ":" << baseURI.port();
+ }
+ if (baseURI.path().size() > 0) {
+ ssAbsoluteURI << baseURI.path() << "/" << uri.path();
+ }
+ return Arabica::io::URI(ssAbsoluteURI.str());
+ }
+ return uri;
+}
+
+Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) {
+ Interpreter* interpreter = new Interpreter();
Arabica::SAX2DOM::Parser<std::string> domParser;
Arabica::SAX::CatchErrorHandler<std::string> errorHandler;
domParser.setErrorHandler(errorHandler);
- if(!domParser.parse(inputSource) || !domParser.getDocument().hasChildNodes()) {
- LOG(INFO) << "could not parse " << _url << ":";
+ if(!domParser.parse(source) || !domParser.getDocument().hasChildNodes()) {
+ LOG(INFO) << "could not parse input:";
if(errorHandler.errorsReported()) {
LOG(ERROR) << errorHandler.errors() << std::endl;
} else {
- Arabica::SAX::InputSourceResolver resolver(inputSource, Arabica::default_string_adaptor<std::string>());
+ Arabica::SAX::InputSourceResolver resolver(source, Arabica::default_string_adaptor<std::string>());
if (!resolver.resolve()) {
LOG(ERROR) << "no such file";
}
}
} else {
- _doc = domParser.getDocument();
+ interpreter->_doc = domParser.getDocument();
}
-
+ interpreter->init();
+ return interpreter;
+}
+
+void Interpreter::init() {
+ _thread = NULL;
+ _dataModel = NULL;
+ _invoker = NULL;
+ _running = false;
+ _sendQueue = new DelayedEventQueue();
+ _sendQueue->start();
if (_doc) {
// do we have a xmlns attribute?
std::string ns = _doc.getDocumentElement().getNamespaceURI();
@@ -72,18 +141,19 @@ Interpreter::~Interpreter() {
ioProcessorIter++;
}
if (_thread) {
+ _running = false;
+ _externalQueue.push(Event());
_thread->join();
delete(_thread);
}
+ delete _dataModel;
+ delete _sendQueue;
}
void Interpreter::start() {
_thread = new tthread::thread(Interpreter::run, this);
}
-
-void Interpreter::stop() {
-}
-
+
void Interpreter::run(void* instance) {
((Interpreter*)instance)->interpret();
}
@@ -158,6 +228,9 @@ void Interpreter::interpret() {
mainEventLoop();
}
+/**
+ * Called with a single data element from the topmost datamodel element.
+ */
void Interpreter::initializeData(const Arabica::DOM::Node<std::string>& data) {
if (!_dataModel) {
LOG(ERROR) << "Cannot initialize data when no datamodel is given!";
@@ -166,28 +239,22 @@ void Interpreter::initializeData(const Arabica::DOM::Node<std::string>& data) {
try {
if (!HAS_ATTR(data, "id"))
return;
- std::string value = "undefined";
if (HAS_ATTR(data, "expr")) {
- value = ATTR(data, "expr");
- goto VALUE_INITIALIZED;
- }
- if (HAS_ATTR(data, "src")) {
+ std::string value = ATTR(data, "expr");
+ _dataModel->assign(ATTR(data, "id"), value);
+ } else if (HAS_ATTR(data, "src")) {
Arabica::SAX::InputSourceResolver resolver(Arabica::SAX::InputSource<std::string>(ATTR(data, "src")),
Arabica::default_string_adaptor<std::string>());
- value = std::string(std::istreambuf_iterator<char>(*resolver.resolve()), std::istreambuf_iterator<char>());
- goto VALUE_INITIALIZED;
- }
- if (data.hasChildNodes()) {
+ std::string value = std::string(std::istreambuf_iterator<char>(*resolver.resolve()), std::istreambuf_iterator<char>());
+ _dataModel->assign(ATTR(data, "id"), value);
+ } else if (data.hasChildNodes()) {
// search for the text node with the actual script
- if (data.getFirstChild().getNodeType() == Node_base::TEXT_NODE) {
- value = data.getFirstChild().getNodeValue();
- }
+ Data value = Data(data);
+// std::cout << value << std::endl;
+ _dataModel->assign(ATTR(data, "id"), value);
}
-
-VALUE_INITIALIZED:
- _dataModel->assign(ATTR(data, "id"), value);
-
+
} catch (Event e) {
LOG(ERROR) << "Syntax error in send element:" << std::endl << e << std::endl;
}
@@ -204,6 +271,15 @@ void Interpreter::normalize(const Arabica::DOM::Node<std::string>& node) {
}
}
+ // make sure every invoke has an idlocation or id
+ Arabica::XPath::NodeSet<std::string> invokes = _xpath.evaluate("//" + _nsPrefix + "invoke", _doc).asNodeSet();
+ for (int i = 0; i < invokes.size(); i++) {
+ Arabica::DOM::Element<std::string> invokeElem = Arabica::DOM::Element<std::string>(invokes[i]);
+ if (!invokeElem.hasAttribute("id") && !invokeElem.hasAttribute("idlocation")) {
+ invokeElem.setAttribute("id", getUUID());
+ }
+ }
+
Arabica::XPath::NodeSet<std::string> finals = _xpath.evaluate("//" + _nsPrefix + "final", _doc).asNodeSet();
for (int i = 0; i < finals.size(); i++) {
Arabica::DOM::Element<std::string> finalElem = Arabica::DOM::Element<std::string>(finals[i]);
@@ -260,9 +336,7 @@ void Interpreter::mainEventLoop() {
for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
NodeSet<std::string> invokes = _xpath.evaluate("" + _nsPrefix + "invoke", _statesToInvoke[i]).asNodeSet();
for (unsigned int j = 0; j < invokes.size(); j++) {
- // @TODO:
- // boost::shared_ptr<Invoke> invoke = boost::static_pointer_cast<Invoke>(interpreter::Factory::create("invoke", invokes[j]));
- // invoke->invoke(this);
+ invoke(invokes[j]);
}
}
@@ -295,7 +369,8 @@ void Interpreter::mainEventLoop() {
// invoke->applyFinalize(this);
}
if (autoForward.length() > 0) {
- send(invokeId, externalEvent);
+ // @TODO
+// send(invokeId, externalEvent);
}
}
}
@@ -305,9 +380,6 @@ void Interpreter::mainEventLoop() {
}
exitInterpreter();
}
-
-void Interpreter::send(const std::string invokeId, Event& event) {
-}
void Interpreter::send(const Arabica::DOM::Node<std::string>& element) {
SendRequest sendReq;
@@ -424,24 +496,43 @@ void Interpreter::send(const Arabica::DOM::Node<std::string>& element) {
LOG(ERROR) << "content element has expr attribute but no datamodel is specified.";
}
} else if (contents[0].hasChildNodes()) {
-// dump(contents[0].getFirstChild());
sendReq.content = contents[0].getFirstChild().getNodeValue();
} else {
LOG(ERROR) << "content element does not specify any content.";
}
}
- IOProcessor* ioProc = getIOProcessor(sendReq.type);
- if (ioProc != NULL) {
- _ioProcessorsIds[sendReq.sendid] = ioProc;
- ioProc->send(sendReq);
- }
+ assert(_sendIds.find(sendReq.sendid) == _sendIds.end());
+ _sendIds[sendReq.sendid] = std::make_pair(this, sendReq);
+ _sendQueue->addEvent(sendReq.sendid, Interpreter::delayedSend, sendReq.delayMs, &_sendIds[sendReq.sendid]);
} catch (Event e) {
LOG(ERROR) << "Syntax error in send element:" << std::endl << e << std::endl;
}
}
-
+
+void Interpreter::delayedSend(void* userdata, std::string eventName) {
+ std::pair<Interpreter*, SendRequest>* data = (std::pair<Interpreter*, SendRequest>*)(userdata);
+
+ Interpreter* THIS = data->first;
+ SendRequest sendReq = data->second;
+
+ if (boost::iequals(sendReq.target, "_parent")) {
+ if (THIS->_invoker != NULL) {
+ THIS->_invoker->sendToParent(sendReq);
+ } else {
+ LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl;
+ }
+ } else {
+ IOProcessor* ioProc = THIS->getIOProcessor(sendReq.type);
+ if (ioProc != NULL) {
+ ioProc->send(sendReq);
+ }
+ }
+ assert(THIS->_sendIds.find(sendReq.sendid) != THIS->_sendIds.end());
+ THIS->_sendIds.erase(sendReq.sendid);
+}
+
void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
InvokeRequest invokeReq;
try {
@@ -455,21 +546,35 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
}
// src
+ std::string source;
if (HAS_ATTR(element, "srcexpr") && _dataModel) {
- invokeReq.src = _dataModel->evalAsString(ATTR(element, "srcexpr"));
+ source = _dataModel->evalAsString(ATTR(element, "srcexpr"));
} else if (HAS_ATTR(element, "src")) {
- invokeReq.src = ATTR(element, "src");
+ source = ATTR(element, "src");
} else {
LOG(ERROR) << "invoke element is missing src or srcexpr or no datamodel is specified";
}
-
+ Arabica::io::URI srcURI(source);
+ if (!srcURI.is_absolute()) {
+ if (_baseURI.as_string().size() > 0) {
+ srcURI = toAbsoluteURI(srcURI, _baseURI);
+ invokeReq.src = srcURI.as_string();
+ } else {
+ LOG(ERROR) << "invoke element has relative src with no baseURI set";
+ return;
+ }
+ } else {
+ invokeReq.src = srcURI.as_string();
+ }
+
+
// id
if (HAS_ATTR(element, "idlocation") && _dataModel) {
invokeReq.invokeid = _dataModel->evalAsString(ATTR(element, "idlocation"));
} else if (HAS_ATTR(element, "id")) {
invokeReq.invokeid = ATTR(element, "id");
} else {
- invokeReq.invokeid = getUUID();
+ assert(false);
}
// namelist
@@ -513,10 +618,10 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
invokeReq.content = contents[0].getNodeValue();
}
- IOProcessor* ioProc = getIOProcessor(invokeReq.type);
- if (ioProc != NULL) {
- _ioProcessorsIds[invokeReq.invokeid] = ioProc;
- ioProc->invoke(invokeReq);
+ Invoker* invoker = Factory::getInvoker(invokeReq.type, this);
+ if (invoker != NULL) {
+ _invokerIds[invokeReq.invokeid] = invoker;
+ invoker->invoke(invokeReq);
}
} catch (Event e) {
@@ -525,6 +630,23 @@ void Interpreter::invoke(const Arabica::DOM::Node<std::string>& element) {
}
+void Interpreter::cancelInvoke(const Arabica::DOM::Node<std::string>& element) {
+ std::string invokeId;
+ if (HAS_ATTR(element, "idlocation") && _dataModel) {
+ invokeId = _dataModel->evalAsString(ATTR(element, "idlocation"));
+ } else if (HAS_ATTR(element, "id")) {
+ invokeId = ATTR(element, "id");
+ } else {
+ assert(false);
+ }
+ if (_invokerIds.find(invokeId) != _invokerIds.end()) {
+ delete (_invokerIds[invokeId]);
+ _invokerIds.erase(invokeId);
+ } else {
+ LOG(ERROR) << "Cannot cancel invoke for id " << invokeId << ": no soch invokation";
+ }
+}
+
Arabica::XPath::NodeSet<std::string> Interpreter::selectTransitions(const std::string& event) {
Arabica::XPath::NodeSet<std::string> enabledTransitions;
@@ -857,12 +979,8 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content)
} else {
LOG(ERROR) << "Expected sendidexpr or sendid attribute in cancel element";
return;
- }
-
- IOProcessor* ioProc = getIOProcessorForId(sendId);
- if (ioProc != NULL) {
- ioProc->cancel(sendId);
- }
+ }
+ _sendQueue->cancelEvent(sendId);
} catch (Event e) {
LOG(ERROR) << "Syntax error while executing cancel element" << std::endl << e << std::endl;
@@ -878,9 +996,6 @@ void Interpreter::executeContent(const Arabica::DOM::Node<std::string>& content)
}
}
-void Interpreter::cancelInvoke(const Arabica::DOM::Node<std::string>& content) {
-}
-
void Interpreter::returnDoneEvent(const Arabica::DOM::Node<std::string>& state) {
}
@@ -1450,7 +1565,9 @@ void Interpreter::setupIOProcessors() {
_ioProcessors[ioProcIter->first] = Factory::getIOProcessor(ioProcIter->first, this);
if (_dataModel) {
try {
- _dataModel->assign("_ioprocessors['" + ioProcIter->first + "']", "'" + _ioProcessors[ioProcIter->first]->getURL() + "'");
+// _dataModel->setData("_ioprocessors", ioProcIter->first, _ioProcessors[ioProcIter->first]->getDataModelVariables());
+ _dataModel->assign("_ioprocessors['" + ioProcIter->first + "']", _ioProcessors[ioProcIter->first]->getDataModelVariables());
+ std::cout << _dataModel->evalAsString("_ioprocessors['basichttp'].location") << std::endl;
} catch (Event e) {
LOG(ERROR) << "Syntax error when setting _ioprocessors:" << std::endl << e << std::endl;
}
@@ -1469,19 +1586,19 @@ IOProcessor* Interpreter::getIOProcessor(const std::string& type) {
return _ioProcessors[type];
}
-IOProcessor* Interpreter::getIOProcessorForId(const std::string& sendId) {
- if (_ioProcessorsIds.find(sendId) == _ioProcessorsIds.end()) {
- LOG(ERROR) << "No ioProcessor with pending send id " << sendId << sendId;
- return NULL;
- }
- return _ioProcessorsIds[sendId];
-}
+//IOProcessor* Interpreter::getIOProcessorForId(const std::string& sendId) {
+// if (_sendQueue.find(sendId) == _sendQueue.end()) {
+// LOG(ERROR) << "No ioProcessor with pending send id " << sendId << sendId;
+// return NULL;
+// }
+// return _ioProcessorsIds[sendId];
+//}
bool Interpreter::validate() {
bool validationErrors = false;
if (!_doc) {
- LOG(ERROR) << "Document " << _url << " was not parsed successfully" << std::endl;
+ LOG(ERROR) << "Document " << _baseURI.as_string() << " was not parsed successfully" << std::endl;
return false;
}
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index fb913d1..a60f9f6 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -10,11 +10,13 @@
#include <XPath/XPath.hpp>
#include <DOM/Document.hpp>
+#include <io/uri.hpp>
#include <DOM/SAX2DOM/SAX2DOM.hpp>
#include <SAX/helpers/CatchErrorHandler.hpp>
#include "uscxml/concurrency/tinythread.h"
+#include "uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.h"
#include "uscxml/concurrency/BlockingQueue.h"
#include "uscxml/Message.h"
#include "uscxml/Factory.h"
@@ -28,16 +30,29 @@ namespace uscxml {
LATE = 1
};
- Interpreter(const std::string& url);
+ struct SendData {
+ Interpreter* interpreter;
+ uscxml::SendRequest req;
+ };
+
virtual ~Interpreter();
+ static Interpreter* fromDOM(const Arabica::DOM::Node<std::string>& node);
+ static Interpreter* fromXML(const std::string& xml);
+ static Interpreter* fromURI(const std::string& uri);
+ static Interpreter* fromInputSource(Arabica::SAX::InputSource<std::string>& source);
+
void start();
- void stop();
static void run(void*);
void interpret();
bool validate();
+ void setBaseURI(std::string baseURI) { _baseURI = Arabica::io::URI(baseURI); }
+ DataModel* getDataModel() { return _dataModel; }
+ Invoker* getInvoker() { return _invoker; }
+ void setInvoker(Invoker* invoker) { _invoker = invoker; }
+
void waitForStabilization();
void receive(Event& event) { _externalQueue.push(event); }
@@ -54,6 +69,9 @@ namespace uscxml {
static void dump(const Arabica::DOM::Node<std::string>& node, int lvl = 0);
protected:
+ Interpreter();
+ void init();
+
void normalize(const Arabica::DOM::Node<std::string>& node);
void setupIOProcessors();
@@ -64,7 +82,7 @@ namespace uscxml {
tthread::mutex _mutex;
tthread::condition_variable _stabilized;
- std::string _url;
+ Arabica::io::URI _baseURI;
Arabica::DOM::Document<std::string> _doc;
Arabica::DOM::Element<std::string> _scxml;
Arabica::XPath::XPath<std::string> _xpath;
@@ -81,6 +99,11 @@ namespace uscxml {
std::list<Event > _internalQueue;
uscxml::concurrency::BlockingQueue<Event> _externalQueue;
+ DelayedEventQueue* _sendQueue;
+ Invoker* _invoker;
+
+ static Arabica::io::URI toBaseURI(const Arabica::io::URI& uri);
+ static Arabica::io::URI toAbsoluteURI(const Arabica::io::URI& uri, const Arabica::io::URI& baseURI);
void microstep(const Arabica::XPath::NodeSet<std::string>& enabledTransitions);
void exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions);
@@ -105,11 +128,11 @@ namespace uscxml {
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 cancelInvoke(const Arabica::DOM::Node<std::string>& element);
void returnDoneEvent(const Arabica::DOM::Node<std::string>& state);
+ static void delayedSend(void* userdata, std::string eventName);
static bool nameMatch(const std::string& transitionEvent, const std::string& event);
Arabica::XPath::NodeSet<std::string> filterPreempted(const Arabica::XPath::NodeSet<std::string>& enabledTransitions);
@@ -139,10 +162,12 @@ namespace uscxml {
std::string _sessionId;
IOProcessor* getIOProcessor(const std::string& type);
- IOProcessor* getIOProcessorForId(const std::string& sendId);
+// IOProcessor* getIOProcessorForId(const std::string& sendId);
- std::map<std::string, IOProcessor*> _ioProcessorsIds;
std::map<std::string, IOProcessor*> _ioProcessors;
+ std::map<std::string, std::pair<Interpreter*, SendRequest> > _sendIds;
+ std::map<std::string, Invoker*> _invokerIds;
+ std::map<std::string, Invoker*> _invokers;
};
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index 3d3048b..f7e7a5a 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -1,4 +1,5 @@
#include "uscxml/Message.h"
+//#include "uscxml/Interpreter.h"
#include <DOM/SAX2DOM/SAX2DOM.hpp>
#include <SAX/helpers/CatchErrorHandler.hpp>
@@ -6,6 +7,65 @@ namespace uscxml {
static int _dataIndentation = 1;
+Data::Data(const Arabica::DOM::Node<std::string>& dom) {
+ // we may need to convert some keys to arrays if we have the same name as an element
+ std::map<std::string, std::list<Data> > arrays;
+// Interpreter::dump(dom);
+
+ if (dom.hasAttributes()) {
+ Arabica::DOM::NamedNodeMap<std::string> attributes = dom.getAttributes();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Arabica::DOM::Node<std::string> attribute = attributes.item(i);
+// Interpreter::dump(attribute);
+
+ assert(attribute.getNodeType() == Arabica::DOM::Node_base::ATTRIBUTE_NODE);
+ std::string key = attribute.getLocalName();
+ std::string value = attribute.getNodeValue();
+ compound[key] = Data(value, VERBATIM);
+ }
+ }
+
+ if (dom.hasChildNodes()) {
+ Arabica::DOM::NodeList<std::string> children = dom.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Arabica::DOM::Node<std::string> child = children.item(i);
+// Interpreter::dump(child);
+ std::string key;
+ switch (child.getNodeType()) {
+ case Arabica::DOM::Node_base::ELEMENT_NODE:
+ key = TAGNAME(child);
+ break;
+ case Arabica::DOM::Node_base::ATTRIBUTE_NODE:
+ key = ((Arabica::DOM::Attr<std::string>)child).getName();
+ break;
+ case Arabica::DOM::Node_base::TEXT_NODE:
+ default:
+ break;
+ }
+ if (key.length() == 0)
+ continue;
+
+ if (compound.find(key) != compound.end()) {
+ // we already have such a key .. make it an array after we processed all children
+ arrays[key].push_back(Data(child));
+ } else {
+ compound[key] = Data(child);
+ }
+ }
+ } else {
+ atom = dom.getNodeValue();
+ type = VERBATIM;
+ }
+
+ std::map<std::string, std::list<Data> >::iterator arrayIter = arrays.begin();
+ while(arrayIter != arrays.end()) {
+ assert(compound.find(arrayIter->first) != compound.end());
+ Data arrayData;
+ arrays[arrayIter->first].push_front(compound[arrayIter->first]);
+ arrayData.array = arrays[arrayIter->first];
+ compound[arrayIter->first] = arrayData;
+ }
+}
Arabica::DOM::Document<std::string> Data::toDocument() {
Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
@@ -137,7 +197,7 @@ std::ostream& operator<< (std::ostream& os, const Data& data) {
os << "{" << std::endl;
compoundIter = data.compound.begin();
while(compoundIter != data.compound.end()) {
- os << indent << " \"" << compoundIter->first << "\" " << keyPadding.substr(0, longestKey - compoundIter->first.size()) << "= ";
+ os << indent << " \"" << compoundIter->first << "\" " << keyPadding.substr(0, longestKey - compoundIter->first.size()) << ": ";
_dataIndentation += 2;
os << compoundIter->second << "," << std::endl;
_dataIndentation -= 2;
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index a520ff5..cd10c05 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -2,6 +2,7 @@
#define EVENT_H_XZAQ4HR
#include <map>
+#include <list>
#include <vector>
#include <string>
@@ -23,6 +24,7 @@ public:
Data() {}
Data(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {}
+ Data(const Arabica::DOM::Node<std::string>& dom);
virtual ~Data() {}
static Data fromXML(const std::string& xmlString);
@@ -34,7 +36,7 @@ public:
}
std::map<std::string, Data> compound;
- std::vector<Data> array;
+ std::list<Data> array;
std::string atom;
Type type;
diff --git a/src/uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.cpp b/src/uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.cpp
index ce42af7..647380e 100644
--- a/src/uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.cpp
+++ b/src/uscxml/concurrency/eventqueue/libevent/DelayedEventQueue.cpp
@@ -12,8 +12,7 @@ namespace uscxml {
DelayedEventQueue::~DelayedEventQueue() {
std::cout << "Deleting DelayedEventQueue" << std::endl;
- if(_eventLoop)
- event_base_loopbreak(_eventLoop);
+ stop();
if (_thread)
_thread->join();
if(_eventLoop)
@@ -66,6 +65,7 @@ namespace uscxml {
void DelayedEventQueue::stop() {
if (_isStarted) {
_isStarted = false;
+ event_base_loopbreak(_eventLoop);
_thread->join();
delete _thread;
}
diff --git a/src/uscxml/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/datamodel/ecmascript/v8/V8DataModel.cpp
index e31438a..2dfc72f 100644
--- a/src/uscxml/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -64,7 +64,7 @@ void V8DataModel::popContext() {
void V8DataModel::initialize() {
}
-void V8DataModel::setEvent(Event& event) {
+void V8DataModel::setEvent(const Event& event) {
_event = event;
v8::Locker locker;
v8::HandleScope handleScope;
@@ -86,24 +86,16 @@ void V8DataModel::setEvent(Event& event) {
assert(_eventTemplate->InternalFieldCount() == 1);
v8::Handle<v8::Object> eventJS = _eventTemplate->NewInstance();
- eventJS->SetInternalField(0, v8::External::New(&event));
+ eventJS->SetInternalField(0, v8::External::New(&_event));
eventJS->Set(v8::String::New("data"), getDataAsValue(event)); // set data part of _event
global->Set(v8::String::New("_event"), eventJS);
}
-void V8DataModel::setData(const std::string& key, Data& data) {
- v8::Locker locker;
- v8::HandleScope handleScope;
- v8::Context::Scope contextScope(_contexts.front());
- v8::Handle<v8::Object> global = _contexts.front()->Global();
- global->Set(v8::String::New(key.c_str()), getDataAsValue(data));
-}
-
-v8::Handle<v8::Value> V8DataModel::getDataAsValue(Data& data) {
+v8::Handle<v8::Value> V8DataModel::getDataAsValue(const Data& data) {
if (data.compound.size() > 0) {
v8::Handle<v8::Object> value = v8::Array::New();
- std::map<std::string, Data>::iterator compoundIter = data.compound.begin();
+ std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
while(compoundIter != data.compound.end()) {
value->Set(v8::String::New(compoundIter->first.c_str()), getDataAsValue(compoundIter->second));
compoundIter++;
@@ -112,7 +104,7 @@ v8::Handle<v8::Value> V8DataModel::getDataAsValue(Data& data) {
}
if (data.array.size() > 0) {
v8::Handle<v8::Object> value = v8::Array::New();
- std::vector<Data>::iterator arrayIter = data.array.begin();
+ std::list<Data>::const_iterator arrayIter = data.array.begin();
uint32_t index = 0;
while(arrayIter != data.array.end()) {
value->Set(index++, getDataAsValue(*arrayIter));
@@ -126,7 +118,7 @@ v8::Handle<v8::Value> V8DataModel::getDataAsValue(Data& data) {
return evalAsValue(data.atom);
}
}
-
+
v8::Handle<v8::Value> V8DataModel::jsIn(const v8::Arguments& args) {
V8DataModel* THIS = static_cast<V8DataModel*>(v8::External::Unwrap(args.Data()));
for (unsigned int i = 0; i < args.Length(); i++) {
@@ -227,6 +219,38 @@ std::string V8DataModel::evalAsString(const std::string& expr) {
return std::string(*data);
}
+void V8DataModel::assign(const std::string& location, const Data& data) {
+ v8::Locker locker;
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(_contexts.front());
+
+ std::stringstream ssJSON;
+ ssJSON << data;
+ assign(location, ssJSON.str());
+// v8::Handle<v8::Object> variable = evalAsValue(location).As<v8::Object>();
+// assert(!variable.IsEmpty());
+// if (data.compound.size() > 0) {
+// std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
+// while(compoundIter != data.compound.end()) {
+// variable->Set(v8::String::New(compoundIter->first.c_str()), getDataAsValue(compoundIter->second));
+// compoundIter++;
+// }
+// return;
+// } else if (data.array.size() > 0) {
+// std::list<Data>::const_iterator arrayIter = data.array.begin();
+// uint32_t index = 0;
+// while(arrayIter != data.array.end()) {
+// variable->Set(index++, getDataAsValue(*arrayIter));
+// arrayIter++;
+// }
+// } else if (data.type == Data::VERBATIM) {
+// assign(location, "'" + data.atom + "'");
+// } else {
+// assign(location, data.atom);
+// }
+
+}
+
void V8DataModel::assign(const std::string& location, const std::string& expr) {
v8::Locker locker;
v8::HandleScope handleScope;
diff --git a/src/uscxml/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/datamodel/ecmascript/v8/V8DataModel.h
index 7522679..340b6ee 100644
--- a/src/uscxml/datamodel/ecmascript/v8/V8DataModel.h
+++ b/src/uscxml/datamodel/ecmascript/v8/V8DataModel.h
@@ -21,9 +21,7 @@ public:
virtual void initialize();
virtual void setSessionId(const std::string& sessionId);
virtual void setName(const std::string& name);
- virtual void setEvent(Event& event);
- virtual void setData(const std::string& key, Data& event);
- virtual v8::Handle<v8::Value> getDataAsValue(Data& data);
+ virtual void setEvent(const Event& event);
virtual bool validate(const std::string& location, const std::string& schema);
@@ -33,6 +31,7 @@ public:
virtual void eval(const std::string& expr);
virtual void assign(const std::string& location, const std::string& expr);
+ virtual void assign(const std::string& location, const Data& data);
virtual std::string evalAsString(const std::string& expr);
virtual bool evalAsBool(const std::string& expr);
@@ -65,6 +64,7 @@ protected:
v8::Persistent<v8::ObjectTemplate> _eventTemplate;
v8::Handle<v8::Value> evalAsValue(const std::string& expr);
+ virtual v8::Handle<v8::Value> getDataAsValue(const Data& data);
};
diff --git a/src/uscxml/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/invoker/scxml/USCXMLInvoker.cpp
new file mode 100644
index 0000000..2f5a0b6
--- /dev/null
+++ b/src/uscxml/invoker/scxml/USCXMLInvoker.cpp
@@ -0,0 +1,48 @@
+#include "USCXMLInvoker.h"
+#include "uscxml/Interpreter.h"
+
+namespace uscxml {
+
+USCXMLInvoker::USCXMLInvoker() {
+
+}
+
+
+USCXMLInvoker::~USCXMLInvoker() {
+ delete _invokedInterpreter;
+};
+
+Invoker* USCXMLInvoker::create(Interpreter* interpreter) {
+ USCXMLInvoker* invoker = new USCXMLInvoker();
+ invoker->_parentInterpreter = interpreter;
+ return invoker;
+}
+
+Data USCXMLInvoker::getDataModelVariables() {
+ Data data;
+ return data;
+}
+
+void USCXMLInvoker::send(SendRequest& req) {
+
+}
+
+void USCXMLInvoker::cancel(const std::string sendId) {
+
+}
+
+void USCXMLInvoker::sendToParent(SendRequest& req) {
+ _parentInterpreter->receive(req);
+}
+
+void USCXMLInvoker::invoke(InvokeRequest& req) {
+ _invokedInterpreter = Interpreter::fromURI(req.src);
+ DataModel* dataModel = _invokedInterpreter->getDataModel();
+ if (dataModel != NULL) {
+
+ }
+ _invokedInterpreter->setInvoker(this);
+ _invokedInterpreter->start();
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/invoker/scxml/USCXMLInvoker.h b/src/uscxml/invoker/scxml/USCXMLInvoker.h
new file mode 100644
index 0000000..2fc9d25
--- /dev/null
+++ b/src/uscxml/invoker/scxml/USCXMLInvoker.h
@@ -0,0 +1,29 @@
+#ifndef USCXMLINVOKER_H_OQFA21IO
+#define USCXMLINVOKER_H_OQFA21IO
+
+#include "uscxml/Factory.h"
+
+namespace uscxml {
+
+class Interpreter;
+
+class USCXMLInvoker : public Invoker {
+public:
+ USCXMLInvoker();
+ virtual ~USCXMLInvoker();
+ virtual Invoker* create(Interpreter* interpreter);
+
+ virtual Data getDataModelVariables();
+ virtual void send(SendRequest& req);
+ virtual void cancel(const std::string sendId);
+ virtual void invoke(InvokeRequest& req);
+ virtual void sendToParent(SendRequest& req);
+
+protected:
+ Interpreter* _invokedInterpreter;
+ Interpreter* _parentInterpreter;
+};
+
+}
+
+#endif /* end of include guard: USCXMLINVOKER_H_OQFA21IO */
diff --git a/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
index c06c7e8..4daf179 100644
--- a/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
+++ b/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.cpp
@@ -14,8 +14,6 @@
#include <arpa/inet.h>
namespace uscxml {
-namespace io {
-namespace libevent {
// see http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor
@@ -23,7 +21,8 @@ EventIOProcessor::EventIOProcessor() {
}
EventIOProcessor::~EventIOProcessor() {
- _eventQueue.stop();
+ _asyncQueue.stop();
+ evdns_base_free(_dns, 1);
EventIOServer* httpServer = EventIOServer::getInstance();
httpServer->unregisterProcessor(this);
}
@@ -32,7 +31,7 @@ IOProcessor* EventIOProcessor::create(Interpreter* interpreter) {
EventIOProcessor* io = new EventIOProcessor();
io->_interpreter = interpreter;
- io->_dns = evdns_base_new(io->_eventQueue._eventLoop, 1);
+ io->_dns = evdns_base_new(io->_asyncQueue._eventLoop, 1);
assert(io->_dns);
assert(evdns_base_count_nameservers(io->_dns) > 0);
@@ -45,34 +44,30 @@ IOProcessor* EventIOProcessor::create(Interpreter* interpreter) {
}
void EventIOProcessor::start() {
- _eventQueue.start();
+ _asyncQueue.start();
}
+Data EventIOProcessor::getDataModelVariables() {
+ Data data;
+ assert(_url.length() > 0);
+ data.compound["location"] = Data(_url, Data::VERBATIM);
+ return data;
+}
+
+
void EventIOProcessor::send(SendRequest& req) {
// I cant figure out how to copy the reference into the struct :(
_sendData[req.sendid].req = req;
_sendData[req.sendid].ioProcessor = this;
- if (req.delayMs > 0) {
- LOG(INFO) << "Enqueing HTTP send request";
- _eventQueue.addEvent(req.sendid, EventIOProcessor::httpMakeSendReq, req.delayMs, &_sendData[req.sendid]);
- } else {
- LOG(INFO) << "Sending HTTP send request";
- EventIOProcessor::httpMakeSendReq(&_sendData[req.sendid], req.sendid);
- }
-}
-
-void EventIOProcessor::httpMakeSendReq(void* userdata, std::string eventName) {
- SendData* sendData = ((SendData*)userdata);
- EventIOProcessor* THIS = sendData->ioProcessor;
int err = 0;
char uriBuf[1024];
- struct evhttp_uri* targetURI = evhttp_uri_parse(sendData->req.target.c_str());
+ struct evhttp_uri* targetURI = evhttp_uri_parse(_sendData[req.sendid].req.target.c_str());
if (evhttp_uri_get_port(targetURI) == 0)
evhttp_uri_set_port(targetURI, 80);
const char* hostName = evhttp_uri_get_host(targetURI);
-
+
// use synchronous dns resolving for multicast dns
if(strlen(hostName) >= strlen(".local")) {
if(strcmp(hostName + strlen(hostName) - strlen(".local"), ".local") == 0) {
@@ -80,22 +75,22 @@ void EventIOProcessor::httpMakeSendReq(void* userdata, std::string eventName) {
}
}
evhttp_uri_join(targetURI, uriBuf, 1024);
-
+
LOG(INFO) << "URI for send request: " << uriBuf << std::endl;
std::stringstream ssEndPoint;
ssEndPoint << evhttp_uri_get_host(targetURI) << ":" << evhttp_uri_get_port(targetURI);
std::string endPoint = ssEndPoint.str();
-
+
std::stringstream ssLocalURI;
ssLocalURI << evhttp_uri_get_path(targetURI) << evhttp_uri_get_fragment(targetURI);
std::string localURI = ssLocalURI.str();
-
- if (THIS->_httpConnections.find(endPoint) == THIS->_httpConnections.end())
- THIS->_httpConnections[endPoint] = evhttp_connection_base_new(THIS->_eventQueue._eventLoop, THIS->_dns, evhttp_uri_get_host(targetURI), evhttp_uri_get_port(targetURI));
-
- struct evhttp_connection* httpConn = THIS->_httpConnections[endPoint];
- struct evhttp_request* httpReq = evhttp_request_new(EventIOProcessor::httpSendReqDone, userdata);
+
+ if (_httpConnections.find(endPoint) == _httpConnections.end())
+ _httpConnections[endPoint] = evhttp_connection_base_new(_asyncQueue._eventLoop, _dns, evhttp_uri_get_host(targetURI), evhttp_uri_get_port(targetURI));
+
+ struct evhttp_connection* httpConn = _httpConnections[endPoint];
+ struct evhttp_request* httpReq = evhttp_request_new(EventIOProcessor::httpSendReqDone, this);
#if 0
// event name
@@ -129,16 +124,16 @@ void EventIOProcessor::httpMakeSendReq(void* userdata, std::string eventName) {
if (sendData->req.content.size() > 0)
evbuffer_add(evhttp_request_get_output_buffer(httpReq), sendData->req.content.c_str(), sendData->req.content.size());
#endif
-
- evhttp_add_header(evhttp_request_get_output_headers(httpReq), "_scxmleventstruct", evhttp_encode_uri(sendData->req.toXMLString().c_str()));
-
- THIS->_httpRequests[sendData->req.sendid] = httpReq;
+ evhttp_add_header(evhttp_request_get_output_headers(httpReq), "_scxmleventstruct", evhttp_encode_uri(req.toXMLString().c_str()));
+
+
+ _httpRequests[req.sendid] = httpReq;
err = evhttp_make_request(httpConn,
httpReq,
EVHTTP_REQ_POST, localURI.c_str());
if (err) {
- LOG(ERROR) << "Could not make http request to " << sendData->req.target;
+ LOG(ERROR) << "Could not make http request to " << req.target;
}
}
@@ -206,13 +201,6 @@ void EventIOProcessor::httpSendReqDone(struct evhttp_request *req, void *cb_arg)
}
}
-void EventIOProcessor::invoke(InvokeRequest& req) {
-
-}
-void EventIOProcessor::cancel(const std::string sendId) {
-
-}
-
EventIOServer::EventIOServer(unsigned short port) {
_port = port;
_base = event_base_new();
@@ -281,7 +269,7 @@ void EventIOServer::registerProcessor(EventIOProcessor* processor) {
void EventIOServer::unregisterProcessor(EventIOProcessor* processor) {
EventIOServer* THIS = getInstance();
tthread::lock_guard<tthread::recursive_mutex> lock(THIS->_mutex);
- evhttp_del_cb(THIS->_http, processor->getURL().c_str());
+ evhttp_del_cb(THIS->_http, processor->_url.c_str());
}
void EventIOServer::start() {
@@ -356,6 +344,4 @@ void EventIOServer::determineAddress() {
#endif
}
-}
-}
} \ No newline at end of file
diff --git a/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h b/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h
index 7e8eaa9..c2e5b17 100644
--- a/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h
+++ b/src/uscxml/ioprocessor/basichttp/libevent/EventIOProcessor.h
@@ -10,8 +10,6 @@
#include <event2/http_struct.h>
namespace uscxml {
-namespace io {
-namespace libevent {
class EventIOServer;
@@ -27,10 +25,8 @@ public:
virtual IOProcessor* create(uscxml::Interpreter* interpreter);
virtual void send(uscxml::SendRequest& req);
- virtual void invoke(uscxml::InvokeRequest& req);
- virtual void cancel(const std::string sendId);
- std::string getURL() { return _url; }
+ Data getDataModelVariables();
void setURL(const std::string& url) { _url = url; }
void start();
@@ -45,7 +41,7 @@ protected:
std::string _url;
- uscxml::DelayedEventQueue _eventQueue;
+ uscxml::DelayedEventQueue _asyncQueue;
uscxml::Interpreter* _interpreter;
std::map<std::string, struct evhttp_connection*> _httpConnections;
std::map<std::string, struct evhttp_request*> _httpRequests;
@@ -90,7 +86,5 @@ private:
};
}
-}
-}
#endif /* end of include guard: EVENTIOPROCESSOR_H_2CUY93KU */ \ No newline at end of file