diff options
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 |