summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/swig/php/uscxml.i85
-rw-r--r--src/bindings/swig/php/uscxmlNativePHP.php116
-rw-r--r--src/uscxml/Factory.cpp4
-rw-r--r--src/uscxml/Factory.h8
-rw-r--r--src/uscxml/Interpreter.cpp51
-rw-r--r--src/uscxml/Interpreter.h5
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp48
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h7
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp111
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h2
-rw-r--r--src/uscxml/plugins/invoker/CMakeLists.txt20
-rw-r--r--src/uscxml/plugins/invoker/calendar/CalendarInvoker.cpp44
-rw-r--r--src/uscxml/plugins/invoker/calendar/CalendarInvoker.h40
-rw-r--r--src/uscxml/server/HTTPServer.cpp2
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);