summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-11-13 23:56:53 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-11-13 23:56:53 (GMT)
commit7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c (patch)
treeb681e35b778f5c17d768b0713d8141a17a1dedb9 /src
parent2bc6ae32bbb67d242436d173c41fabc47626b943 (diff)
downloaduscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.zip
uscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.tar.gz
uscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.tar.bz2
Support for DataModelExtensions
Diffstat (limited to 'src')
-rw-r--r--src/bindings/swig/csharp/uscxml.i2
-rw-r--r--src/bindings/swig/java/uscxml.i2
-rw-r--r--src/bindings/swig/uscxml_beautify.i2
-rw-r--r--src/bindings/swig/uscxml_ignores.i1
-rw-r--r--src/bindings/swig/wrapped/WrappedDataModel.cpp3
-rw-r--r--src/bindings/swig/wrapped/WrappedDataModel.h10
-rw-r--r--src/uscxml/Interpreter.cpp86
-rw-r--r--src/uscxml/Interpreter.h17
-rw-r--r--src/uscxml/URL.cpp10
-rw-r--r--src/uscxml/plugins/DataModel.h18
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp72
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h8
12 files changed, 151 insertions, 80 deletions
diff --git a/src/bindings/swig/csharp/uscxml.i b/src/bindings/swig/csharp/uscxml.i
index 334a534..e218bf4 100644
--- a/src/bindings/swig/csharp/uscxml.i
+++ b/src/bindings/swig/csharp/uscxml.i
@@ -21,6 +21,7 @@ typedef uscxml::SendRequest SendRequest;
typedef uscxml::Invoker Invoker;
typedef uscxml::IOProcessor IOProcessor;
typedef uscxml::DataModel DataModel;
+typedef uscxml::DataModelExtension DataModelExtension;
typedef uscxml::ExecutableContent ExecutableContent;
typedef uscxml::InvokerImpl InvokerImpl;
typedef uscxml::IOProcessorImpl IOProcessorImpl;
@@ -30,6 +31,7 @@ typedef uscxml::InterpreterIssue InterpreterIssue;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
+%feature("director") uscxml::WrappedDataModelExtension;
%feature("director") uscxml::WrappedIOProcessor;
%feature("director") uscxml::WrappedExecutableContent;
%feature("director") uscxml::WrappedInterpreterMonitor;
diff --git a/src/bindings/swig/java/uscxml.i b/src/bindings/swig/java/uscxml.i
index 22fad3c..9a86c28 100644
--- a/src/bindings/swig/java/uscxml.i
+++ b/src/bindings/swig/java/uscxml.i
@@ -21,6 +21,7 @@ typedef uscxml::SendRequest SendRequest;
typedef uscxml::Invoker Invoker;
typedef uscxml::IOProcessor IOProcessor;
typedef uscxml::DataModel DataModel;
+typedef uscxml::DataModelExtension DataModelExtension;
typedef uscxml::ExecutableContent ExecutableContent;
typedef uscxml::InvokerImpl InvokerImpl;
typedef uscxml::IOProcessorImpl IOProcessorImpl;
@@ -30,6 +31,7 @@ typedef uscxml::InterpreterIssue InterpreterIssue;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
+%feature("director") uscxml::WrappedDataModelExtension;
%feature("director") uscxml::WrappedIOProcessor;
%feature("director") uscxml::WrappedExecutableContent;
%feature("director") uscxml::WrappedInterpreterMonitor;
diff --git a/src/bindings/swig/uscxml_beautify.i b/src/bindings/swig/uscxml_beautify.i
index 751be78..0350426 100644
--- a/src/bindings/swig/uscxml_beautify.i
+++ b/src/bindings/swig/uscxml_beautify.i
@@ -1,5 +1,7 @@
%rename(NativeDataModel) DataModel;
%rename(DataModel) WrappedDataModel;
+%rename(NativeDataModelExtension) DataModelExtension;
+%rename(DataModelExtension) WrappedDataModelExtension;
%rename(NativeExecutableContent) ExecutableContent;
%rename(ExecutableContent) WrappedExecutableContent;
%rename(NativeInvoker) Invoker;
diff --git a/src/bindings/swig/uscxml_ignores.i b/src/bindings/swig/uscxml_ignores.i
index be597bc..7f7f7a3 100644
--- a/src/bindings/swig/uscxml_ignores.i
+++ b/src/bindings/swig/uscxml_ignores.i
@@ -136,6 +136,7 @@
%ignore uscxml::WrappedDataModel::eval(const Arabica::DOM::Element<std::string>&, const std::string&);
%ignore uscxml::WrappedDataModel::evalAsBool(const Arabica::DOM::Node<std::string>&, const std::string&);
+%ignore uscxml::DataModelExtension::dm;
// Executable Content
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.cpp b/src/bindings/swig/wrapped/WrappedDataModel.cpp
index 8ba57be..e0124eb 100644
--- a/src/bindings/swig/wrapped/WrappedDataModel.cpp
+++ b/src/bindings/swig/wrapped/WrappedDataModel.cpp
@@ -21,6 +21,9 @@
namespace uscxml {
+WrappedDataModelExtension::WrappedDataModelExtension() {}
+WrappedDataModelExtension::~WrappedDataModelExtension() {}
+
WrappedDataModel::WrappedDataModel() {}
WrappedDataModel::~WrappedDataModel() {}
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h
index e988dc0..f33f5da 100644
--- a/src/bindings/swig/wrapped/WrappedDataModel.h
+++ b/src/bindings/swig/wrapped/WrappedDataModel.h
@@ -33,8 +33,18 @@
namespace uscxml {
+class WrappedDataModelExtension : public DataModelExtension {
+public:
+ WrappedDataModelExtension();
+ virtual ~WrappedDataModelExtension();
+ virtual std::string provides() { return ""; }
+ virtual Data getValueOf(const std::string& member) { return Data(); }
+ virtual void setValueOf(const std::string& member, const Data& data) { }
+};
+
class WrappedDataModel : public DataModelImpl {
public:
+
WrappedDataModel();
virtual ~WrappedDataModel();
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 717000e..5d9d1cd 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -1321,6 +1321,9 @@ void InterpreterImpl::init() {
if (HAS_ATTR(_scxml, "datamodel")) {
// might throw
_dataModel = _factory->createDataModel(ATTR(_scxml, "datamodel"), this);
+ for (std::set<DataModelExtension*>::iterator extIter = _dataModelExtensions.begin(); extIter != _dataModelExtensions.end(); extIter++) {
+ _dataModel.addExtension(*extIter);
+ }
} else {
_dataModel = _factory->createDataModel("null", this);
}
@@ -2020,8 +2023,6 @@ void InterpreterImpl::cancelInvoke(const Arabica::DOM::Element<std::string>& ele
//receiveInternal(Event("done.invoke." + invokeId, Event::PLATFORM));
}
-#if 1
-
// see: http://www.w3.org/TR/scxml/#EventDescriptors
bool InterpreterImpl::nameMatch(const std::string& eventDescs, const std::string& eventName) {
if(eventDescs.length() == 0 || eventName.length() == 0)
@@ -2074,50 +2075,6 @@ NEXT_DESC:
return false;
}
-#else
-// see: http://www.w3.org/TR/scxml/#EventDescriptors
-bool InterpreterImpl::nameMatch(const std::string& transitionEvent, const std::string& event) {
- if(transitionEvent.length() == 0 || event.length() == 0)
- return false;
-
- // naive case of single descriptor and exact match
- if (iequals(transitionEvent, event))
- return true;
-
- boost::char_separator<char> sep(" ");
- boost::tokenizer<boost::char_separator<char> > tokens(transitionEvent, sep);
- boost::tokenizer<boost::char_separator<char> >::iterator tokenIter = tokens.begin();
-
- while(tokenIter != tokens.end()) {
- std::string eventDesc(*tokenIter++);
-
- // remove optional trailing .* for CCXML compatibility
- if (eventDesc.find("*", eventDesc.size() - 1) != std::string::npos)
- eventDesc = eventDesc.substr(0, eventDesc.size() - 1);
- if (eventDesc.find(".", eventDesc.size() - 1) != std::string::npos)
- eventDesc = eventDesc.substr(0, eventDesc.size() - 1);
-
- // was eventDesc the * wildcard
- if (eventDesc.size() == 0)
- return true;
-
- // are they already equal?
- if (iequals(eventDesc, event))
- return true;
-
- // eventDesc has to be a real prefix of event now and therefore shorter
- if (eventDesc.size() >= event.size())
- continue;
-
- // it is a prefix of the event name and event continues with .something
- if (boost::istarts_with(event, eventDesc))
-// if (eventDesc.compare(event.substr(0, eventDesc.size())) == 0)
- if (event.find(".", eventDesc.size()) == eventDesc.size())
- return true;
- }
- return false;
-}
-#endif
bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Element<std::string>& conditional) {
if (HAS_ATTR(conditional, "cond") && ATTR(conditional, "cond").length() > 0) {
@@ -2754,43 +2711,24 @@ NodeSet<std::string> InterpreterImpl::getTargetStates(const Arabica::XPath::Node
return targets;
}
-std::list<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) {
- std::list<std::string> ids;
+std::list<std::string> InterpreterImpl::tokenize(const std::string& line, const char sep) {
+ std::list<std::string> tokens;
// appr. 3x faster than stringstream
size_t start = 0;
- for (int i = 0; i < idRefs.size(); i++) {
- if (isspace(idRefs[i])) {
+ for (int i = 0; i < line.size(); i++) {
+ if (line[i] == sep) {
if (i > 0 && start < i) {
- ids.push_back(idRefs.substr(start, i - start));
+ tokens.push_back(line.substr(start, i - start));
}
- while(isspace(idRefs[++i])); // skip whitespaces
+ while(line[++i] == sep); // skip multiple occurences of seperator
start = i;
- } else if (i + 1 == idRefs.size()) {
- ids.push_back(idRefs.substr(start, i + 1 - start));
+ } else if (i + 1 == line.size()) {
+ tokens.push_back(line.substr(start, i + 1 - start));
}
}
-
-#if 0
- if (idRefs.length() > 0) {
- std::istringstream iss(idRefs);
-
- std::copy(std::istream_iterator<std::string>(iss),
- std::istream_iterator<std::string>(),
- std::back_inserter<std::vector<std::string> >(ids));
- }
-#endif
-
-#if 0
- // this version is somewhat fatser than the one above
- std::stringstream ss (idRefs);
- std::string item;
- while(ss >> item)
- ids.push_back(item);
-#endif
-
- return ids;
+ return tokens;
}
std::string InterpreterImpl::spaceNormalize(const std::string& text) {
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 6772a59..70c9c0e 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -375,6 +375,10 @@ public:
return _dataModel;
}
+ void addDataModelExtension(DataModelExtension* ext) {
+ _dataModelExtensions.insert(ext);
+ }
+
void setInvoker(const std::string& invokeId, Invoker invoker) {
_dontDestructOnUninvoke.insert(invokeId);
_invokers[invokeId] = invoker;
@@ -428,7 +432,11 @@ public:
static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::DOM::Node<std::string>& node, bool recurse = false);
static Arabica::XPath::NodeSet<std::string> filterChildType(const Arabica::DOM::Node_base::Type type, const Arabica::XPath::NodeSet<std::string>& nodeSet, bool recurse = false);
- static std::list<std::string> tokenizeIdRefs(const std::string& idRefs);
+ static std::list<std::string> tokenizeIdRefs(const std::string& idRefs) {
+ return tokenize(idRefs);
+ }
+ static std::list<std::string> tokenize(const std::string& line, const char seperator = ' ');
+
static std::string spaceNormalize(const std::string& text);
static bool nameMatch(const std::string& eventDescs, const std::string& event);
Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states);
@@ -558,7 +566,8 @@ protected:
std::map<std::string, std::pair<InterpreterImpl*, SendRequest> > _sendIds;
std::map<std::string, Invoker> _invokers;
std::map<Arabica::DOM::Node<std::string>, ExecutableContent> _executableContent;
-
+ std::set<DataModelExtension*> _dataModelExtensions;
+
std::map<std::pair<Arabica::DOM::Node<std::string>, Arabica::DOM::Node<std::string> >, Arabica::XPath::NodeSet<std::string> > _cachedProperAncestors;
std::map<Arabica::DOM::Element<std::string>, Arabica::XPath::NodeSet<std::string> > _cachedTargets;
std::map<std::string, Arabica::DOM::Element<std::string> > _cachedStates;
@@ -702,6 +711,10 @@ public:
return _impl->getInvokers();
}
+ void addDataModelExtension(DataModelExtension* ext) {
+ _impl->addDataModelExtension(ext);
+ }
+
void setParentQueue(uscxml::concurrency::BlockingQueue<SendRequest>* parentQueue) {
return _impl->setParentQueue(parentQueue);
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index 8fa80c5..d18b55c 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -554,15 +554,19 @@ URLFetcher::URLFetcher() {
bool unsupported = false;
CURLcode curlError;
- char* envProxy = getenv("USCXML_PROXY"); // e.g. 'socks5://bob:marley@localhost:12345'
+ /*
+ see http://curl.haxx.se/libcurl/c/CURLOPT_PROXY.html
+ e.g. 'socks5://bob:marley@localhost:12345'
+ */
+ char* envProxy = getenv("USCXML_PROXY");
// exposed just in case
char* envProxyTransferMode = getenv("USCXML_PROXY_TRANSFER_MODE");
char* envProxyAuth = getenv("USCXML_PROXYAUTH");
-// char* envProxyHeader = getenv("USCXML_PROXYHEADER");
+// char* envProxyHeader = getenv("USCXML_PROXYHEADER"); // not available in older curl
char* envProxyPassword = getenv("USCXML_PROXYPASSWORD");
char* envProxyPort = getenv("USCXML_PROXYPORT");
-// char* envProxyType = getenv("USCXML_PROXYTYPE");
+// char* envProxyType = getenv("USCXML_PROXYTYPE"); // takes an int, have another look if needed
char* envProxyUsername = getenv("USCXML_PROXYUSERNAME");
char* envProxyUserPwd = getenv("USCXML_PROXYUSERPWD");
diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h
index be68ea2..a210ea1 100644
--- a/src/uscxml/plugins/DataModel.h
+++ b/src/uscxml/plugins/DataModel.h
@@ -33,6 +33,17 @@
namespace uscxml {
class InterpreterImpl;
+class DataModelImpl;
+
+class USCXML_API DataModelExtension {
+public:
+ DataModelExtension() : dm(NULL) {}
+ virtual ~DataModelExtension() {}
+ virtual std::string provides() = 0;
+ virtual Data getValueOf(const std::string& member) = 0;
+ virtual void setValueOf(const std::string& member, const Data& data) = 0;
+ DataModelImpl* dm;
+};
class USCXML_API DataModelImpl {
public:
@@ -86,6 +97,8 @@ public:
_interpreter = interpreter;
}
+ virtual void addExtension(DataModelExtension* ext) {}
+
virtual std::string andExpressions(std::list<std::string>) {
return "";
}
@@ -96,6 +109,7 @@ protected:
class USCXML_API DataModel {
public:
+
DataModel() : _impl() {}
DataModel(const boost::shared_ptr<DataModelImpl> impl) : _impl(impl) { }
DataModel(const DataModel& other) : _impl(other._impl) { }
@@ -205,6 +219,10 @@ public:
_impl->setInterpreter(interpreter);
}
+ virtual void addExtension(DataModelExtension* ext) {
+ _impl->addExtension(ext);
+ }
+
protected:
boost::shared_ptr<DataModelImpl> _impl;
};
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 2f07528..bb77944 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -85,6 +85,77 @@ JSCDataModel::~JSCDataModel() {
JSGlobalContextRelease(_ctx);
}
+void JSCDataModel::addExtension(DataModelExtension* ext) {
+ if (_extensions.find(ext) != _extensions.end())
+ return;
+
+ ext->dm = this;
+ _extensions.insert(ext);
+
+ JSObjectRef currScope = JSContextGetGlobalObject(_ctx);
+ std::list<std::string> locPath = InterpreterImpl::tokenize(ext->provides(), '.');
+ std::list<std::string>::iterator locIter = locPath.begin();
+ while(true) {
+ std::string pathComp = *locIter;
+ JSStringRef pathCompJS = JSStringCreateWithUTF8CString(pathComp.c_str());
+
+ if (++locIter != locPath.end()) {
+ // just another intermediate step
+ if (!JSObjectHasProperty(_ctx, currScope, pathCompJS)) {
+ JSObjectSetProperty(_ctx, currScope, pathCompJS, JSObjectMake(_ctx, NULL, NULL), kJSPropertyAttributeNone, NULL);
+ }
+ JSValueRef newScope = JSObjectGetProperty(_ctx, currScope, pathCompJS, NULL);
+ JSStringRelease(pathCompJS);
+
+
+ if (JSValueIsObject(_ctx, newScope)) {
+ currScope = JSValueToObject(_ctx, newScope, NULL);
+ } else {
+ JSStringRelease(pathCompJS);
+ throw "adsf";
+ }
+ } else {
+ // this is the function!
+ JSClassRef jsExtensionClassRef = JSClassCreate(&jsExtensionClassDef);
+ JSObjectRef jsExtFuncObj = JSObjectMake(_ctx, jsExtensionClassRef, ext);
+ JSObjectSetProperty(_ctx, currScope, pathCompJS, jsExtFuncObj, kJSPropertyAttributeNone, NULL);
+
+ JSStringRelease(pathCompJS);
+ break;
+ }
+ }
+}
+
+JSValueRef JSCDataModel::jsExtension(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
+ DataModelExtension* extension = (DataModelExtension*)JSObjectGetPrivate(function);
+
+ JSStringRef memberRef;
+ std::string memberName;
+
+ if (argumentCount > 0 && JSValueIsString(ctx, arguments[0])) {
+ memberRef = JSValueToStringCopy(ctx, arguments[0], exception);
+ size_t maxSize = JSStringGetMaximumUTF8CStringSize(memberRef);
+ char* buffer = new char[maxSize];
+ JSStringGetUTF8CString(memberRef, buffer, maxSize);
+ JSStringRelease(memberRef);
+ memberName = buffer;
+ free(buffer);
+ }
+
+ if (argumentCount > 1) {
+ // setter
+ Data data = ((JSCDataModel*)(extension->dm))->getValueAsData(arguments[1]);
+ extension->setValueOf(memberName, data);
+ return JSValueMakeNull(ctx);
+ }
+ if (argumentCount == 1) {
+ // getter
+ return ((JSCDataModel*)(extension->dm))->getDataAsValue(extension->getValueOf(memberName));
+ }
+
+ return JSValueMakeNull(ctx);
+}
+
#if 0
typedef struct {
int version; /* current (and only) version is 0 */
@@ -113,6 +184,7 @@ typedef struct {
// functions need to be objects to hold private data in JSC
JSClassDefinition JSCDataModel::jsInClassDef = { 0, 0, "In", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsIn, 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::jsExtensionClassDef = { 0, 0, "Extension", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsExtension, 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 };
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
index 10d5999..c2ba01c 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
@@ -42,6 +42,8 @@ public:
virtual ~JSCDataModel();
virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter);
+ virtual void addExtension(DataModelExtension* ext);
+
virtual std::list<std::string> getNames() {
std::list<std::string> names;
names.push_back("ecmascript");
@@ -91,6 +93,8 @@ protected:
static JSValueRef jsIn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSClassDefinition jsPrintClassDef;
static JSValueRef jsPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+ static JSClassDefinition jsExtensionClassDef;
+ static JSValueRef jsExtension(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSClassDefinition jsIOProcessorsClassDef;
static bool jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
@@ -101,7 +105,7 @@ protected:
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 getNodeAsValue(const Arabica::DOM::Node<std::string>& node);
JSValueRef getDataAsValue(const Data& data);
Data getValueAsData(const JSValueRef value);
@@ -112,6 +116,8 @@ protected:
std::string _sessionId;
std::string _name;
+ std::set<DataModelExtension*> _extensions;
+
Event _event;
JSGlobalContextRef _ctx;
};