diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/swig/php/uscxml.i | 85 | ||||
-rw-r--r-- | src/bindings/swig/php/uscxmlNativePHP.php | 116 | ||||
-rw-r--r-- | src/uscxml/Factory.cpp | 4 | ||||
-rw-r--r-- | src/uscxml/Factory.h | 8 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 51 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 5 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterDraft6.cpp | 4 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp | 48 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h | 7 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp | 111 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h | 2 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/calendar/CalendarInvoker.cpp | 44 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/calendar/CalendarInvoker.h | 40 | ||||
-rw-r--r-- | src/uscxml/server/HTTPServer.cpp | 2 |
15 files changed, 464 insertions, 83 deletions
diff --git a/src/bindings/swig/php/uscxml.i b/src/bindings/swig/php/uscxml.i index 0ab248e..f51309f 100644 --- a/src/bindings/swig/php/uscxml.i +++ b/src/bindings/swig/php/uscxml.i @@ -15,6 +15,10 @@ %ignore operator!=; %ignore operator<; %ignore operator=; +%ignore operator[]; +%ignore operator std::list<Data>; +%ignore operator std::string; +%ignore operator std::map<std::string,Data>; %template(StringMap) std::map<std::string, std::string>; %template(StringVector) std::vector<std::string>; @@ -74,6 +78,38 @@ void*** tsrm_ls; %ignore uscxml::Interpreter::getBasicConfiguration(); %extend uscxml::Interpreter { + bool isState(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isState(state); + } +} +%ignore uscxml::Interpreter::isState(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isPseudoState(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isPseudoState(state); + } +} +%ignore uscxml::Interpreter::isPseudoState(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isTransitionTarget(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isTransitionTarget(state); + } +} +%ignore uscxml::Interpreter::isTransitionTarget(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isTargetless(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isTargetless(state); + } +} +%ignore uscxml::Interpreter::isTargetless(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { bool isAtomic(const std::string stateId) { Arabica::DOM::Node<std::string> state = self->getState(stateId); return self->isAtomic(state); @@ -81,6 +117,55 @@ void*** tsrm_ls; } %ignore uscxml::Interpreter::isAtomic(Arabica::DOM::Node<std::string>); +%extend uscxml::Interpreter { + bool isInitial(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isInitial(state); + } +} +%ignore uscxml::Interpreter::isInitial(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isFinal(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isFinal(state); + } +} +%ignore uscxml::Interpreter::isFinal(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isHistory(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isHistory(state); + } +} +%ignore uscxml::Interpreter::isHistory(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isParallel(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isParallel(state); + } +} +%ignore uscxml::Interpreter::isParallel(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isCompound(const std::string stateId) { + Arabica::DOM::Node<std::string> state = self->getState(stateId); + return self->isCompound(state); + } +} +%ignore uscxml::Interpreter::isCompound(Arabica::DOM::Node<std::string>); + +%extend uscxml::Interpreter { + bool isDescendant(const std::string stateId1, const std::string stateId2) { + Arabica::DOM::Node<std::string> state1 = self->getState(stateId1); + Arabica::DOM::Node<std::string> state2 = self->getState(stateId2); + return self->isDescendant(state1, state2); + } +} +%ignore uscxml::Interpreter::isDescendant(Arabica::DOM::Node<std::string>); + //*********************************************** // Parse the header file to generate wrappers //*********************************************** diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php index 451fb1d..ef37b94 100644 --- a/src/bindings/swig/php/uscxmlNativePHP.php +++ b/src/bindings/swig/php/uscxmlNativePHP.php @@ -946,40 +946,8 @@ class Interpreter { return Interpreter_hasLegalConfiguration($this->_cPtr); } - static function isState($state) { - return Interpreter_isState($state); - } - - static function isPseudoState($state) { - return Interpreter_isPseudoState($state); - } - - static function isTransitionTarget($elem) { - return Interpreter_isTransitionTarget($elem); - } - - static function isTargetless($transition) { - return Interpreter_isTargetless($transition); - } - - static function isFinal($state) { - return Interpreter_isFinal($state); - } - - static function isHistory($state) { - return Interpreter_isHistory($state); - } - - static function isParallel($state) { - return Interpreter_isParallel($state); - } - - static function isCompound($state) { - return Interpreter_isCompound($state); - } - - static function isDescendant($s1,$s2) { - return Interpreter_isDescendant($s1,$s2); + function isLegalConfiguration($config) { + return Interpreter_isLegalConfiguration($this->_cPtr,$config); } static function tokenizeIdRefs($idRefs) { @@ -996,10 +964,6 @@ class Interpreter { return Interpreter_spaceNormalize($text); } - function isInitial($state) { - return Interpreter_isInitial($this->_cPtr,$state); - } - function getInitialStates($state=null) { switch (func_num_args()) { case 0: $r=Interpreter_getInitialStates($this->_cPtr); break; @@ -1072,6 +1036,38 @@ class Interpreter { return $r; } + function isState($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isState($this->_cPtr); break; + default: $r=Interpreter_isState($this->_cPtr,$stateId); + } + return $r; + } + + function isPseudoState($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isPseudoState($this->_cPtr); break; + default: $r=Interpreter_isPseudoState($this->_cPtr,$stateId); + } + return $r; + } + + function isTransitionTarget($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isTransitionTarget($this->_cPtr); break; + default: $r=Interpreter_isTransitionTarget($this->_cPtr,$stateId); + } + return $r; + } + + function isTargetless($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isTargetless($this->_cPtr); break; + default: $r=Interpreter_isTargetless($this->_cPtr,$stateId); + } + return $r; + } + function isAtomic($stateId=null) { switch (func_num_args()) { case 0: $r=Interpreter_isAtomic($this->_cPtr); break; @@ -1079,6 +1075,50 @@ class Interpreter { } return $r; } + + function isInitial($state_or_stateId) { + return Interpreter_isInitial($this->_cPtr,$state_or_stateId); + } + + function isFinal($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isFinal($this->_cPtr); break; + default: $r=Interpreter_isFinal($this->_cPtr,$stateId); + } + return $r; + } + + function isHistory($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isHistory($this->_cPtr); break; + default: $r=Interpreter_isHistory($this->_cPtr,$stateId); + } + return $r; + } + + function isParallel($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isParallel($this->_cPtr); break; + default: $r=Interpreter_isParallel($this->_cPtr,$stateId); + } + return $r; + } + + function isCompound($stateId=null) { + switch (func_num_args()) { + case 0: $r=Interpreter_isCompound($this->_cPtr); break; + default: $r=Interpreter_isCompound($this->_cPtr,$stateId); + } + return $r; + } + + function isDescendant($s2_or_stateId1,$stateId2=null) { + switch (func_num_args()) { + case 1: $r=Interpreter_isDescendant($this->_cPtr,$s2_or_stateId1); break; + default: $r=Interpreter_isDescendant($this->_cPtr,$s2_or_stateId1,$stateId2); + } + return $r; + } } class InterpreterMonitor { diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 7ac3b98..0d5f401 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -45,6 +45,10 @@ # include "uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h" # endif +# ifdef LIBICAL_FOUND +# include "uscxml/plugins/invoker/calendar/CalendarInvoker.h" +# endif + # ifdef V8_FOUND # include "uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h" # endif diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 9507d07..58002fe 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -14,6 +14,10 @@ namespace uscxml { +inline bool isnan(double x) { + return x != x; +} + // see http://stackoverflow.com/questions/228005/alternative-to-itoa-for-converting-integer-to-string-c template <typename T> std::string toStr(T tmp) { std::ostringstream out; @@ -30,9 +34,9 @@ template <typename T> T strTo(std::string tmp) { } inline bool isNumeric( const char* pszInput, int nNumberBase) { - std::string base = ".0123456789ABCDEF"; + std::string base = ".-0123456789ABCDEF"; std::string input = pszInput; - return (input.find_first_not_of(base.substr(0, nNumberBase + 1)) == std::string::npos); + return (input.find_first_not_of(base.substr(0, nNumberBase + 2)) == std::string::npos); } class InterpreterImpl; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 16fb503..4e33c8b 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -382,12 +382,12 @@ void InterpreterImpl::normalize(Arabica::DOM::Element<std::string>& scxml) { } void InterpreterImpl::receiveInternal(const Event& event) { - //std::cout << _name << " receiveInternal: " << event.name << std::endl; + std::cout << _name << " receiveInternal: " << event.name << std::endl; _internalQueue.push_back(event); } void InterpreterImpl::receive(const Event& event, bool toFront) { - //std::cout << _name << " receive: " << event.name << std::endl; + std::cout << _name << " receive: " << event.name << std::endl; if (toFront) { _externalQueue.push_front(event); } else { @@ -695,6 +695,8 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) { e.name = "error.execution"; receiveInternal(e); } + } else if (sendReq.content.length() > 0) { + sendReq.data = Data::fromJSON(sendReq.content); } } } catch (Event e) { @@ -822,7 +824,10 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) { e.name = "error.execution"; receiveInternal(e); } + } else if (invokeReq.content.length() > 0) { + invokeReq.data = Data::fromJSON(invokeReq.content); } + } } catch (Event e) { LOG(ERROR) << "Syntax error in send element content:" << std::endl << e << std::endl; @@ -1062,18 +1067,16 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "log")) { // --- LOG -------------------------- Arabica::DOM::Element<std::string> logElem = (Arabica::DOM::Element<std::string>)content; + if (logElem.hasAttribute("label")) + std::cout << logElem.getAttribute("label") << ": "; if (logElem.hasAttribute("expr")) { - if (logElem.hasAttribute("label")) - std::cout << logElem.getAttribute("label") << ": "; - if (_dataModel) { - try { - std::cout << _dataModel.evalAsString(logElem.getAttribute("expr")) << std::endl; - } - CATCH_AND_DISTRIBUTE("Syntax error in expr attribute of log element:") - } else { - if (logElem.hasAttribute("label")) - std::cout << std::endl; + try { + std::cout << _dataModel.evalAsString(logElem.getAttribute("expr")) << std::endl; } + CATCH_AND_DISTRIBUTE("Syntax error in expr attribute of log element:") + } else { + if (logElem.hasAttribute("label")) + std::cout << std::endl; } } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "assign")) { // --- ASSIGN -------------------------- @@ -1345,9 +1348,12 @@ Arabica::DOM::Node<std::string> InterpreterImpl::getState(const std::string& sta FOUND: if (target.size() > 0) { - assert(target.size() == 1); - _cachedStates[stateId] = target[0]; - return target[0]; + for (int i = 0; i < target.size(); i++) { + if (!isInEmbeddedDocument(target[i])) { + _cachedStates[stateId] = target[i]; + return target[i]; + } + } } // return the empty node return Arabica::DOM::Node<std::string>(); @@ -1549,6 +1555,21 @@ bool InterpreterImpl::isFinal(const Arabica::DOM::Node<std::string>& state) { return false; } +bool InterpreterImpl::isInEmbeddedDocument(const Node<std::string>& node) { + // a node is in an embedded document if there is a content element in its parents + Node<std::string> parent = node; + while(parent) { + if(parent == _scxml) { + return false; + } + if(boost::iequals(parent.getLocalName(), "content")) { + return true; + } + parent = parent.getParentNode(); + } + return false; +} + bool InterpreterImpl::isInitial(const Arabica::DOM::Node<std::string>& state) { if (!isState(state)) return false; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index d4ec389..56454db 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -215,11 +215,12 @@ public: 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 std::string spaceNormalize(const std::string& text); - bool isInitial(const Arabica::DOM::Node<std::string>& state); + bool isInEmbeddedDocument(const Arabica::DOM::Node<std::string>& node); + bool isInitial(const Arabica::DOM::Node<std::string>& state); Arabica::XPath::NodeSet<std::string> getInitialStates(Arabica::DOM::Node<std::string> state = Arabica::DOM::Node<std::string>()); static Arabica::XPath::NodeSet<std::string> getChildStates(const Arabica::DOM::Node<std::string>& state); static Arabica::DOM::Node<std::string> getParentState(const Arabica::DOM::Node<std::string>& element); diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index abea1ae..b3e76bd 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -278,7 +278,9 @@ void InterpreterDraft6::mainEventLoop() { } if (boost::iequals(autoForward, "true")) { try { - _invokers[invokeId].send(_currEvent); + // do not autoforward to invokers that send to #_parent from the SCXML IO Processor! + if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) + _invokers[invokeId].send(_currEvent); } catch(...) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId; } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 2143f5f..1326fb9 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -57,6 +57,7 @@ JSClassDefinition JSCDataModel::jsInClassDef = { 0, 0, "In", 0, 0, 0, 0, 0, 0, 0 JSClassDefinition JSCDataModel::jsPrintClassDef = { 0, 0, "print", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsPrint, 0, 0, 0 }; JSClassDefinition JSCDataModel::jsIOProcessorsClassDef = { 0, 0, "ioProcessors", 0, 0, 0, 0, 0, jsIOProcessorHasProp, jsIOProcessorGetProp, 0, 0, jsIOProcessorListProps, 0, 0, 0, 0 }; +JSClassDefinition JSCDataModel::jsInvokersClassDef = { 0, 0, "invokers", 0, 0, 0, 0, 0, jsInvokerHasProp, jsInvokerGetProp, 0, 0, jsInvokerListProps, 0, 0, 0, 0 }; boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr<JSCDataModel> dm = boost::shared_ptr<JSCDataModel>(new JSCDataModel()); @@ -81,6 +82,12 @@ boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpret JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL); JSStringRelease(inName); + JSClassRef jsInvokerClassRef = JSClassCreate(&jsInvokersClassDef); + JSObjectRef jsInvoker = JSObjectMake(dm->_ctx, jsInvokerClassRef, dm.get()); + JSStringRef invokerName = JSStringCreateWithUTF8CString("_invokers"); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeNone, NULL); + JSStringRelease(invokerName); + JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef); JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get()); JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors"); @@ -109,7 +116,6 @@ boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpret JSObjectSetProperty(dm->_ctx, globalObject, JSStringCreateWithUTF8CString("document"), documentObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); } - dm->eval(Element<std::string>(), "_invokers = {};"); dm->eval(Element<std::string>(), "_x = {};"); return dm; @@ -576,4 +582,44 @@ void JSCDataModel::jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, } } + +bool JSCDataModel::jsInvokerHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map<std::string, Invoker> invokers = INSTANCE->_interpreter->getInvokers(); + + size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char buffer[maxSize]; + JSStringGetUTF8CString(propertyName, buffer, maxSize); + std::string prop(buffer); + + return invokers.find(prop) != invokers.end(); +} + +JSValueRef JSCDataModel::jsInvokerGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map<std::string, Invoker> invokers = INSTANCE->_interpreter->getInvokers(); + + size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char buffer[maxSize]; + JSStringGetUTF8CString(propertyName, buffer, maxSize); + std::string prop(buffer); + + if (invokers.find(prop) != invokers.end()) { + return INSTANCE->getDataAsValue(invokers.find(prop)->second.getDataModelVariables()); + } + return JSValueMakeUndefined(ctx); +} + +void JSCDataModel::jsInvokerListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map<std::string, Invoker> invokers = INSTANCE->_interpreter->getInvokers(); + + std::map<std::string, Invoker>::const_iterator invokerIter = invokers.begin(); + while(invokerIter != invokers.end()) { + JSStringRef invokeName = JSStringCreateWithUTF8CString(invokerIter->first.c_str()); + JSPropertyNameAccumulatorAddName(propertyNames, invokeName); + invokerIter++; + } +} + }
\ No newline at end of file diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h index 9f254e4..9e70a8f 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h @@ -71,7 +71,12 @@ protected: static bool jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); static JSValueRef jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); static void jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); - + + static JSClassDefinition jsInvokersClassDef; + static bool jsInvokerHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + static JSValueRef jsInvokerGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + static void jsInvokerListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); + JSValueRef getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc); JSValueRef getDataAsValue(const Data& data); Data getValueAsData(const JSValueRef value); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 2f43c73..462b661 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -8,6 +8,21 @@ #include <Pluma/Connector.hpp> #endif +#define SET_PL_CONTEXT \ +_dmPtr = this; + +#define PL_MODULE \ +_interpreter.getSessionId().c_str() \ + +#define UNSET_PL_ENGINE(dm) \ +PL_set_engine(NULL, NULL); + +#define SET_PL_ENGINE(dm) \ +assert(_swiEngines.find(dm) != _swiEngines.end()); \ +int rc = PL_set_engine(_swiEngines[dm], NULL); \ +assert(rc == PL_ENGINE_SET); \ +_dmPtr = dm; + namespace uscxml { using namespace Arabica::XPath; @@ -21,43 +36,90 @@ bool connect(pluma::Host& host) { } #endif +// SWI prolog does not support passing user data +static SWIDataModel* _dmPtr; +static std::map<SWIDataModel*, PL_engine_t> _swiEngines; + SWIDataModel::SWIDataModel() { } -// SWI prolog does not support passing user data -static InterpreterImpl* _swiInterpreterPtr; - +SWIDataModel::~SWIDataModel() { + if (_swiEngines.find(this) != _swiEngines.end()) { + PL_destroy_engine(_swiEngines[this]); + _swiEngines.erase(this); + } +} + boost::shared_ptr<DataModelImpl> SWIDataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr<SWIDataModel> dm = boost::shared_ptr<SWIDataModel>(new SWIDataModel()); dm->_interpreter = interpreter; - // this is most unfortunate! - _swiInterpreterPtr = interpreter; const char* swibin = getenv("SWI_BINARY"); if (swibin == NULL) swibin = SWI_BINARY; const char* quiet = "--quiet"; + int argc = 2; static char * av[] = { (char*)swibin, (char*)quiet, - // "-s", - // "/Users/sradomski/Documents/TK/Code/pl-devel/demo/likes.pl", NULL }; - if(!PL_initialise(2,av)) { - LOG(ERROR) << "Error intializing prolog engine"; - PL_halt(1); - return boost::shared_ptr<DataModelImpl>(); - } - // load SWI XML parser - PlCall("use_module", PlCompound("library", PlTerm("sgml"))); + PL_engine_t engine; - // load json parser - PlCall("use_module", PlCompound("library", PlTerm("http/json"))); - PlCall("use_module", PlCompound("library", PlTerm("http/json_convert"))); + if (!PL_is_initialised(NULL, NULL)) { + if(!PL_initialise(argc,av)) { + LOG(ERROR) << "Error intializing prolog engine"; + PL_halt(1); + return boost::shared_ptr<DataModelImpl>(); + } else { + LOG(WARNING) << "Instantiating more than one SWI prolog datamodel will lead to weird effects as I cannot seperate the environments"; + } + + PL_set_engine(PL_ENGINE_CURRENT, &engine); + + // load SWI XML parser + try { + PlCall("use_module", PlCompound("library", PlTerm("sgml"))); + } catch (PlException plex) { + + LOG(ERROR) << "Cannot load prolog sgml module - make sure you have it installed in your prolog runtime: " << (char*)plex; + throw plex; + } + + // load json parser + try { + PlCall("use_module", PlCompound("library", PlTerm("http/json"))); + PlCall("use_module", PlCompound("library", PlTerm("http/json_convert"))); + } catch (PlException plex) { + LOG(ERROR) << "Cannot load prolog json module or json_convert - make sure you have it installed in your prolog runtime: " << (char*)plex; + throw plex; + } + } else { + engine = PL_create_engine(NULL); + } + + assert(engine); + _swiEngines[dm.get()] = engine; + _dmPtr = dm.get(); + + int rc = PL_set_engine(engine, NULL); + assert(rc == PL_ENGINE_SET); + + _plModule = boost::replace_all_copy(interpreter->getSessionId(), "-", ""); + boost::replace_all(_plModule, "0", "g"); + boost::replace_all(_plModule, "1", "h"); + boost::replace_all(_plModule, "2", "i"); + boost::replace_all(_plModule, "3", "j"); + boost::replace_all(_plModule, "4", "k"); + boost::replace_all(_plModule, "5", "l"); + boost::replace_all(_plModule, "6", "m"); + boost::replace_all(_plModule, "7", "n"); + boost::replace_all(_plModule, "8", "o"); + boost::replace_all(_plModule, "9", "p"); + // use atoms for double quoted PlCall("set_prolog_flag(double_quotes,atom)."); @@ -89,7 +151,7 @@ boost::shared_ptr<DataModelImpl> SWIDataModel::create(InterpreterImpl* interpret foreign_t SWIDataModel::inPredicate(term_t a0, int arity, void* context) { char *s; if ( PL_get_atom_chars(a0, &s) ) { - NodeSet<std::string> config = _swiInterpreterPtr->getConfiguration(); + NodeSet<std::string> config = _dmPtr->_interpreter->getConfiguration(); for (int i = 0; i < config.size(); i++) { if (HAS_ATTR(config[i], "id") && strcmp(ATTR(config[i], "id").c_str(), s) == 0) { return TRUE; @@ -113,9 +175,6 @@ void SWIDataModel::setName(const std::string& name) { _name = name; } -SWIDataModel::~SWIDataModel() { -} - void SWIDataModel::pushContext() { // std::cout << "SWIDataModel::pushContext" << std::endl; } @@ -129,6 +188,7 @@ void SWIDataModel::initialize() { } void SWIDataModel::setEvent(const Event& event) { + SET_PL_CONTEXT; // remove old event try { PlCall("retractall(event(_))"); @@ -208,17 +268,20 @@ void SWIDataModel::setEvent(const Event& event) { } Data SWIDataModel::getStringAsData(const std::string& content) { + SET_PL_CONTEXT // std::cout << "SWIDataModel::getStringAsData" << std::endl; Data data; return data; } bool SWIDataModel::validate(const std::string& location, const std::string& schema) { + SET_PL_CONTEXT // std::cout << "SWIDataModel::validate" << std::endl; return true; } uint32_t SWIDataModel::getLength(const std::string& expr) { + SET_PL_CONTEXT PlCompound compound(expr.c_str()); PlTermv termv(compound.arity()); for (int i = 0; i < compound.arity(); i++) { @@ -235,6 +298,7 @@ void SWIDataModel::setForeach(const std::string& item, const std::string& array, const std::string& index, uint32_t iteration) { + SET_PL_CONTEXT PlCompound compound(array.c_str()); PlCompound orig(array.c_str()); PlTermv termv(compound.arity()); @@ -262,6 +326,7 @@ void SWIDataModel::setForeach(const std::string& item, } void SWIDataModel::eval(const Element<std::string>& scriptElem, const std::string& expr) { + SET_PL_CONTEXT if (scriptElem && HAS_ATTR(scriptElem, "type") && boost::iequals(ATTR(scriptElem, "type"), "query")) { evalAsBool(expr); } else { @@ -271,6 +336,7 @@ void SWIDataModel::eval(const Element<std::string>& scriptElem, const std::strin } bool SWIDataModel::evalAsBool(const std::string& expr) { + SET_PL_CONTEXT try { PlCompound compound(expr.c_str()); PlTermv termv(compound.arity()); @@ -285,6 +351,7 @@ bool SWIDataModel::evalAsBool(const std::string& expr) { } std::string SWIDataModel::evalAsString(const std::string& expr) { + SET_PL_CONTEXT PlCompound orig(expr.c_str()); // keep the original to find variables PlCompound compound(expr.c_str()); if (strlen(compound.name())) { @@ -316,6 +383,7 @@ std::string SWIDataModel::evalAsString(const std::string& expr) { // this is similar to http://etalis.googlecode.com/svn/eEtalis/src/term.c std::map<std::string, PlTerm> SWIDataModel::resolveAtoms(PlTerm& term, PlTerm& orig) { + SET_PL_CONTEXT std::map<std::string, PlTerm> atoms; switch (orig.type()) { case PL_VARIABLE: { @@ -343,6 +411,7 @@ std::map<std::string, PlTerm> SWIDataModel::resolveAtoms(PlTerm& term, PlTerm& o void SWIDataModel::assign(const Element<std::string>& assignElem, const Document<std::string>& doc, const std::string& content) { + SET_PL_CONTEXT std::string expr = content; std::string predicate; if (HAS_ATTR(assignElem, "expr")) { diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index f391139..b4532cf 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -66,8 +66,8 @@ protected: std::map<std::string, PlTerm> resolveAtoms(PlTerm& term, PlTerm& orig); Event _event; - PlEngine* _plEngine; + std::string _plModule; std::string _name; std::string _sessionId; }; diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt index e836275..67d356a 100644 --- a/src/uscxml/plugins/invoker/CMakeLists.txt +++ b/src/uscxml/plugins/invoker/CMakeLists.txt @@ -127,6 +127,26 @@ if (FFMPEG_FOUND) endif() +# calendar invoker + +if (LIBICAL_FOUND) + file(GLOB_RECURSE CALENDAR_INVOKER + calendar/*.cpp + calendar/*.h + ) + source_group("Invoker\\caledar" FILES ${CALENDAR_INVOKER}) + if (BUILD_AS_PLUGINS) + add_library( + invoker_calendar SHARED + ${CALENDAR_INVOKER}) + target_link_libraries(invoker_calendar uscxml) + set_target_properties(invoker_calendar PROPERTIES FOLDER "Plugin Invoker") + else() + list (APPEND USCXML_FILES ${CALENDAR_INVOKER}) + endif() +endif() + + # UMUNDO invoker if (UMUNDO_FOUND) diff --git a/src/uscxml/plugins/invoker/calendar/CalendarInvoker.cpp b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.cpp new file mode 100644 index 0000000..7ea3fc3 --- /dev/null +++ b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.cpp @@ -0,0 +1,44 @@ +#include "CalendarInvoker.h" +#include <glog/logging.h> + +#ifdef BUILD_AS_PLUGINS +#include <Pluma/Connector.hpp> +#endif + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool connect(pluma::Host& host) { + host.add( new CalendarInvokerProvider() ); + return true; +} +#endif + +CalendarInvoker::CalendarInvoker() { +} + +CalendarInvoker::~CalendarInvoker() { +}; + +boost::shared_ptr<InvokerImpl> CalendarInvoker::create(InterpreterImpl* interpreter) { + boost::shared_ptr<CalendarInvoker> invoker = boost::shared_ptr<CalendarInvoker>(new CalendarInvoker()); + invoker->_interpreter = interpreter; + return invoker; +} + +Data CalendarInvoker::getDataModelVariables() { + Data data; + return data; +} + +void CalendarInvoker::send(const SendRequest& req) { +} + +void CalendarInvoker::cancel(const std::string sendId) { +} + +void CalendarInvoker::invoke(const InvokeRequest& req) { +} + +}
\ No newline at end of file diff --git a/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h new file mode 100644 index 0000000..45dc8d0 --- /dev/null +++ b/src/uscxml/plugins/invoker/calendar/CalendarInvoker.h @@ -0,0 +1,40 @@ +#ifndef CALENDARINVOKER_H_W09J90F0 +#define CALENDARINVOKER_H_W09J90F0 + +#include <uscxml/Interpreter.h> + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class CalendarInvoker : public InvokerImpl { +public: + CalendarInvoker(); + virtual ~CalendarInvoker(); + virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter); + + virtual std::set<std::string> getNames() { + std::set<std::string> names; + names.insert("calendar"); + names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#calendar"); + return names; + } + + virtual Data getDataModelVariables(); + virtual void send(const SendRequest& req); + virtual void cancel(const std::string sendId); + virtual void invoke(const InvokeRequest& req); + +protected: +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(CalendarInvoker, InvokerImpl); +#endif + +} + + +#endif /* end of include guard: CALENDARINVOKER_H_W09J90F0 */ diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index f4b1a57..7e1a858 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -346,7 +346,7 @@ bool HTTPServer::registerServlet(const std::string& path, HTTPServlet* servlet) INSTANCE->_servlets[suffixedPath] = servlet; - LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl; +// LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl; // register callback evhttp_set_cb(INSTANCE->_http, ("/" + suffixedPath).c_str(), HTTPServer::httpRecvReqCallback, servlet); |