summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/src/uscxml/ExtendedLuaDataModel.h15
-rw-r--r--src/bindings/swig/wrapped/WrappedDataModel.h4
-rw-r--r--src/uscxml/plugins/DataModelImpl.h26
-rw-r--r--src/uscxml/plugins/datamodel/c89/C89DataModel.cpp9
-rw-r--r--src/uscxml/plugins/datamodel/c89/C89DataModel.h1
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp38
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h1
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp33
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h1
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp45
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.h1
-rw-r--r--src/uscxml/plugins/datamodel/null/NullDataModel.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/null/NullDataModel.h1
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp21
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.h1
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp7
-rw-r--r--test/issues/test-issue121.child29
-rw-r--r--test/issues/test-issue121.scxml21
18 files changed, 183 insertions, 75 deletions
diff --git a/contrib/src/uscxml/ExtendedLuaDataModel.h b/contrib/src/uscxml/ExtendedLuaDataModel.h
index 652a2a0..44e4b5d 100644
--- a/contrib/src/uscxml/ExtendedLuaDataModel.h
+++ b/contrib/src/uscxml/ExtendedLuaDataModel.h
@@ -27,15 +27,18 @@ public:
ExtendedLuaDataModel() {};
std::shared_ptr<DataModelImpl> create(uscxml::DataModelCallbacks* callbacks) {
-
std::shared_ptr<ExtendedLuaDataModel> dm(new ExtendedLuaDataModel());
-// dm->LuaDataModel::init(callbacks);
-
- lua_pushcfunction(dm->_luaState, GetSomeResult);
- lua_setglobal(dm->_luaState, "GetSomeResult");
-
+ dm->_callbacks = callbacks;
+ dm->setup();
return dm;
}
+
+ void setup() {
+ uscxml::LuaDataModel::setup();
+ lua_pushcfunction(_luaState, GetSomeResult);
+ lua_setglobal(_luaState, "GetSomeResult");
+
+ }
static int GetSomeResult(lua_State * L) {
LOGD(uscxml::USCXML_INFO) << "Calling GetSomeResult!" << std::endl;
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h
index e0bd422..d920dc6 100644
--- a/src/bindings/swig/wrapped/WrappedDataModel.h
+++ b/src/bindings/swig/wrapped/WrappedDataModel.h
@@ -40,9 +40,13 @@ public:
virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks) {
std::shared_ptr<WrappedDataModel> dm(create());
dm->callbacks = callbacks;
+ dm->setup();
return dm;
}
+ virtual void setup() {
+ }
+
virtual std::list<std::string> getNames() {
return std::list<std::string>();
}
diff --git a/src/uscxml/plugins/DataModelImpl.h b/src/uscxml/plugins/DataModelImpl.h
index 8326871..a804ea3 100644
--- a/src/uscxml/plugins/DataModelImpl.h
+++ b/src/uscxml/plugins/DataModelImpl.h
@@ -80,15 +80,35 @@ public:
/**
* The Factory wants to instantiate a new instance.
- * This function will have to initialize the object. The actual constructor
- * is called from within here. The only one who calls the constructor directly
- * is the Factory for the prototype object.
+ * This functions calls the constructor and returns a shared_ptr to the respective
+ * object. Note that this function can not contain actual initialization code as we
+ * could no longer inherit the class. Therefore, this function calls the setup()
+ * method which can be extended by an child class to actually get the object ready.
+ * The only other time that the constructor is called directly is for the prototype
+ * object in the Factory.
*
* @param callbacks The callbacks available to the datamodel
* @return A shared pointer with an initialized instance
*/
virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks) = 0;
+protected:
+ /**
+ * This function will initialize the object.
+ * We cannot initialize an instance of a datamodel from the default constructors as
+ * it would be called for the prototype objects in the factory as well. And we can
+ * neither initialize an instance in create() as it is invoke in the prototype and
+ * cannot be overridden by an inheriting class. Thus, we have to call this setup()
+ * function on the instance created by create() so that inheriting classes won't have
+ * to copy all the code in create() and can rely on the base class' initialization
+ * of the datamodel runtime environment and merely extend it.
+ *
+ * @TODO: We may want to introduce two-stage constructors for other prototype types in
+ * the factory as well.
+ */
+ virtual void setup() = 0;
+
+public:
/**
* Return a list of names to be matched by the `datamodel` attribute in SCXML.
*/
diff --git a/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp b/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp
index 24b9bb1..699d946 100644
--- a/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp
@@ -34,11 +34,16 @@ C89DataModel::C89DataModel() {
std::shared_ptr<DataModelImpl> C89DataModel::create(DataModelCallbacks* callbacks) {
std::shared_ptr<C89DataModel> dm(new C89DataModel());
- PicocInitialise(&dm->_pc, PICOC_STACK_SIZE);
- PicocIncludeAllSystemHeaders(&dm->_pc);
+ dm->setup();
return dm;
}
+C89DataModel::setup() {
+ PicocInitialise(&_pc, PICOC_STACK_SIZE);
+ PicocIncludeAllSystemHeaders(&_pc);
+
+}
+
C89DataModel::~C89DataModel() {
PicocCleanup(&_pc);
}
diff --git a/src/uscxml/plugins/datamodel/c89/C89DataModel.h b/src/uscxml/plugins/datamodel/c89/C89DataModel.h
index 4e9eef0..526d06c 100644
--- a/src/uscxml/plugins/datamodel/c89/C89DataModel.h
+++ b/src/uscxml/plugins/datamodel/c89/C89DataModel.h
@@ -86,6 +86,7 @@ public:
virtual std::string andExpressions(std::list<std::string>);
protected:
+ virtual void setup();
Picoc _pc;
};
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 1358f8b..124da6e 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -246,9 +246,13 @@ JSValueRef JSCNodeListGetPropertyCallback(JSContextRef context, JSObjectRef obje
std::shared_ptr<DataModelImpl> JSCDataModel::create(DataModelCallbacks* callbacks) {
std::shared_ptr<JSCDataModel> dm(new JSCDataModel());
-
- dm->_ctx = JSGlobalContextCreate(NULL);
dm->_callbacks = callbacks;
+ dm->setup();
+ return dm;
+}
+
+void JSCDataModel::setup() {
+ _ctx = JSGlobalContextCreate(NULL);
#ifndef NO_XERCESC
JSObjectRef exports;
@@ -260,50 +264,48 @@ std::shared_ptr<DataModelImpl> JSCDataModel::create(DataModelCallbacks* callback
// not thread safe!
{
std::lock_guard<std::mutex> lock(_initMutex);
- JSCDOM_initialize(dm->_ctx, &exports);
+ JSCDOM_initialize(_ctx, &exports);
}
#endif
// introduce global functions as objects for private data
JSClassRef jsInClassRef = JSClassCreate(&jsInClassDef);
- JSObjectRef jsIn = JSObjectMake(dm->_ctx, jsInClassRef, dm.get());
+ JSObjectRef jsIn = JSObjectMake(_ctx, jsInClassRef, this);
JSStringRef inName = JSStringCreateWithUTF8CString("In");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), inName, jsIn, kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), inName, jsIn, kJSPropertyAttributeNone, NULL);
JSStringRelease(inName);
JSClassRef jsPrintClassRef = JSClassCreate(&jsPrintClassDef);
- JSObjectRef jsPrint = JSObjectMake(dm->_ctx, jsPrintClassRef, dm.get());
+ JSObjectRef jsPrint = JSObjectMake(_ctx, jsPrintClassRef, this);
JSStringRef printName = JSStringCreateWithUTF8CString("print");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL);
JSStringRelease(printName);
JSClassRef jsInvokerClassRef = JSClassCreate(&jsInvokersClassDef);
- JSObjectRef jsInvoker = JSObjectMake(dm->_ctx, jsInvokerClassRef, dm.get());
+ JSObjectRef jsInvoker = JSObjectMake(_ctx, jsInvokerClassRef, this);
JSStringRef invokerName = JSStringCreateWithUTF8CString("_invokers");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), invokerName, jsInvoker, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(invokerName);
JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef);
- JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get());
+ JSObjectRef jsIOProc = JSObjectMake(_ctx, jsIOProcClassRef, this);
JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors");
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), ioProcName, jsIOProc, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(ioProcName);
JSStringRef nameName = JSStringCreateWithUTF8CString("_name");
- JSStringRef name = JSStringCreateWithUTF8CString(dm->_callbacks->getName().c_str());
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ JSStringRef name = JSStringCreateWithUTF8CString(_callbacks->getName().c_str());
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), nameName, JSValueMakeString(_ctx, name), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(nameName);
JSStringRelease(name);
JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid");
- JSStringRef sessionId = JSStringCreateWithUTF8CString(dm->_callbacks->getSessionId().c_str());
- JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ JSStringRef sessionId = JSStringCreateWithUTF8CString(_callbacks->getSessionId().c_str());
+ JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), sessionIdName, JSValueMakeString(_ctx, sessionId), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
JSStringRelease(sessionIdName);
JSStringRelease(sessionId);
- dm->evalAsValue("_x = {};");
-
- return dm;
+ evalAsValue("_x = {};");
}
void JSCDataModel::setEvent(const Event& event) {
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
index 5a0e830..977385c 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
@@ -89,6 +89,7 @@ public:
const std::map<std::string, std::string>& attr = std::map<std::string, std::string>());
protected:
+ virtual void setup();
static JSClassDefinition jsInClassDef;
static JSValueRef jsIn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index e3820c2..a7942a1 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -176,35 +176,39 @@ void V8NodeListIndexedPropertyHandler(uint32_t index, const v8::PropertyCallback
std::shared_ptr<DataModelImpl> V8DataModel::create(DataModelCallbacks* callbacks) {
std::shared_ptr<V8DataModel> dm(new V8DataModel());
dm->_callbacks = callbacks;
+ dm->setup();
+ return dm;
+}
+void V8DataModel::setup() {
// TODO: we cannot use one isolate per thread as swig's type will be unknown :(
// We could register them by hand and avoid the _export_ globals in swig?
- if (dm->_isolate == NULL) {
- dm->_isolate = v8::Isolate::New();
+ if (_isolate == NULL) {
+ _isolate = v8::Isolate::New();
}
- v8::Locker locker(dm->_isolate);
- v8::Isolate::Scope isoScope(dm->_isolate);
+ v8::Locker locker(_isolate);
+ v8::Isolate::Scope isoScope(_isolate);
// Create a handle scope to hold the temporary references.
- v8::HandleScope scope(dm->_isolate);
+ v8::HandleScope scope(_isolate);
// Create a template for the global object where we set the built-in global functions.
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// some free functions
global->Set(v8::String::NewSymbol("print"),
- v8::FunctionTemplate::New(dm->_isolate, jsPrint,v8::External::New(reinterpret_cast<void*>(dm.get()))));
+ v8::FunctionTemplate::New(_isolate, jsPrint,v8::External::New(reinterpret_cast<void*>(this))));
global->Set(v8::String::NewSymbol("In"),
- v8::FunctionTemplate::New(dm->_isolate, jsIn, v8::External::New(reinterpret_cast<void*>(dm.get()))));
+ v8::FunctionTemplate::New(_isolate, jsIn, v8::External::New(reinterpret_cast<void*>(this))));
- v8::Local<v8::Context> context = v8::Context::New(dm->_isolate, NULL, global);
+ v8::Local<v8::Context> context = v8::Context::New(_isolate, NULL, global);
- dm->_context.Reset(dm->_isolate, context);
+ _context.Reset(_isolate, context);
// Enter the new context so all the following operations take place within it.
v8::Context::Scope contextScope(context);
- assert(dm->_isolate->GetCurrentContext() == context);
+ assert(_isolate->GetCurrentContext() == context);
#ifndef NO_XERCESC
@@ -236,11 +240,11 @@ std::shared_ptr<DataModelImpl> V8DataModel::create(DataModelCallbacks* callbacks
context->Global()->SetAccessor(v8::String::NewSymbol("_ioprocessors"),
V8DataModel::getIOProcessors,
V8DataModel::setWithException,
- v8::External::New(reinterpret_cast<void*>(dm.get())));
+ v8::External::New(reinterpret_cast<void*>(this)));
context->Global()->SetAccessor(v8::String::NewSymbol("_invokers"),
V8DataModel::getInvokers,
V8DataModel::setWithException,
- v8::External::New(reinterpret_cast<void*>(dm.get())));
+ v8::External::New(reinterpret_cast<void*>(this)));
// v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value> > persistent(_isolate, context);
@@ -252,7 +256,7 @@ std::shared_ptr<DataModelImpl> V8DataModel::create(DataModelCallbacks* callbacks
V8Document::V8DocumentPrivate* privData = new V8Document::V8DocumentPrivate();
privData->nativeObj = new Document<std::string>(interpreter->getDocument());
- privData->dom = dm->_dom;
+ privData->dom = _dom;
docObj->SetInternalField(0, V8DOM::toExternal(privData));
context->Global()->Set(v8::String::New("document"), docObj);
@@ -273,10 +277,9 @@ std::shared_ptr<DataModelImpl> V8DataModel::create(DataModelCallbacks* callbacks
// instantiate objects - we have to have a context for that!
- dm->eval(Element<std::string>(), "_x = {};");
+ eval(Element<std::string>(), "_x = {};");
#endif
- return dm;
}
void V8DataModel::getAttribute(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
index 00a871b..e286c56 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
@@ -82,6 +82,7 @@ public:
const std::map<std::string, std::string>& attr = std::map<std::string, std::string>());
protected:
+ virtual void setup();
static void jsExtension(const v8::FunctionCallbackInfo<v8::Value>& info);
static void jsIn(const v8::FunctionCallbackInfo<v8::Value>& info);
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
index 2071d39..94d2467 100644
--- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
@@ -208,13 +208,17 @@ int LuaDataModel::luaInFunction(lua_State * l) {
std::shared_ptr<DataModelImpl> LuaDataModel::create(DataModelCallbacks* callbacks) {
std::shared_ptr<LuaDataModel> dm(new LuaDataModel());
-
dm->_callbacks = callbacks;
- dm->_luaState = luaL_newstate();
- luaL_openlibs(dm->_luaState);
+ dm->setup();
+ return dm;
+}
+
+void LuaDataModel::setup() {
+ _luaState = luaL_newstate();
+ luaL_openlibs(_luaState);
try {
- const luabridge::LuaRef& requireFunc = luabridge::getGlobal(dm->_luaState, "require");
+ const luabridge::LuaRef& requireFunc = luabridge::getGlobal(_luaState, "require");
if (requireFunc.isFunction()) {
const luabridge::LuaRef& resultLxp = requireFunc("lxp");
const luabridge::LuaRef& resultLxpLOM = requireFunc("lxp.lom");
@@ -222,43 +226,42 @@ std::shared_ptr<DataModelImpl> LuaDataModel::create(DataModelCallbacks* callback
// MSVC compiler bug with implicit cast operators, see comments in LuaRef class
if ((bool)resultLxp && (bool)resultLxpLOM) {
_luaHasXMLParser = true;
- luabridge::setGlobal(dm->_luaState, resultLxp, "lxp");
- luabridge::setGlobal(dm->_luaState, resultLxpLOM, "lxp.lom");
+ luabridge::setGlobal(_luaState, resultLxp, "lxp");
+ luabridge::setGlobal(_luaState, resultLxpLOM, "lxp.lom");
}
}
} catch (luabridge::LuaException e) {
- LOG(dm->_callbacks->getLogger(), USCXML_INFO) << e.what() << std::endl;
+ LOG(_callbacks->getLogger(), USCXML_INFO) << e.what() << std::endl;
}
- luabridge::getGlobalNamespace(dm->_luaState).beginClass<LuaDataModel>("DataModel").endClass();
- luabridge::setGlobal(dm->_luaState, dm.get(), "__datamodel");
+ luabridge::getGlobalNamespace(_luaState).beginClass<LuaDataModel>("DataModel").endClass();
+ luabridge::setGlobal(_luaState, this, "__datamodel");
- luabridge::getGlobalNamespace(dm->_luaState).addCFunction("In", luaInFunction);
+ luabridge::getGlobalNamespace(_luaState).addCFunction("In", luaInFunction);
- luabridge::LuaRef ioProcTable = luabridge::newTable(dm->_luaState);
- std::map<std::string, IOProcessor> ioProcs = dm->_callbacks->getIOProcessors();
+ luabridge::LuaRef ioProcTable = luabridge::newTable(_luaState);
+ std::map<std::string, IOProcessor> ioProcs = _callbacks->getIOProcessors();
std::map<std::string, IOProcessor>::const_iterator ioProcIter = ioProcs.begin();
while(ioProcIter != ioProcs.end()) {
Data ioProcData = ioProcIter->second.getDataModelVariables();
- ioProcTable[ioProcIter->first] = getDataAsLua(dm->_luaState, ioProcData);
+ ioProcTable[ioProcIter->first] = getDataAsLua(_luaState, ioProcData);
ioProcIter++;
}
- luabridge::setGlobal(dm->_luaState, ioProcTable, "_ioprocessors");
+ luabridge::setGlobal(_luaState, ioProcTable, "_ioprocessors");
- luabridge::LuaRef invTable = luabridge::newTable(dm->_luaState);
- std::map<std::string, Invoker> invokers = dm->_callbacks->getInvokers();
+ luabridge::LuaRef invTable = luabridge::newTable(_luaState);
+ std::map<std::string, Invoker> invokers = _callbacks->getInvokers();
std::map<std::string, Invoker>::const_iterator invIter = invokers.begin();
while(invIter != invokers.end()) {
Data invData = invIter->second.getDataModelVariables();
- invTable[invIter->first] = getDataAsLua(dm->_luaState, invData);
+ invTable[invIter->first] = getDataAsLua(_luaState, invData);
invIter++;
}
- luabridge::setGlobal(dm->_luaState, invTable, "_invokers");
+ luabridge::setGlobal(_luaState, invTable, "_invokers");
- luabridge::setGlobal(dm->_luaState, dm->_callbacks->getName(), "_name");
- luabridge::setGlobal(dm->_luaState, dm->_callbacks->getSessionId(), "_sessionid");
+ luabridge::setGlobal(_luaState, _callbacks->getName(), "_name");
+ luabridge::setGlobal(_luaState, _callbacks->getSessionId(), "_sessionid");
- return dm;
}
LuaDataModel::~LuaDataModel() {
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.h b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
index c64656a..a43b959 100644
--- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
@@ -86,6 +86,7 @@ public:
const std::map<std::string, std::string>& attr = std::map<std::string, std::string>());
protected:
+ virtual void setup();
static int luaInFunction(lua_State * l);
diff --git a/src/uscxml/plugins/datamodel/null/NullDataModel.cpp b/src/uscxml/plugins/datamodel/null/NullDataModel.cpp
index cf608f5..05453f9 100644
--- a/src/uscxml/plugins/datamodel/null/NullDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/null/NullDataModel.cpp
@@ -42,9 +42,13 @@ NullDataModel::NullDataModel() {
std::shared_ptr<DataModelImpl> NullDataModel::create(DataModelCallbacks* callbacks) {
std::shared_ptr<NullDataModel> dm(new NullDataModel());
dm->_callbacks = callbacks;
+ dm->setup();
return dm;
}
+void NullDataModel::setup() {
+}
+
NullDataModel::~NullDataModel() {
}
diff --git a/src/uscxml/plugins/datamodel/null/NullDataModel.h b/src/uscxml/plugins/datamodel/null/NullDataModel.h
index 8c9f5b9..278762c 100644
--- a/src/uscxml/plugins/datamodel/null/NullDataModel.h
+++ b/src/uscxml/plugins/datamodel/null/NullDataModel.h
@@ -101,6 +101,7 @@ public:
virtual void addExtension(DataModelExtension* ext) {}
protected:
+ virtual void setup();
};
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
index 2a02099..048deb5 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
@@ -60,33 +60,36 @@ std::shared_ptr<DataModelImpl> PromelaDataModel::create(DataModelCallbacks* call
std::shared_ptr<PromelaDataModel> dm(new PromelaDataModel());
dm->_callbacks = callbacks;
+ dm->setup();
+ return dm;
+}
+void PromelaDataModel::setup() {
// session id
Data sessionId;
sessionId.compound["type"] = Data("string", Data::VERBATIM);
- sessionId.compound["value"] = Data(callbacks->getSessionId(), Data::VERBATIM);
- dm->_variables["_sessionid"] = sessionId;
+ sessionId.compound["value"] = Data(_callbacks->getSessionId(), Data::VERBATIM);
+ _variables["_sessionid"] = sessionId;
// name
Data name;
name.compound["type"] = Data("string", Data::VERBATIM);
- name.compound["value"] = Data(callbacks->getName(), Data::VERBATIM);
- dm->_variables["_name"] = name;
+ name.compound["value"] = Data(_callbacks->getName(), Data::VERBATIM);
+ _variables["_name"] = name;
// ioprocessors
Data ioProcs;
ioProcs.compound["type"] = Data("compound", Data::VERBATIM);
- std::map<std::string, IOProcessor> ioProcessors = callbacks->getIOProcessors();
+ std::map<std::string, IOProcessor> ioProcessors = _callbacks->getIOProcessors();
for (std::map<std::string, IOProcessor>::iterator iter = ioProcessors.begin(); iter != ioProcessors.end(); iter++) {
ioProcs.compound["value"].compound[iter->first] = iter->second.getDataModelVariables();
}
- dm->_variables["_ioprocessors"] = ioProcs;
+ _variables["_ioprocessors"] = ioProcs;
- dm->_lastMType = 0;
- return dm;
-}
+ _lastMType = 0;
+}
void PromelaDataModel::setEvent(const Event& event) {
Data variable;
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
index f19bd5d..80f6b34 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
@@ -69,6 +69,7 @@ public:
const std::map<std::string, std::string>& attr = std::map<std::string, std::string>());
protected:
+ virtual void setup();
int dataToInt(const Data& data);
bool dataToBool(const Data& data);
diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
index 1248205..44af2dd 100644
--- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
@@ -19,7 +19,7 @@
#include "USCXMLInvoker.h"
#include "uscxml/util/DOM.h"
-
+#include "uscxml/interpreter/LoggingImpl.h"
#ifdef BUILD_AS_PLUGINS
#include <Pluma/Connector.hpp>
@@ -191,6 +191,11 @@ void USCXMLInvoker::invoke(const std::string& source, const Event& invokeEvent)
al.internalQueue = alOrig->internalQueue.getImplBase()->create();
al.externalQueue = alOrig->externalQueue.getImplBase()->create();
al.microStepper = alOrig->microStepper.getImpl()->create(invoked);
+ /**
+ * TODO: Do we want a clone of the logger or the same instance?
+ */
+ al.logger = alOrig->logger.getImpl()->create();
+ // Note: we do not create a new instance from the existing datamodel as it may be of a different type
_invokedInterpreter.setActionLanguage(al);
}
diff --git a/test/issues/test-issue121.child b/test/issues/test-issue121.child
new file mode 100644
index 0000000..4d4aeb2
--- /dev/null
+++ b/test/issues/test-issue121.child
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="child" version="1.0" datamodel="promela">
+ <datamodel>
+ <data id="p_id" type="int" expr="0"/>
+ <data id="child_id" type="int" expr="0"/>
+ </datamodel>
+ <state id="sc" initial="sc_01">
+ <onentry>
+ <assign location="child_id" expr="p_id"/>
+ <log label="Hello, I am invoker number" expr="child_id" />
+ </onentry>
+ <state id="sc_01">
+ <onentry>
+ <log label="state sc_01 of invoker number" expr="child_id"/>
+ <send event="sc01_over" delayexpr="500"/>
+ </onentry>
+ <transition event="sc01_over" target="sc_02"/>
+ </state>
+ <state id="sc_02">
+ <onentry>
+ <log label="state sc_02 of invoker number" expr="child_id"/>
+ <send event="Random_Event" delayexpr="300" target="#_parent">
+ <param name="var1" type="int" expr="child_id" />
+ </send>
+ </onentry>
+ <transition event="Random_Event2" target="sc"/>
+ </state>
+ </state>
+</scxml> \ No newline at end of file
diff --git a/test/issues/test-issue121.scxml b/test/issues/test-issue121.scxml
new file mode 100644
index 0000000..d5bf353
--- /dev/null
+++ b/test/issues/test-issue121.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="promela">
+ <datamodel>
+ <data id="var1" type="int" />
+ </datamodel>
+ <state id="s0" initial="s01">
+ <invoke src="test-issue121.child" type="http://www.w3.org/TR/scxml/" id="pOne">
+ <param name="p_id" type="int" expr="1" />
+ </invoke>
+ <invoke src="test-issue121.child" type="http://www.w3.org/TR/scxml/" id="pTwo">
+ <param name="p_id" type="int" expr="2" />
+ </invoke>
+ <state id="s01">
+ <transition event="Random_Event">
+ <assign location="var1" expr="_event.data.var1"/>
+ <log label="var1 value" expr="var1"/>
+ </transition>
+ </state>
+ </state>
+</scxml>
+ \ No newline at end of file