diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2014-11-13 23:56:53 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2014-11-13 23:56:53 (GMT) |
commit | 7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c (patch) | |
tree | b681e35b778f5c17d768b0713d8141a17a1dedb9 | |
parent | 2bc6ae32bbb67d242436d173c41fabc47626b943 (diff) | |
download | uscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.zip uscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.tar.gz uscxml-7a1dc775d5d8edcf9193ca4ad7154af5eab18f1c.tar.bz2 |
Support for DataModelExtensions
-rw-r--r-- | embedding/java/src/org/uscxml/tests/datamodel/TestPlatformExtensions.java | 59 | ||||
-rw-r--r-- | src/bindings/swig/csharp/uscxml.i | 2 | ||||
-rw-r--r-- | src/bindings/swig/java/uscxml.i | 2 | ||||
-rw-r--r-- | src/bindings/swig/uscxml_beautify.i | 2 | ||||
-rw-r--r-- | src/bindings/swig/uscxml_ignores.i | 1 | ||||
-rw-r--r-- | src/bindings/swig/wrapped/WrappedDataModel.cpp | 3 | ||||
-rw-r--r-- | src/bindings/swig/wrapped/WrappedDataModel.h | 10 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 86 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 17 | ||||
-rw-r--r-- | src/uscxml/URL.cpp | 10 | ||||
-rw-r--r-- | src/uscxml/plugins/DataModel.h | 18 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp | 72 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h | 8 | ||||
-rw-r--r-- | test/src/test-datamodel.cpp | 44 |
14 files changed, 253 insertions, 81 deletions
diff --git a/embedding/java/src/org/uscxml/tests/datamodel/TestPlatformExtensions.java b/embedding/java/src/org/uscxml/tests/datamodel/TestPlatformExtensions.java new file mode 100644 index 0000000..86ba884 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/datamodel/TestPlatformExtensions.java @@ -0,0 +1,59 @@ +package org.uscxml.tests.datamodel; + +import org.uscxml.Data; +import org.uscxml.DataModelExtension; +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; +import org.uscxml.InterpreterState; + +public class TestPlatformExtensions extends DataModelExtension { + + /* Currently only with ECMAScript via JavaScriptCore! */ + + @Override + public String provides() { + return "_x.platform.pool"; + } + + @Override + public Data getValueOf(String member) { + return new Data(true); + } + + @Override + public void setValueOf(String member, Data data) { + System.out.println("Setting " + member + " to \n" + data); + } + + public static void main(String[] args) throws InterpreterException { + // load JNI library from build directory + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + + TestPlatformExtensions ext = new TestPlatformExtensions(); + + String xml = + "<scxml datamodel=\"ecmascript\">" + + " <script src=\"http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js\" />" + + " <state id=\"s1\">" + + " <onentry>" + + " <script>_x.platform.pool('member.second', { foo: 12, bar: 34})</script>" + + " <log label=\"ext\" expr=\"dump(_x.platform.pool('member.first'))\" />" + + " </onentry>" + + " <transition target=\"done\" />" + + " </state>" + + " <final id=\"done\" />" + + "</scxml>"; + + Interpreter interpreter = Interpreter.fromXML(xml); + interpreter.addDataModelExtension(ext); + + InterpreterState state; + + do { + state = interpreter.step(); + } while (state != InterpreterState.USCXML_FINISHED && + state != InterpreterState.USCXML_DESTROYED); + + } + +} 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; }; diff --git a/test/src/test-datamodel.cpp b/test/src/test-datamodel.cpp index 71189d6..f0b7536 100644 --- a/test/src/test-datamodel.cpp +++ b/test/src/test-datamodel.cpp @@ -13,6 +13,22 @@ using namespace uscxml; using namespace boost; +class TestDataModelExtension : public DataModelExtension { +public: + TestDataModelExtension() {} + + std::string provides() { + return "_x.platform.pool"; + } + + Data getValueOf(const std::string& member) { + return Data(true); + } + + void setValueOf(const std::string& member, const Data& data) { + std::cout << "Setting " << member << " to " << std::endl << Data::toJSON(data); + } +}; int main(int argc, char** argv) { #ifdef _WIN32 @@ -34,7 +50,6 @@ int main(int argc, char** argv) { assert(testData[i] == otherData[i]); } - exit(0); } Interpreter interpreter = Interpreter::fromXML("<scxml></scxml>"); @@ -482,4 +497,31 @@ int main(int argc, char** argv) { std::cout << content << std::endl; assert(boost::equals(content, "There are 12 monkeys! Really 12 monkeys!")); } + + { + std::string xml = + "<scxml datamodel=\"ecmascript\">" + " <script src=\"http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js\" />" + " <state id=\"s1\">" + " <onentry>" + " <script>_x.platform.pool('memeber.second', { foo: 12, bar: 34})</script>" + " <log label=\"ext\" expr=\"dump(_x.platform.pool('member.first'))\" />" + " </onentry>" + " <transition target=\"done\" />" + " </state>" + " <final id=\"done\" />" + "</scxml>"; + + TestDataModelExtension ext; + Interpreter interpreter = Interpreter::fromXML(xml); + interpreter.addDataModelExtension(&ext); + + InterpreterState state; + + do { + state = interpreter.step(); + } while (state != USCXML_FINISHED && state!= USCXML_DESTROYED); + + + } }
\ No newline at end of file |