From a33a96fd7aee6d53f663102c56236e91d77f53a7 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Wed, 10 May 2017 22:48:14 +0200 Subject: Fixed issue 114 --- contrib/src/uscxml/ExtendedLuaDataModel.h | 15 +++++--- src/bindings/swig/wrapped/WrappedDataModel.h | 4 ++ src/uscxml/plugins/DataModelImpl.h | 26 +++++++++++-- src/uscxml/plugins/datamodel/c89/C89DataModel.cpp | 9 ++++- src/uscxml/plugins/datamodel/c89/C89DataModel.h | 1 + .../ecmascript/JavaScriptCore/JSCDataModel.cpp | 38 +++++++++--------- .../ecmascript/JavaScriptCore/JSCDataModel.h | 1 + .../datamodel/ecmascript/v8/V8DataModel.cpp | 33 ++++++++-------- .../plugins/datamodel/ecmascript/v8/V8DataModel.h | 1 + src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp | 45 ++++++++++++---------- src/uscxml/plugins/datamodel/lua/LuaDataModel.h | 1 + .../plugins/datamodel/null/NullDataModel.cpp | 4 ++ src/uscxml/plugins/datamodel/null/NullDataModel.h | 1 + .../plugins/datamodel/promela/PromelaDataModel.cpp | 21 +++++----- .../plugins/datamodel/promela/PromelaDataModel.h | 1 + src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 7 +++- test/issues/test-issue121.child | 29 ++++++++++++++ test/issues/test-issue121.scxml | 21 ++++++++++ 18 files changed, 183 insertions(+), 75 deletions(-) create mode 100644 test/issues/test-issue121.child create mode 100644 test/issues/test-issue121.scxml 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 create(uscxml::DataModelCallbacks* callbacks) { - std::shared_ptr 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 create(DataModelCallbacks* callbacks) { std::shared_ptr dm(create()); dm->callbacks = callbacks; + dm->setup(); return dm; } + virtual void setup() { + } + virtual std::list getNames() { return std::list(); } 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 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 C89DataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr 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); 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 JSCDataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr 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 JSCDataModel::create(DataModelCallbacks* callback // not thread safe! { std::lock_guard 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& attr = std::map()); 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 V8DataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr 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 global = v8::ObjectTemplate::New(); // some free functions global->Set(v8::String::NewSymbol("print"), - v8::FunctionTemplate::New(dm->_isolate, jsPrint,v8::External::New(reinterpret_cast(dm.get())))); + v8::FunctionTemplate::New(_isolate, jsPrint,v8::External::New(reinterpret_cast(this)))); global->Set(v8::String::NewSymbol("In"), - v8::FunctionTemplate::New(dm->_isolate, jsIn, v8::External::New(reinterpret_cast(dm.get())))); + v8::FunctionTemplate::New(_isolate, jsIn, v8::External::New(reinterpret_cast(this)))); - v8::Local context = v8::Context::New(dm->_isolate, NULL, global); + v8::Local 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 V8DataModel::create(DataModelCallbacks* callbacks context->Global()->SetAccessor(v8::String::NewSymbol("_ioprocessors"), V8DataModel::getIOProcessors, V8DataModel::setWithException, - v8::External::New(reinterpret_cast(dm.get()))); + v8::External::New(reinterpret_cast(this))); context->Global()->SetAccessor(v8::String::NewSymbol("_invokers"), V8DataModel::getInvokers, V8DataModel::setWithException, - v8::External::New(reinterpret_cast(dm.get()))); + v8::External::New(reinterpret_cast(this))); // v8::Persistent > persistent(_isolate, context); @@ -252,7 +256,7 @@ std::shared_ptr V8DataModel::create(DataModelCallbacks* callbacks V8Document::V8DocumentPrivate* privData = new V8Document::V8DocumentPrivate(); privData->nativeObj = new Document(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 V8DataModel::create(DataModelCallbacks* callbacks // instantiate objects - we have to have a context for that! - dm->eval(Element(), "_x = {};"); + eval(Element(), "_x = {};"); #endif - return dm; } void V8DataModel::getAttribute(v8::Local property, const v8::PropertyCallbackInfo& 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& attr = std::map()); protected: + virtual void setup(); static void jsExtension(const v8::FunctionCallbackInfo& info); static void jsIn(const v8::FunctionCallbackInfo& 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 LuaDataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr 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 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("DataModel").endClass(); - luabridge::setGlobal(dm->_luaState, dm.get(), "__datamodel"); + luabridge::getGlobalNamespace(_luaState).beginClass("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 ioProcs = dm->_callbacks->getIOProcessors(); + luabridge::LuaRef ioProcTable = luabridge::newTable(_luaState); + std::map ioProcs = _callbacks->getIOProcessors(); std::map::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 invokers = dm->_callbacks->getInvokers(); + luabridge::LuaRef invTable = luabridge::newTable(_luaState); + std::map invokers = _callbacks->getInvokers(); std::map::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& attr = std::map()); 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 NullDataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr 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 PromelaDataModel::create(DataModelCallbacks* call std::shared_ptr 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 ioProcessors = callbacks->getIOProcessors(); + std::map ioProcessors = _callbacks->getIOProcessors(); for (std::map::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& attr = std::map()); 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 @@ -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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v0.12