From f2d8c967076e5d8ebd3ca718e14edef8acb5f87c Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Mon, 22 Jul 2013 14:38:43 +0200 Subject: Removed iOS project again --- .gitignore | 2 + CMakeLists.txt | 15 +- apps/w3c-mmi/MMIEventServlet.cpp | 4 +- src/uscxml/Factory.cpp | 56 +++++ src/uscxml/Factory.h | 12 +- src/uscxml/Interpreter.cpp | 12 +- src/uscxml/Message.h | 2 +- src/uscxml/NameSpacingParser.h | 7 + .../ecmascript/JavaScriptCore/JSCDataModel.cpp | 102 ++++++++- .../ecmascript/JavaScriptCore/JSCDataModel.h | 5 + .../plugins/datamodel/prolog/swi/SWIDataModel.cpp | 16 +- src/uscxml/plugins/invoker/CMakeLists.txt | 19 ++ .../plugins/invoker/location/LocationInvoker.cpp | 44 ++++ .../plugins/invoker/location/LocationInvoker.h | 40 ++++ src/uscxml/plugins/invoker/miles/SpatialAudio.cpp | 43 +++- src/uscxml/plugins/invoker/miles/SpatialAudio.h | 1 + .../plugins/invoker/umundo/UmundoInvoker.cpp | 14 +- .../plugins/invoker/vxml/VoiceXMLInvoker.cpp | 14 +- src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp | 63 ++++-- test/CMakeLists.txt | 12 +- .../uscxml/applications/SpatialMapTicker.java | 153 +++++++++++++ .../uscxml/applications/spoken-map-ticker.scxml | 64 ++++++ .../uscxml/applications/spoken-map-ticker.xhtml | 236 +++++++++++++++++++++ .../uscxml/arabica/test-arabica-parsing.xml | 6 + test/samples/uscxml/test-prolog.scxml | 15 +- test/src/test-arabica-parsing.cpp | 48 +++++ test/src/test-datamodel.cpp | 80 +++++++ test/src/test-predicates.cpp | 3 +- 28 files changed, 1010 insertions(+), 78 deletions(-) create mode 100644 src/uscxml/plugins/invoker/location/LocationInvoker.cpp create mode 100644 src/uscxml/plugins/invoker/location/LocationInvoker.h create mode 100644 test/samples/uscxml/applications/SpatialMapTicker.java create mode 100644 test/samples/uscxml/applications/spoken-map-ticker.scxml create mode 100644 test/samples/uscxml/applications/spoken-map-ticker.xhtml create mode 100644 test/samples/uscxml/arabica/test-arabica-parsing.xml create mode 100644 test/src/test-arabica-parsing.cpp create mode 100644 test/src/test-datamodel.cpp diff --git a/.gitignore b/.gitignore index c1665be..649e14d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ package/darwin* package/windows* *.tgz + +*.class diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fa22f8..4c27508 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,10 +287,13 @@ if (APPLE) endif() if (IOS) - set(CMAKE_OSX_DEPLOYMENT_TARGET 4.3) - foreach(FLAGS CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) - set(${FLAGS} "${${FLAGS}} -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - endforeach() + if (${CMAKE_GENERATOR} STREQUAL "Xcode") + else() + set(CMAKE_OSX_DEPLOYMENT_TARGET 4.3) + foreach(FLAGS CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) + set(${FLAGS} "${${FLAGS}} -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endforeach() + endif() endif() ############################################################ @@ -636,6 +639,10 @@ if (NOT WIN32) add_subdirectory(src/bindings) endif() +#if (IOS) + add_subdirectory(apps/ios) +#endif() + ############################################################ # Header Files ############################################################ diff --git a/apps/w3c-mmi/MMIEventServlet.cpp b/apps/w3c-mmi/MMIEventServlet.cpp index cb5136a..22b8d91 100644 --- a/apps/w3c-mmi/MMIEventServlet.cpp +++ b/apps/w3c-mmi/MMIEventServlet.cpp @@ -68,7 +68,7 @@ bool MMIEventServlet::httpRecvRequest(const HTTPServer::Request& req) { return true; } - std::cout << mmiDoc.getNamespaceURI() << std::endl; +// std::cout << mmiDoc.getNamespaceURI() << std::endl; Node mmiEvent = mmiDoc.getFirstChild(); // get the first element while (mmiEvent && mmiEvent.getNodeType() != Node_base::ELEMENT_NODE) { @@ -81,7 +81,7 @@ bool MMIEventServlet::httpRecvRequest(const HTTPServer::Request& req) { mmiEvent = mmiEvent.getNextSibling(); } } - std::cout << mmiEvent << std::endl; +// std::cout << mmiEvent << std::endl; if (!mmiEvent) { evhttp_send_error(req.curlReq, 402, NULL); diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index b3ad09e..7ac3b98 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -392,6 +392,62 @@ boost::shared_ptr Factory::createExecutableContent(const } +size_t DataModelImpl::replaceExpressions(std::string& content) { + std::stringstream ss; + size_t replacements = 0; + size_t indent = 0; + size_t pos = 0; + size_t start = std::string::npos; + size_t end = 0; + while (true) { + // find any of ${} + pos = content.find_first_of("${}", pos); + if (pos == std::string::npos) { + ss << content.substr(end, content.length() - end); + break; + } + if (content[pos] == '$') { + if (content.size() > pos && content[pos+1] == '{') { + pos++; + start = pos + 1; + // copy everything in between + ss << content.substr(end, (start - 2) - end); + } + } else if (content[pos] == '{' && start != std::string::npos) { + indent++; + } else if (content[pos] == '}' && start != std::string::npos) { + if (!indent) { + end = pos; + // we found a token to substitute + std::string expr = content.substr(start, end - start); + end++; + try { + Data data = getStringAsData(expr); +// if (data.type == Data::VERBATIM) { +// ss << "\"" << data.atom << "\""; +// } else { +// ss << data.atom; +// } + ss << Data::toJSON(data); + replacements++; + } catch (Event e) { + // insert unsubstituted + start -= 2; + ss << content.substr(start, end - start); + } + start = std::string::npos; + } else { + indent--; + } + } + pos++; + } + if (replacements) + content = ss.str(); + + return replacements; +} + Factory* Factory::getInstance() { if (_instance == NULL) { diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 7b08982..2a0ec43 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -10,12 +10,14 @@ #include #include #include +#include namespace uscxml { // see http://stackoverflow.com/questions/228005/alternative-to-itoa-for-converting-integer-to-string-c template std::string toStr(T tmp) { std::ostringstream out; + out.precision(std::numeric_limits::digits10 + 1); out << tmp; return out.str(); } @@ -28,9 +30,9 @@ template T strTo(std::string tmp) { } inline bool isNumeric( const char* pszInput, int nNumberBase) { - std::string base = "0123456789ABCDEF"; + std::string base = ".0123456789ABCDEF"; std::string input = pszInput; - return (input.find_first_not_of(base.substr(0, nNumberBase)) == std::string::npos); + return (input.find_first_not_of(base.substr(0, nNumberBase + 1)) == std::string::npos); } class InterpreterImpl; @@ -252,6 +254,8 @@ public: virtual void setEvent(const Event& event) = 0; virtual Data getStringAsData(const std::string& content) = 0; + size_t replaceExpressions(std::string& content); + // foreach virtual uint32_t getLength(const std::string& expr) = 0; virtual void setForeach(const std::string& item, @@ -363,6 +367,10 @@ public: return _impl->isDeclared(expr); } + size_t replaceExpressions(std::string& content) { + return _impl->replaceExpressions(content); + } + protected: boost::shared_ptr _impl; }; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 158ea96..8c1b4a6 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -436,7 +436,7 @@ void InterpreterImpl::processContentElement(const Arabica::DOM::Node& no LOG(ERROR) << LOCALNAME(node) << " element has relative src or srcexpr URI with no baseURI set."; return; } - if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end()) { + if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end() && false) { srcContent << _cachedURLs[sourceURL.asString()]; } else { srcContent << sourceURL; @@ -473,8 +473,12 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& no std::auto_ptr ssPtr(ss); Arabica::SAX::InputSource inputSource; inputSource.setByteStream(ssPtr); + +// parser.setFeature(Arabica::SAX::FeatureNames().external_general, true); + if (parser.parse(inputSource) && parser.getDocument()) { dom = parser.getDocument(); + std::cout << dom; Node content = dom.getDocumentElement(); assert(content.getNodeType() == Node_base::ELEMENT_NODE); Node container = dom.createElement("container"); @@ -1106,7 +1110,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont } std::stringstream srcContent; - if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end()) { + if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end() && false) { srcContent << _cachedURLs[scriptUrl.asString()]; } else { srcContent << scriptUrl; @@ -1313,7 +1317,7 @@ Arabica::XPath::NodeSet InterpreterImpl::getStates(const std::vecto Arabica::DOM::Node InterpreterImpl::getState(const std::string& stateId) { - if (_cachedStates.find(stateId) != _cachedStates.end()) { + if (_cachedStates.find(stateId) != _cachedStates.end() && false) { return _cachedStates[stateId]; } diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index dd62702..dda2279 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -26,7 +26,7 @@ public: INTERPRETED }; - Data() {} + Data() : type(INTERPRETED) {} Data(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {} explicit Data(const Arabica::DOM::Node& dom); virtual ~Data() {} diff --git a/src/uscxml/NameSpacingParser.h b/src/uscxml/NameSpacingParser.h index fddf306..50cc260 100644 --- a/src/uscxml/NameSpacingParser.h +++ b/src/uscxml/NameSpacingParser.h @@ -6,6 +6,13 @@ namespace uscxml { +class ScriptEntityResolver : public Arabica::SAX::EntityResolver { + virtual InputSourceT resolveEntity(const std::string& publicId, const std::string& systemId) { + Arabica::SAX::InputSource is; + return is; + } +}; + class NameSpacingParser : public Arabica::SAX2DOM::Parser { public: NameSpacingParser(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 8feb73a..47ec21d 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -24,10 +24,37 @@ bool connect(pluma::Host& host) { JSCDataModel::JSCDataModel() { } +#if 0 +typedef struct { + int version; /* current (and only) version is 0 */ + JSClassAttributes attributes; + + const char* className; + JSClassRef parentClass; + + const JSStaticValue* staticValues; + const JSStaticFunction* staticFunctions; + + JSObjectInitializeCallback initialize; + JSObjectFinalizeCallback finalize; + JSObjectHasPropertyCallback hasProperty; + JSObjectGetPropertyCallback getProperty; + JSObjectSetPropertyCallback setProperty; + JSObjectDeletePropertyCallback deleteProperty; + JSObjectGetPropertyNamesCallback getPropertyNames; + JSObjectCallAsFunctionCallback callAsFunction; + JSObjectCallAsConstructorCallback callAsConstructor; + JSObjectHasInstanceCallback hasInstance; + JSObjectConvertToTypeCallback convertToType; +} JSClassDefinition; +#endif + // 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::jsIOProcessorsClassDef = { 0, 0, "ioProcessors", 0, 0, 0, 0, 0, jsIOProcessorHasProp, jsIOProcessorGetProp, 0, 0, jsIOProcessorListProps, 0, 0, 0, 0 }; + boost::shared_ptr JSCDataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr dm = boost::shared_ptr(new JSCDataModel()); @@ -51,15 +78,33 @@ boost::shared_ptr JSCDataModel::create(InterpreterImpl* interpret JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL); JSStringRelease(inName); - dm->eval("_ioprocessors = {};"); + JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef); + JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get()); + JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors"); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeNone, NULL); + JSStringRelease(ioProcName); + + JSStringRef nameName = JSStringCreateWithUTF8CString("_name"); + JSStringRef name = JSStringCreateWithUTF8CString(dm->_interpreter->getName().c_str()); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeNone, NULL); + JSStringRelease(nameName); + JSStringRelease(name); + + JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid"); + JSStringRef sessionId = JSStringCreateWithUTF8CString(dm->_interpreter->getSessionId().c_str()); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeNone, NULL); + JSStringRelease(sessionIdName); + JSStringRelease(sessionId); Arabica::DOM::JSCDocument::JSCDocumentPrivate* privData = new Arabica::DOM::JSCDocument::JSCDocumentPrivate(); - privData->nativeObj = new Arabica::DOM::Document(interpreter->getDocument()); - privData->dom = dm->_dom; + if (interpreter) { + privData->nativeObj = new Arabica::DOM::Document(interpreter->getDocument()); + privData->dom = dm->_dom; - JSObjectRef documentObject = JSObjectMake(dm->_ctx, Arabica::DOM::JSCDocument::getTmpl(), privData); - JSObjectRef globalObject = JSContextGetGlobalObject(dm->_ctx); - JSObjectSetProperty(dm->_ctx, globalObject, JSStringCreateWithUTF8CString("document"), documentObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); + JSObjectRef documentObject = JSObjectMake(dm->_ctx, Arabica::DOM::JSCDocument::getTmpl(), privData); + JSObjectRef globalObject = JSContextGetGlobalObject(dm->_ctx); + JSObjectSetProperty(dm->_ctx, globalObject, JSStringCreateWithUTF8CString("document"), documentObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); + } dm->eval("_invokers = {};"); dm->eval("_x = {};"); @@ -202,10 +247,9 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) { JSValueRef exception = NULL; switch(JSValueGetType(_ctx, value)) { case kJSTypeUndefined: - LOG(ERROR) << "IsUndefined is unimplemented"; - break; case kJSTypeNull: - LOG(ERROR) << "IsNull is unimplemented"; + data.atom = "null"; + data.type = Data::INTERPRETED; break; case kJSTypeBoolean: data.atom = (JSValueToBoolean(_ctx, value) ? "true" : "false"); @@ -225,6 +269,7 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) { JSStringGetUTF8CString(stringValue, buf, maxSize); data.atom = std::string(buf); + data.type = Data::VERBATIM; JSStringRelease(stringValue); free(buf); break; @@ -488,4 +533,43 @@ JSValueRef JSCDataModel::jsIn(JSContextRef ctx, JSObjectRef function, JSObjectRe } +bool JSCDataModel::jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map ioProcessors = INSTANCE->_interpreter->getIOProcessors(); + + size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char buffer[maxSize]; + JSStringGetUTF8CString(propertyName, buffer, maxSize); + std::string prop(buffer); + + return ioProcessors.find(prop) != ioProcessors.end(); +} + +JSValueRef JSCDataModel::jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map ioProcessors = INSTANCE->_interpreter->getIOProcessors(); + + size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char buffer[maxSize]; + JSStringGetUTF8CString(propertyName, buffer, maxSize); + std::string prop(buffer); + + if (ioProcessors.find(prop) != ioProcessors.end()) { + return INSTANCE->getDataAsValue(ioProcessors.find(prop)->second.getDataModelVariables()); + } + return JSValueMakeUndefined(ctx); +} + +void JSCDataModel::jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { + JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object); + std::map ioProcessors = INSTANCE->_interpreter->getIOProcessors(); + + std::map::const_iterator ioProcIter = ioProcessors.begin(); + while(ioProcIter != ioProcessors.end()) { + JSStringRef ioProcName = JSStringCreateWithUTF8CString(ioProcIter->first.c_str()); + JSPropertyNameAccumulatorAddName(propertyNames, ioProcName); + ioProcIter++; + } +} + } \ No newline at end of file diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h index 28a313e..36765c2 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h @@ -66,6 +66,11 @@ protected: static JSClassDefinition jsPrintClassDef; static JSValueRef jsPrint(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); + static JSValueRef jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + static void jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); + JSValueRef getDocumentAsValue(const Arabica::DOM::Document& doc); JSValueRef getDataAsValue(const Data& data); Data getValueAsData(const JSValueRef value); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index c92274c..2e37b29 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -264,13 +264,17 @@ void SWIDataModel::eval(const std::string& expr) { } bool SWIDataModel::evalAsBool(const std::string& expr) { - PlCompound compound(expr.c_str()); - PlTermv termv(compound.arity()); - for (int i = 0; i < compound.arity(); i++) { - termv[i] = compound[i + 1]; + try { + PlCompound compound(expr.c_str()); + PlTermv termv(compound.arity()); + for (int i = 0; i < compound.arity(); i++) { + termv[i] = compound[i + 1]; + } + PlQuery query(compound.name(), termv); + return query.next_solution() > 0; + } catch(...) { + return false; } - PlQuery query(compound.name(), termv); - return query.next_solution() > 0; } std::string SWIDataModel::evalAsString(const std::string& expr) { diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt index 34d8918..e836275 100644 --- a/src/uscxml/plugins/invoker/CMakeLists.txt +++ b/src/uscxml/plugins/invoker/CMakeLists.txt @@ -32,6 +32,25 @@ else() list (APPEND USCXML_FILES ${DIRMON_INVOKER}) endif() + +# Location invoker to watch for proximity to GPS coordinates + +file(GLOB_RECURSE LOCATION_INVOKER + location/*.cpp + location/*.h +) +source_group("Invoker\\location" FILES ${LOCATION_INVOKER}) +if (BUILD_AS_PLUGINS) + add_library( + invoker_location SHARED + ${LOCATION_INVOKER}) + target_link_libraries(invoker_location uscxml) + set_target_properties(invoker_location PROPERTIES FOLDER "Plugin Invoker") +else() + list (APPEND USCXML_FILES ${LOCATION_INVOKER}) +endif() + + # System invoker to open a native command file(GLOB_RECURSE XHTML_INVOKER diff --git a/src/uscxml/plugins/invoker/location/LocationInvoker.cpp b/src/uscxml/plugins/invoker/location/LocationInvoker.cpp new file mode 100644 index 0000000..9aeb6b4 --- /dev/null +++ b/src/uscxml/plugins/invoker/location/LocationInvoker.cpp @@ -0,0 +1,44 @@ +#include "LocationInvoker.h" +#include + +#ifdef BUILD_AS_PLUGINS +#include +#endif + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool connect(pluma::Host& host) { + host.add( new LocationInvokerProvider() ); + return true; +} +#endif + +LocationInvoker::LocationInvoker() { +} + +LocationInvoker::~LocationInvoker() { +}; + +boost::shared_ptr LocationInvoker::create(InterpreterImpl* interpreter) { + boost::shared_ptr invoker = boost::shared_ptr(new LocationInvoker()); + invoker->_interpreter = interpreter; + return invoker; +} + +Data LocationInvoker::getDataModelVariables() { + Data data; + return data; +} + +void LocationInvoker::send(const SendRequest& req) { +} + +void LocationInvoker::cancel(const std::string sendId) { +} + +void LocationInvoker::invoke(const InvokeRequest& req) { +} + +} \ No newline at end of file diff --git a/src/uscxml/plugins/invoker/location/LocationInvoker.h b/src/uscxml/plugins/invoker/location/LocationInvoker.h new file mode 100644 index 0000000..2eb4833 --- /dev/null +++ b/src/uscxml/plugins/invoker/location/LocationInvoker.h @@ -0,0 +1,40 @@ +#ifndef LOCATIONINVOKER_H_W09J90F0 +#define LOCATIONINVOKER_H_W09J90F0 + +#include + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class LocationInvoker : public InvokerImpl { +public: + LocationInvoker(); + virtual ~LocationInvoker(); + virtual boost::shared_ptr create(InterpreterImpl* interpreter); + + virtual std::set getNames() { + std::set names; + names.insert("location"); + names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#location"); + return names; + } + + virtual Data getDataModelVariables(); + virtual void send(const SendRequest& req); + virtual void cancel(const std::string sendId); + virtual void invoke(const InvokeRequest& req); + +protected: +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(LocationInvoker, InvokerImpl); +#endif + +} + + +#endif /* end of include guard: LOCATIONINVOKER_H_W09J90F0 */ diff --git a/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp b/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp index 3826ebb..298b15f 100644 --- a/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp +++ b/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp @@ -28,11 +28,11 @@ SpatialAudio::SpatialAudio() { _pos[0] = _pos[1] = _pos[2] = 0.0; _listener = new float[3]; _listener[0] = _listener[1] = _listener[2] = 0.0; + _maxPos = new float[3]; + _maxPos[0] = _maxPos[1] = _maxPos[2] = 1.0; miles_init(); - } - SpatialAudio::~SpatialAudio() { }; @@ -53,8 +53,8 @@ void SpatialAudio::send(const SendRequest& req) { _audioDev = miles_audio_device_open(MILES_AUDIO_IO_OPENAL, _audioDevIndex, 0, 22050, 2, 1, 1024, false); if (_audioDev != NULL) { _audioDevOpen = true; - float rolloffFactor = 0.2; - miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_ROLLOFF_FACTOR, &rolloffFactor); +// float rolloffFactor = 1.0; +// miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_ROLLOFF_FACTOR, &rolloffFactor); } } @@ -70,24 +70,30 @@ void SpatialAudio::send(const SendRequest& req) { miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_POSITION, _pos); + char* buffer = (char*)malloc(_audioDev->chunk_size); // skip wav header _dataStream.seekg(44); - + while(_dataStream.readsome(buffer, _audioDev->chunk_size) != 0) { - miles_audio_device_write(MILES_AUDIO_IO_OPENAL, _audioDev, buffer, _audioDev->chunk_size); + int written = 0; + while(written < _audioDev->chunk_size) { + written += miles_audio_device_write(MILES_AUDIO_IO_OPENAL, _audioDev, buffer + written, _audioDev->chunk_size - written); + tthread::this_thread::sleep_for(tthread::chrono::milliseconds(10)); + } } + _dataStream.seekg(0); free(buffer); } } else if (boost::iequals(req.name, "move.listener")) { if (_audioDevOpen) { getPosFromParams(req.params, _listener); - std::cout << "Listener: "; - for (int i = 0; i < 3; i++) { - std::cout << _listener[i] << " "; - } - std::cout << std::endl; +// std::cout << "Listener: "; +// for (int i = 0; i < 3; i++) { +// std::cout << _listener[i] << " "; +// } +// std::cout << std::endl; miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_LISTENER_POS, _listener); @@ -119,6 +125,17 @@ void SpatialAudio::invoke(const InvokeRequest& req) { getPosFromParams(req.params, _pos); + std::multimap::const_iterator paramIter = req.params.begin(); + while(paramIter != req.params.end()) { + if (boost::iequals(paramIter->first, "maxX")) + _maxPos[0] = strTo(paramIter->second); + if (boost::iequals(paramIter->first, "maxY")) + _maxPos[1] = strTo(paramIter->second); + if (boost::iequals(paramIter->first, "maxZ")) + _maxPos[2] = strTo(paramIter->second); + paramIter++; + } + struct miles_audio_device_description *devices; int ndevs; @@ -170,6 +187,10 @@ void SpatialAudio::getPosFromParams(const std::multimap::const_iterator metaIter = msg->getMeta().begin(); while(metaIter != msg->getMeta().end()) { - event.data.compound[metaIter->first] = Data(metaIter->second, Data::VERBATIM); + if (isNumeric(metaIter->second.c_str(), 10)) { + event.data.compound[metaIter->first] = Data(metaIter->second, Data::INTERPRETED); + } else { + event.data.compound[metaIter->first] = Data(metaIter->second, Data::VERBATIM); + } metaIter++; } @@ -309,9 +313,13 @@ std::multimap boost::shared_ptr UmundoInvoker::getNode(InterpreterImpl* interpreter, const std::string& domain) { std::pair<_nodes_t::iterator, _nodes_t::iterator> range = _nodes.equal_range(interpreter->getName()); for (_nodes_t::iterator it = range.first; it != range.second; it++) { - if (it->second.first.compare(domain) == 0) - return it->second.second.lock(); + if (it->second.first.compare(domain) == 0) { + boost::shared_ptr node = it->second.second.lock(); + if (node) + return node; + } } + // create a new node boost::shared_ptr node = boost::shared_ptr(new umundo::Node(domain)); std::pair > > pair = std::make_pair(interpreter->getName(), std::make_pair(domain, node)); _nodes.insert(pair); diff --git a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp index a71d21a..a18be8e 100644 --- a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp @@ -48,10 +48,20 @@ Data VoiceXMLInvoker::getDataModelVariables() { void VoiceXMLInvoker::send(const SendRequest& req) { StartRequest start; std::stringstream domSS; +// if (req.dom) { +// // hack until jVoiceXML supports XML +// std::cout << req.dom; +// Arabica::DOM::NodeList prompts = req.dom.getElementsByTagName("vxml:prompt"); +// for (int i = 0; i < prompts.getLength(); i++) { +// if (prompts.item(i).hasChildNodes()) { +// domSS << prompts.item(i).getFirstChild().getNodeValue() << "."; +// } +// } +// } domSS << req.getFirstDOMElement(); start.content = domSS.str(); - - start.contentURL.href = "http://localhost/~sradomski/hello.vxml"; + _interpreter->getDataModel().replaceExpressions(start.content); + start.requestId = "asdf"; start.source = "asdf"; start.target = "umundo://mmi/jvoicexml"; diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp index 0c7ef08..4e2c01a 100644 --- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp @@ -7,9 +7,12 @@ #include #endif -#if defined(__APPLE__) and defined(TARGET_OS_MAC) -#include -#include +#if __APPLE__ +# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR +# else +# include +# include +# endif #endif namespace uscxml { @@ -41,6 +44,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { // these are the XHR requests if (boost::iequals(req.data["header"]["X-Requested-With"].atom, "XMLHttpRequest")) { if (boost::iequals(req.data["type"].atom, "get")) { + // the long-polling GET if (_longPoll) { evhttp_send_error(_longPoll.curlReq, 204, NULL); _longPoll.curlReq = NULL; @@ -52,9 +56,12 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { } return true; } else { + // a POST request Event ev(req); if (ev.data["header"]["X-SCXML-Name"]) { ev.name = ev.data["header"]["X-SCXML-Name"].atom; + } else { + ev.name = req.data["type"].atom; } ev.origin = _invokeId; ev.initContent(req.data["content"].atom); @@ -62,6 +69,9 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { // content is already on ev.raw ev.data.compound["Connection"].compound.erase("content"); + HTTPServer::Reply reply(req); + HTTPServer::reply(reply); + returnEvent(ev); return true; } @@ -70,17 +80,9 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { // initial request for a document if (!req.data["query"] && // no query parameters boost::iequals(req.data["type"].atom, "get") && // request type is GET - (boost::icontains(req.data["header"]["Accept"].atom, "text/html") || // accepts html or - boost::contains(req.data["header"]["User-Agent"].atom, "MSIE")) && // is the internet explorer req.content.length() == 0) { // no content HTTPServer::Reply reply(req); - URL templateURL("templates/xhtml-invoker.html"); - templateURL.toAbsolute(_interpreter->getBaseURI()); - templateURL.download(true); - std::string templateContent = templateURL.getInContent(); - boost::replace_all(templateContent, "${scxml.server}", _url); - boost::replace_all(templateContent, "${scxml.invokeId}", _invokeId); std::string content; std::stringstream ss; @@ -90,15 +92,25 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { } else if(_invokeReq.data) { ss << _invokeReq.data; content = ss.str(); - } else { + } else if (_invokeReq.content.length() > 0){ content = _invokeReq.content; + } else { + URL templateURL("templates/xhtml-invoker.html"); + templateURL.toAbsolute(_interpreter->getBaseURI()); + templateURL.download(true); + content = templateURL.getInContent(); } - boost::replace_all(templateContent, "${scxml.content}", content); - reply.content = templateContent; - reply.headers["Content-Type"] = "text/html"; + + _interpreter->getDataModel().replaceExpressions(content); + reply.content = content; + + // application/xhtml+xml + reply.headers["Content-Type"] = "text/html; charset=utf-8"; +// reply.headers["Content-Type"] = "application/xhtml+xml; charset=utf-8"; // aggressive caching in IE will return all XHR get requests instantenously with the template otherwise reply.headers["Cache-Control"] = "no-cache"; +// reply.headers["Cache-Control"] = "max-age=3600"; HTTPServer::reply(reply); @@ -122,17 +134,27 @@ Data XHTMLInvoker::getDataModelVariables() { void XHTMLInvoker::send(const SendRequest& req) { tthread::lock_guard lock(_mutex); + SendRequest reqCopy(req); + _interpreter->getDataModel().replaceExpressions(reqCopy.content); + Data json = Data::fromJSON(reqCopy.content); + if (json) { + reqCopy.data = json; + } + if (!_longPoll) { - _outQueue.push_back(req); + _outQueue.push_back(reqCopy); return; } - reply(req, _longPoll); + reply(reqCopy, _longPoll); _longPoll.curlReq = NULL; } void XHTMLInvoker::reply(const SendRequest& req, const HTTPServer::Request& longPoll) { HTTPServer::Reply reply(longPoll); + // is there JSON in the content? + std::string content = req.content; + if (req.dom) { std::stringstream ss; Arabica::DOM::Node content = req.dom.getDocumentElement(); @@ -164,8 +186,10 @@ void XHTMLInvoker::cancel(const std::string sendId) { void XHTMLInvoker::invoke(const InvokeRequest& req) { _invokeReq = req; - HTTPServer::registerServlet(_interpreter->getName() + "/xhtml/" + req.invokeid, this); -#if defined(__APPLE__) and defined(TARGET_OS_MAC) + HTTPServer::registerServlet(_interpreter->getName() + "/xhtml/" + req.invokeid + ".html", this); +#if __APPLE__ +# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR +# else // see http://stackoverflow.com/questions/4177744/c-osx-open-default-browser CFURLRef url = CFURLCreateWithBytes ( NULL, // allocator @@ -177,6 +201,7 @@ void XHTMLInvoker::invoke(const InvokeRequest& req) { LSOpenCFURLRef(url,0); CFRelease(url); return; +# endif #endif #ifdef _WIN32 // see http://support.microsoft.com/kb/224816 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e00d52..ba332c2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,7 +40,7 @@ if (OFF) set_target_properties(test-dirmon PROPERTIES FOLDER "Tests") endif() -if (OFF) +if (NOT WIN32) add_executable(test-arabica-events src/test-arabica-events.cpp) target_link_libraries(test-arabica-events uscxml) add_test(test-arabica-events ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-arabica-events ${CMAKE_SOURCE_DIR}/test/samples/uscxml/arabica/test-arabica-events.xml) @@ -51,6 +51,11 @@ if (OFF) add_test(test-arabica-xpath ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-arabica-xpath) set_target_properties(test-arabica-xpath PROPERTIES FOLDER "Tests") + add_executable(test-arabica-parsing src/test-arabica-parsing.cpp) + target_link_libraries(test-arabica-parsing uscxml) + add_test(test-arabica-xpath ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-arabica-parsing) + set_target_properties(test-arabica-parsing PROPERTIES FOLDER "Tests") + endif() add_executable(test-url src/test-url.cpp) @@ -58,6 +63,11 @@ target_link_libraries(test-url uscxml) add_test(test-url ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-url) set_target_properties(test-url PROPERTIES FOLDER "Tests") +add_executable(test-datamodel src/test-datamodel.cpp) +target_link_libraries(test-datamodel uscxml) +add_test(test-datamodel ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-datamodel) +set_target_properties(test-datamodel PROPERTIES FOLDER "Tests") + # if (NOT WIN32) # add_executable(test-mmi src/test-mmi.cpp) # target_link_libraries(test-mmi uscxml) diff --git a/test/samples/uscxml/applications/SpatialMapTicker.java b/test/samples/uscxml/applications/SpatialMapTicker.java new file mode 100644 index 0000000..d161264 --- /dev/null +++ b/test/samples/uscxml/applications/SpatialMapTicker.java @@ -0,0 +1,153 @@ +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; +import java.util.Random; + +import org.umundo.core.Greeter; +import org.umundo.core.Message; +import org.umundo.core.Node; +import org.umundo.core.Publisher; + +public class SpatialMapTicker { + + Node node; + Publisher pub; + Greeter greeter; + ArrayList sensors = new ArrayList(); + static ArrayList messages = new ArrayList(); + static Random random = new Random(System.currentTimeMillis()); + + public class SensorMessage { + public String message; + public String severity; + public SensorMessage(String message, String severity) { + this.message = message; + this.severity = severity; + } + public SensorMessage(String message) { + this.message = message; + this.severity = "Notice"; + } + } + + public class Sensor { + @Override + public String toString() { + return "Sensor [id=" + id + ", lat=" + lat + ", lon=" + lon + + ", html=" + getHTML() + "]"; + } + public String id = ""; + public Double lat = new Double(0); + public Double lon = new Double(0); + LinkedList messages = new LinkedList(); + + public void addMessage(SensorMessage message) { + if (messages.size() > 15) + messages.removeLast(); + messages.addFirst(message); + } + + public String getHTML() { + StringBuilder sb = new StringBuilder(); + for (SensorMessage message : messages) { + sb.append(message.severity); + sb.append(": "); + sb.append(message.message); + sb.append("
"); + } + return sb.toString(); + } + } + + public class SensorGreeter extends Greeter { + public void welcome(Publisher publisher, String nodeId, String subId) { + // send all sensors to new subscribers + for (Sensor sensor : sensors) { + Message msg = new Message(); //Message.toSubscriber(subId); + msg.putMeta("id", sensor.id); + msg.putMeta("lat", sensor.lat.toString()); + msg.putMeta("lon", sensor.lon.toString()); + msg.putMeta("html", sensor.getHTML()); + pub.send(msg); + } + } + + @Override + public void farewell(Publisher arg0, String nodeId, String subId) { + } + + } + + public SpatialMapTicker() { + node = new Node(); + pub = new Publisher("map/tick"); + greeter = new SensorGreeter(); + pub.setGreeter(greeter); + node.addPublisher(pub); + + double latCenter = 59.32; + double lonCenter = 18.08; + + int nrSensors = 15; //(int) (Math.random() * 20); + for (int i = 0; i < nrSensors; i++) { + Sensor sensor = new Sensor(); + double latOffset = (Math.random() - 0.5) * 0.3; + double lonOffset = (Math.random() - 0.5) * 0.3; + + sensor.id = "Sensor #" + i; + sensor.lat = latCenter + latOffset; + sensor.lon = lonCenter + lonOffset; + sensors.add(sensor); + } + } + + public static void main(String[] args) { + SpatialMapTicker ticker = new SpatialMapTicker(); + ticker.run(); + } + + private void run() { + messages.add(new SensorMessage("Oil pressure threshold exceeded", "Error")); + messages.add(new SensorMessage("Error #245 in diagnostics unit")); + messages.add(new SensorMessage("Error #32 in diagnostics unit")); + messages.add(new SensorMessage("Error #81 in diagnostics unit")); + messages.add(new SensorMessage("Error #15 in diagnostics unit")); + messages.add(new SensorMessage("Error #145 in diagnostics unit")); + messages.add(new SensorMessage("Unit was moved out of construction site area")); + messages.add(new SensorMessage("Hydraulic pressure exceeding safety limits")); + messages.add(new SensorMessage("Drivers seat belts are not fastened!")); + messages.add(new SensorMessage("Battery recharge cycles exceeded")); + messages.add(new SensorMessage("Unit operated outside recommended paramters")); + + while (true) { + try { + Thread.sleep((long) (Math.random() * 1000) + 200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Sensor sensor = sensors.get(random.nextInt(sensors.size())); + SensorMessage fault = messages.get(random.nextInt(messages.size())); + + Date now = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss z"); + String nowString = sdf.format(now); + sensor.addMessage(fault); + +// System.out.println("Publishing " + sensor); + + Message msg = new Message(); + msg.putMeta("id", sensor.id); + msg.putMeta("lat", sensor.lat.toString()); + msg.putMeta("lon", sensor.lon.toString()); + msg.putMeta("html", sensor.getHTML()); + msg.putMeta("time", nowString); + msg.putMeta("timeStamp", Long.toString(now.getTime())); + msg.putMeta("lastMsg", sensor.messages.getFirst().message); + msg.putMeta("severity", sensor.messages.getFirst().severity); + pub.send(msg); + } + } + +} diff --git a/test/samples/uscxml/applications/spoken-map-ticker.scxml b/test/samples/uscxml/applications/spoken-map-ticker.scxml new file mode 100644 index 0000000..682429d --- /dev/null +++ b/test/samples/uscxml/applications/spoken-map-ticker.scxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + ${_event.data} + + + + + + + + + + + + ${_event.data.lastMsg} + + + + + + + + + \ No newline at end of file diff --git a/test/samples/uscxml/applications/spoken-map-ticker.xhtml b/test/samples/uscxml/applications/spoken-map-ticker.xhtml new file mode 100644 index 0000000..e656be3 --- /dev/null +++ b/test/samples/uscxml/applications/spoken-map-ticker.xhtml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/test/samples/uscxml/arabica/test-arabica-parsing.xml b/test/samples/uscxml/arabica/test-arabica-parsing.xml new file mode 100644 index 0000000..f4e46fb --- /dev/null +++ b/test/samples/uscxml/arabica/test-arabica-parsing.xml @@ -0,0 +1,6 @@ + + + & +]]> + \ No newline at end of file diff --git a/test/samples/uscxml/test-prolog.scxml b/test/samples/uscxml/test-prolog.scxml index 8ccfd6b..def23db 100644 --- a/test/samples/uscxml/test-prolog.scxml +++ b/test/samples/uscxml/test-prolog.scxml @@ -36,7 +36,7 @@ + cond="mother(martha, X), father(bob, X), in(s1)"/> @@ -49,21 +49,10 @@ - - - - - - - - - - - diff --git a/test/src/test-arabica-parsing.cpp b/test/src/test-arabica-parsing.cpp new file mode 100644 index 0000000..2a09dd6 --- /dev/null +++ b/test/src/test-arabica-parsing.cpp @@ -0,0 +1,48 @@ +#include "uscxml/config.h" +#include "uscxml/Common.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace Arabica::DOM; + +int main(int argc, char** argv) { + + { + std::stringstream* ss = new std::stringstream(); + (*ss) << "\n &\n]]>\n"; + // we need an auto_ptr for arabica to assume ownership + std::auto_ptr ssPtr(ss); + Arabica::SAX::InputSource inputSource(ssPtr); + + Arabica::SAX2DOM::Parser domParser; + Arabica::SAX::CatchErrorHandler errorHandler; + domParser.setErrorHandler(errorHandler); + + if(!domParser.parse(inputSource)) { + std::cout << errorHandler.errors(); + return -1; + } + std::cout << domParser.getDocument().getDocumentElement().getFirstChild().getNodeValue() << std::endl; + std::cout << domParser.getDocument() << std::endl; + } + { + Arabica::SAX::InputSource inputSource; + inputSource.setSystemId("/Users/sradomski/Documents/TK/Code/uscxml/test/samples/uscxml/arabica/test-arabica-parsing.xml"); + + Arabica::SAX2DOM::Parser domParser; + Arabica::SAX::CatchErrorHandler errorHandler; + domParser.setErrorHandler(errorHandler); + + if(!domParser.parse(inputSource)) { + std::cout << errorHandler.errors(); + return -1; + } + std::cout << domParser.getDocument() << std::endl; + } + +} \ No newline at end of file diff --git a/test/src/test-datamodel.cpp b/test/src/test-datamodel.cpp new file mode 100644 index 0000000..77f0851 --- /dev/null +++ b/test/src/test-datamodel.cpp @@ -0,0 +1,80 @@ +#include "uscxml/URL.h" +#include "uscxml/Message.h" +#include "uscxml/Interpreter.h" +#include "uscxml/server/HTTPServer.h" + +#include + +#include +#include +#include + +using namespace uscxml; +using namespace boost; + + +int main(int argc, char** argv) { +#ifdef _WIN32 + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif + + DataModel dm(Factory::getInstance()->createDataModel("ecmascript", NULL)); + dm.evalAsString("var foo = 12"); + + { + std::string content = "$"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 0); + std::cout << content << std::endl; + assert(boost::equals(content, "$")); + } + + { + std::string content = "$sadf ${foo}"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 1); + std::cout << content << std::endl; + assert(boost::equals(content, "$sadf 12")); + } + + { + std::string content = "${"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 0); + std::cout << content << std::endl; + assert(boost::equals(content, "${")); + } + + { + std::string content = "${foo}"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 1); + std::cout << content << std::endl; + assert(boost::equals(content, "12")); + } + + { + std::string content = "${bar}"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 0); + std::cout << content << std::endl; + assert(boost::equals(content, "${bar}")); + } + + { + std::string content = "There are ${bar} monkeys! Really ${foo} monkeys!"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 1); + std::cout << content << std::endl; + assert(boost::equals(content, "There are ${bar} monkeys! Really 12 monkeys!")); + } + + { + std::string content = "There are ${foo} monkeys! Really ${foo} monkeys!"; + int rplc = dm.replaceExpressions(content); + assert(rplc == 2); + std::cout << content << std::endl; + assert(boost::equals(content, "There are 12 monkeys! Really 12 monkeys!")); + } +} \ No newline at end of file diff --git a/test/src/test-predicates.cpp b/test/src/test-predicates.cpp index 954afb2..ff61f92 100644 --- a/test/src/test-predicates.cpp +++ b/test/src/test-predicates.cpp @@ -56,6 +56,7 @@ int main(int argc, char** argv) { assert(InterpreterImpl::nameMatch(transEvents, "foo.bar")); assert(!InterpreterImpl::nameMatch(transEvents, "errors.my.custom")); assert(!InterpreterImpl::nameMatch(transEvents, "errorhandler.mistake")); - assert(!InterpreterImpl::nameMatch(transEvents, "errOr.send")); + // is the event name case sensitive? + // assert(!InterpreterImpl::nameMatch(transEvents, "errOr.send")); assert(!InterpreterImpl::nameMatch(transEvents, "foobar")); } \ No newline at end of file -- cgit v0.12