diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-12 11:57:08 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-12 11:57:08 (GMT) |
commit | ba050afaaad699e60ca657b311d5c34d038bb89c (patch) | |
tree | d4c79e30631c63e8557c6ec893a70dda46aa6cd5 /src/uscxml/plugins/datamodel | |
parent | 45ab2909e17f7e0348ccfe4179f23a897a2fd305 (diff) | |
download | uscxml-ba050afaaad699e60ca657b311d5c34d038bb89c.zip uscxml-ba050afaaad699e60ca657b311d5c34d038bb89c.tar.gz uscxml-ba050afaaad699e60ca657b311d5c34d038bb89c.tar.bz2 |
Refactoring for other datamodels
Diffstat (limited to 'src/uscxml/plugins/datamodel')
8 files changed, 502 insertions, 305 deletions
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 2491fc4..22777fa 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -147,9 +147,13 @@ void V8DataModel::setEvent(const Event& event) { if (event.dom) { eventObj->Set(v8::String::New("data"), getDocumentAsValue(event.dom)); } else if (event.content.length() > 0) { - // _event.data is a string - eventObj->Set(v8::String::New("data"), v8::String::New(event.content.c_str())); -// eventObj->Set(v8::String::New("data"), v8::Undefined()); + // _event.data is a string or JSON + Data json = Data::fromJSON(event.content); + if (json) { + eventObj->Set(v8::String::New("data"), getDataAsValue(json)); + } else { + eventObj->Set(v8::String::New("data"), v8::String::New(Interpreter::spaceNormalize(event.content).c_str())); + } } else { // _event.data is KVP Event eventCopy(event); @@ -188,12 +192,23 @@ Data V8DataModel::getStringAsData(const std::string& content) { } Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value) { + std::set<v8::Value*> foo = std::set<v8::Value*>(); + return getValueAsData(value, foo); +} + +Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value, std::set<v8::Value*>& alreadySeen) { Data data; + + /// TODO: Breaking cycles does not work yet + if (alreadySeen.find(*value) != alreadySeen.end()) + return data; + alreadySeen.insert(*value); + if (false) { } else if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); for (int i = 0; i < array->Length(); i++) { - data.array.push_back(getValueAsData(array->Get(i))); + data.array.push_back(getValueAsData(array->Get(i), alreadySeen)); } } else if (value->IsBoolean()) { data.atom = (value->ToBoolean()->Value() ? "true" : "false"); @@ -226,7 +241,7 @@ Data V8DataModel::getValueAsData(const v8::Handle<v8::Value>& value) { assert(properties->Get(i)->IsString()); v8::String::AsciiValue key(v8::Handle<v8::String>::Cast(properties->Get(i))); v8::Local<v8::Value> property = object->Get(properties->Get(i)); - data.compound[*key] = getValueAsData(property); + data.compound[*key] = getValueAsData(property, alreadySeen); } } else if (value->IsRegExp()) { LOG(ERROR) << "IsRegExp is unimplemented" << std::endl; @@ -374,9 +389,33 @@ std::string V8DataModel::evalAsString(const std::string& expr) { v8::Context::Scope contextScope(_contexts.back()); v8::Handle<v8::Value> result = evalAsValue(expr); if (result->IsObject()) { + v8::Local<v8::Object> obj = result->ToObject(); + v8::Local<v8::Object> proto; + + proto = obj->FindInstanceInPrototypeChain(Arabica::DOM::V8Document::getTmpl()); + if (!proto.IsEmpty()) { + struct Arabica::DOM::V8Document::V8DocumentPrivate* privData = + Arabica::DOM::V8DOM::toClassPtr<Arabica::DOM::V8Document::V8DocumentPrivate >(obj->GetInternalField(0)); + std::stringstream ss; + ss << privData->nativeObj->getDocumentElement(); + return ss.str(); + } + + proto = obj->FindInstanceInPrototypeChain(Arabica::DOM::V8Node::getTmpl()); + if (!proto.IsEmpty()) { + struct Arabica::DOM::V8Node::V8NodePrivate* privData = + Arabica::DOM::V8DOM::toClassPtr<Arabica::DOM::V8Node::V8NodePrivate >(obj->GetInternalField(0)); + std::stringstream ss; + ss << privData->nativeObj; + return ss.str(); + } + Data data = getValueAsData(result); return toStr(data); } + if (result->IsNumber()) { + return toStr(result->ToNumber()->NumberValue()); + } v8::String::AsciiValue data(result->ToString()); return std::string(*data); } @@ -392,40 +431,89 @@ double V8DataModel::evalAsNumber(const std::string& expr) { return 0; } -void V8DataModel::assign(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { +void V8DataModel::assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) { v8::Locker locker; v8::HandleScope handleScope; v8::Context::Scope contextScope(_contexts.front()); v8::Handle<v8::Object> global = _contexts.front()->Global(); - global->Set(v8::String::New(location.c_str()), getDocumentAsValue(doc)); - + std::string key; + if (HAS_ATTR(assignElem, "id")) { + key = ATTR(assignElem, "id"); + } else if (HAS_ATTR(assignElem, "location")) { + key = ATTR(assignElem, "location"); + } + if (key.length() == 0) + throw Event("error.execution", Event::PLATFORM); + + if (HAS_ATTR(assignElem, "expr")) { + evalAsValue(key + " = " + ATTR(assignElem, "expr")); + } else if (doc) { + global->Set(v8::String::New(key.c_str()), getDocumentAsValue(doc)); + } else if (content.size() > 0) { + try { + evalAsValue(key + " = " + content); + } catch (...) { + evalAsValue(key + " = " + "\"" + Interpreter::spaceNormalize(content) + "\""); + } + } else { + global->Set(v8::String::New(key.c_str()), v8::Undefined()); + } } void V8DataModel::assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { + const Data& data) { v8::Locker locker; v8::HandleScope handleScope; v8::Context::Scope contextScope(_contexts.front()); std::stringstream ssJSON; ssJSON << data; - assign(location, ssJSON.str(), dataElem); + evalAsValue(location + " = " + ssJSON.str()); } -void V8DataModel::assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { - v8::Locker locker; - v8::HandleScope handleScope; - v8::Context::Scope contextScope(_contexts.back()); - evalAsValue(location + " = " + expr); +void V8DataModel::init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) { + try { + assign(dataElem, doc, content); + } catch (Event e) { + // test 277 + std::string key; + if (HAS_ATTR(dataElem, "id")) { + key = ATTR(dataElem, "id"); + } else if (HAS_ATTR(dataElem, "location")) { + key = ATTR(dataElem, "location"); + } + v8::Locker locker; + v8::HandleScope handleScope; + v8::Context::Scope contextScope(_contexts.front()); + + evalAsValue(key + " = undefined", true); + throw e; + } +}; + +void V8DataModel::init(const std::string& location, + const Data& data) { + try { + assign(location, data); + } catch (Event e) { + // test 277 + v8::Locker locker; + v8::HandleScope handleScope; + v8::Context::Scope contextScope(_contexts.front()); + + evalAsValue(location + " = undefined", true); + throw e; + } + } -v8::Handle<v8::Value> V8DataModel::evalAsValue(const std::string& expr) { + +v8::Handle<v8::Value> V8DataModel::evalAsValue(const std::string& expr, bool dontThrow) { v8::TryCatch tryCatch; v8::Handle<v8::String> source = v8::String::New(expr.c_str()); v8::Handle<v8::Script> script = v8::Script::Compile(source); @@ -436,7 +524,7 @@ v8::Handle<v8::Value> V8DataModel::evalAsValue(const std::string& expr) { if (script.IsEmpty() || result.IsEmpty()) { // throw an exception - if (tryCatch.HasCaught()) + if (tryCatch.HasCaught() && !dontThrow) throwExceptionEvent(tryCatch); } diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index 7bea50c..7c4f2b3 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -39,36 +39,26 @@ public: virtual void pushContext(); virtual void popContext(); - virtual bool supportsJSON() { return true; } + virtual bool supportsJSON() { + return true; + } virtual void eval(const std::string& expr); + virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content); virtual void assign(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& assignElem); - virtual void assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& assignElem); - virtual void assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& assignElem); - - virtual void init(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { - assign(location, doc, dataElem); - }; - virtual void init(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { - assign(location, expr, dataElem); - } + const Data& data); + + virtual void init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content); virtual void init(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { - assign(location, data, dataElem); - } + const Data& data); virtual Data getStringAsData(const std::string& content); + virtual Data getValueAsData(const v8::Handle<v8::Value>& value, + std::set<v8::Value*>& alreadySeen); virtual Data getValueAsData(const v8::Handle<v8::Value>& value); virtual bool isDeclared(const std::string& expr); @@ -90,7 +80,7 @@ protected: static v8::Handle<v8::Value> getAttribute(v8::Local<v8::String> property, const v8::AccessorInfo& info); static void setWithException(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info); - v8::Handle<v8::Value> evalAsValue(const std::string& expr); + v8::Handle<v8::Value> evalAsValue(const std::string& expr, bool dontThrow = false); v8::Handle<v8::Value> getDataAsValue(const Data& data); v8::Handle<v8::Value> getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc); void throwExceptionEvent(const v8::TryCatch& tryCatch); diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp index 69970dd..6911480 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp @@ -52,7 +52,7 @@ bool NULLDataModel::validate(const std::string& location, const std::string& sch } uint32_t NULLDataModel::getLength(const std::string& expr) { - return 0; + return 0; } void NULLDataModel::eval(const std::string& expr) { @@ -63,9 +63,9 @@ bool NULLDataModel::isDeclared(const std::string& expr) { } /** - * The boolean expression language consists of the In predicate only. It has the - * form 'In(id)', where id is the id of a state in the enclosing state machine. - * The predicate must return 'true' if and only if that state is in the current + * The boolean expression language consists of the In predicate only. It has the + * form 'In(id)', where id is the id of a state in the enclosing state machine. + * The predicate must return 'true' if and only if that state is in the current * state configuration. */ bool NULLDataModel::evalAsBool(const std::string& expr) { @@ -73,14 +73,14 @@ bool NULLDataModel::evalAsBool(const std::string& expr) { boost::trim(trimmedExpr); if (!boost::istarts_with(trimmedExpr, "in")) return false; - + // find string in between brackets size_t start = trimmedExpr.find_first_of("("); size_t end = trimmedExpr.find_last_of(")"); if (start == std::string::npos || end == std::string::npos || start >= end) return false; start++; - + // split at comma std::stringstream ss(trimmedExpr.substr(start, end - start)); std::vector<std::string> stateExprs; @@ -88,7 +88,7 @@ bool NULLDataModel::evalAsBool(const std::string& expr) { while(std::getline(ss, item, ',')) { stateExprs.push_back(item); } - + for (unsigned int i = 0; i < stateExprs.size(); i++) { // remove ticks size_t start = stateExprs[i].find_first_of("'"); @@ -101,7 +101,7 @@ bool NULLDataModel::evalAsBool(const std::string& expr) { } else { stateName = stateExprs[i]; } - + if (Interpreter::isMember(_interpreter->getState(stateName), _interpreter->getConfiguration())) { continue; } diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.h b/src/uscxml/plugins/datamodel/null/NULLDataModel.h index eaa9dbd..423c5ff 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.h +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.h @@ -36,30 +36,20 @@ public: virtual void pushContext(); virtual void popContext(); - virtual void eval(const std::string& expr); - virtual void assign(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& assignElem) {} - virtual void assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& assignElem) {} - virtual void assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& assignElem) {} - - virtual void init(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) {}; - virtual void init(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) {}; - virtual void init(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) {}; + virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) {} + virtual void assign(const std::string& location, const Data& data) {} + + virtual void init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) {} + virtual void init(const std::string& location, const Data& data) {} virtual Data getStringAsData(const std::string& content); virtual bool isDeclared(const std::string& expr); + virtual void eval(const std::string& expr); virtual std::string evalAsString(const std::string& expr); virtual bool evalAsBool(const std::string& expr); virtual double evalAsNumber(const std::string& expr); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 75d6da9..f3af4b6 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -21,7 +21,7 @@ bool connect(pluma::Host& host) { SWIDataModel::SWIDataModel() { } -boost::shared_ptr<DataModelImpl> SWIDataModel::create(Interpreter* interpreter) { +boost::shared_ptr<DataModelImpl> SWIDataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr<SWIDataModel> dm = boost::shared_ptr<SWIDataModel>(new SWIDataModel()); dm->_interpreter = interpreter; @@ -134,16 +134,41 @@ std::string SWIDataModel::evalAsString(const std::string& expr) { return std::string(compound); } -void SWIDataModel::assign(const std::string& location, const Data& data) { - eval(data.atom); +void SWIDataModel::assign(const std::string& location, + const Arabica::DOM::Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& assignElem) { + } +void SWIDataModel::assign(const std::string& location, + const std::string& expr, + const Arabica::DOM::Element<std::string>& assignElem) { -void SWIDataModel::assign(const std::string& location, const std::string& expr) { eval(expr); } +void SWIDataModel::assign(const std::string& location, + const Data& data, + const Arabica::DOM::Element<std::string>& assignElem) { + eval(data.atom); +} + +void SWIDataModel::init(const std::string& location, + const Arabica::DOM::Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& dataElem) { + +} +void SWIDataModel::init(const std::string& location, + const std::string& expr, + const Arabica::DOM::Element<std::string>& dataElem) { + +} +void SWIDataModel::init(const std::string& location, + const Data& data, + const Arabica::DOM::Element<std::string>& dataElem) { -bool SWIDataModel::isDefined(const std::string& expr) { +} + +bool SWIDataModel::isDeclared(const std::string& expr) { return true; } -}
\ No newline at end of file +} diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index 52d1e34..5d95476 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -15,7 +15,7 @@ class SWIDataModel : public DataModelImpl { public: SWIDataModel(); virtual ~SWIDataModel(); - virtual boost::shared_ptr<DataModelImpl> create(Interpreter* interpreter); + virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter); virtual std::set<std::string> getNames() { std::set<std::string> names; @@ -37,20 +37,39 @@ public: virtual void popContext(); virtual void eval(const std::string& expr); - virtual void assign(const std::string& location, const std::string& expr); - virtual void assign(const std::string& location, const Data& data); - virtual bool isDefined(const std::string& expr); + virtual bool isDeclared(const std::string& expr); virtual Data getStringAsData(const std::string& content); virtual std::string evalAsString(const std::string& expr); virtual bool evalAsBool(const std::string& expr); + virtual void assign(const std::string& location, + const Arabica::DOM::Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& assignElem); + virtual void assign(const std::string& location, + const std::string& expr, + const Arabica::DOM::Element<std::string>& assignElem); + virtual void assign(const std::string& location, + const Data& data, + const Arabica::DOM::Element<std::string>& assignElem); + + virtual void init(const std::string& location, + const Arabica::DOM::Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& dataElem); + virtual void init(const std::string& location, + const std::string& expr, + const Arabica::DOM::Element<std::string>& dataElem); + virtual void init(const std::string& location, + const Data& data, + const Arabica::DOM::Element<std::string>& dataElem); protected: Event _event; PlEngine* _plEngine; + std::string _name; + std::string _sessionId; }; #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index f874c86..eef8e51 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -27,7 +27,7 @@ XPathDataModel::XPathDataModel() { boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr<XPathDataModel> dm = boost::shared_ptr<XPathDataModel>(new XPathDataModel()); dm->_interpreter = interpreter; -// dm->_xpath.setVariableResolver(_varResolver); + // dm->_xpath->setVariableCompileTimeResolver(_varCTResolver); // dm->_xpath->setNamespaceContext(interpreter->getNSContext()); @@ -39,21 +39,21 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr dm->_doc = dm->_domFactory.createDocument("http://www.w3.org/2005/07/scxml", "", 0); dm->_datamodel = dm->_doc.createElement("datamodel"); dm->_doc.appendChild(dm->_datamodel); - + Element<std::string> ioProcElem = dm->_doc.createElement("data"); ioProcElem.setAttribute("id", "_ioprocessors"); std::map<std::string, IOProcessor>::const_iterator ioProcIter = interpreter->getIOProcessors().begin(); while(ioProcIter != interpreter->getIOProcessors().end()) { Element<std::string> ioProc = dm->_doc.createElement("processor"); ioProc.setAttribute("name", ioProcIter->first); - + Data ioProcData = ioProcIter->second.getDataModelVariables(); Element<std::string> ioProcLoc = dm->_doc.createElement("location"); Text<std::string> ioProcLocText = dm->_doc.createTextNode(ioProcData.compound["location"].atom); ioProcLoc.appendChild(ioProcLocText); ioProc.appendChild(ioProcLoc); ioProcElem.appendChild(ioProc); - + ioProcIter++; } dm->_datamodel.appendChild(ioProcElem); @@ -61,8 +61,7 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr NodeSet<std::string> ioProcNodeSet; ioProcNodeSet.push_back(ioProcElem); dm->_varResolver.setVariable("_ioprocessors", ioProcNodeSet); - - + Element<std::string> sessIdElem = dm->_doc.createElement("data"); sessIdElem.setAttribute("id", "_sessionid"); Text<std::string> sessIdText = dm->_doc.createTextNode(interpreter->getSessionId()); @@ -73,13 +72,13 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr sessIdNodeSet.push_back(sessIdElem); dm->_varResolver.setVariable("_sessionid", sessIdNodeSet); - + Element<std::string> nameElem = dm->_doc.createElement("data"); nameElem.setAttribute("id", "_name"); Text<std::string> nameText = dm->_doc.createTextNode(interpreter->getName()); nameElem.appendChild(nameText); dm->_datamodel.appendChild(nameElem); - + NodeSet<std::string> nameNodeSet; nameNodeSet.push_back(nameElem); dm->_varResolver.setVariable("_name", nameNodeSet); @@ -104,7 +103,7 @@ void XPathDataModel::setEvent(const Event& event) { eventElem.setAttribute("id", "_event"); Element<std::string> eventDataElem = _doc.createElement("data"); - + NodeSet<std::string> eventNodeSet; if (event.params.size() > 0) { std::multimap<std::string, std::string>::const_iterator paramIter = event.params.begin(); @@ -131,14 +130,17 @@ void XPathDataModel::setEvent(const Event& event) { } } if (event.content.size() > 0) { - eventDataElem.setNodeValue(event.content); + Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(event.content).c_str()); + eventDataElem.appendChild(textNode); + } + if (event.dom) { + Node<std::string> importedNode = _doc.importNode(event.dom.getFirstChild(), true); + eventDataElem.appendChild(importedNode); } - + eventElem.appendChild(eventDataElem); eventNodeSet.push_back(eventElem); - -// std::cout << eventElem << std::endl; - + // do we need to replace an existing event? Node<std::string> oldEventElem = _datamodel.getFirstChild(); while(oldEventElem) { @@ -148,7 +150,7 @@ void XPathDataModel::setEvent(const Event& event) { } oldEventElem = oldEventElem.getNextSibling(); } - + if (oldEventElem) { _datamodel.replaceChild(eventElem, oldEventElem); } else { @@ -167,7 +169,7 @@ bool XPathDataModel::validate(const std::string& location, const std::string& sc } uint32_t XPathDataModel::getLength(const std::string& expr) { - return 0; + return 0; } void XPathDataModel::eval(const std::string& expr) { @@ -193,9 +195,87 @@ double XPathDataModel::evalAsNumber(const std::string& expr) { return result.asNumber(); } +void XPathDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) { + std::string location; + if (HAS_ATTR(assignElem, "id")) { + location = ATTR(assignElem, "id"); + } else if (HAS_ATTR(assignElem, "location")) { + location = ATTR(assignElem, "location"); + } + + XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); + NodeSet<std::string> nodeSet; + if (doc) { + nodeSet.push_back(doc.getDocumentElement()); + assign(key, nodeSet, assignElem); + } else if (content.length() > 0) { + Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(content)); + nodeSet.push_back(textNode); + assign(key, nodeSet, assignElem); + } else if (HAS_ATTR(assignElem, "expr")) { + XPathValue<std::string> value = _xpath.evaluate_expr(ATTR(assignElem, "expr"), _doc); + assign(key, value, assignElem); + } else { + LOG(ERROR) << "assign element has no content"; + } + + std::cout << _datamodel << std::endl; +} + +void XPathDataModel::assign(const std::string& location, const Data& data) { + +} + +void XPathDataModel::init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) { + std::string location; + if (HAS_ATTR(dataElem, "id")) { + location = ATTR(dataElem, "id"); + } else if (HAS_ATTR(dataElem, "location")) { + location = ATTR(dataElem, "location"); + } + + Element<std::string> container = _doc.createElement("data"); + container.setAttribute("id", location); + if (doc) { + Element<std::string> data = doc.getDocumentElement(); + if (data.hasChildNodes()) { + Node<std::string> dataClone = _doc.importNode(data, true); + container.appendChild(dataClone); + } + } else if (content.length() > 0) { + Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(content)); + container.appendChild(textNode); + } else if (HAS_ATTR(dataElem, "expr")) { + XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc); + XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); + assign(key, expr, dataElem); + for (int i = 0; expr.asNodeSet().size(); i++) + container.appendChild(expr.asNodeSet()[i]); + } else { + LOG(ERROR) << "data element has no content"; + } + _datamodel.appendChild(container); + + // put data element into nodeset and bind to xpath variable + NodeSet<std::string> nodeSet; + nodeSet.push_back(container); + _varResolver.setVariable(location, nodeSet); + + std::cout << _datamodel << std::endl; +} + +void XPathDataModel::init(const std::string& location, const Data& data) { + +} + +#if 0 void XPathDataModel::assign(const std::string& location, - const Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { + const Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& dataElem) { XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); NodeSet<std::string> nodeSet; nodeSet.push_back(doc.getDocumentElement()); @@ -203,15 +283,15 @@ void XPathDataModel::assign(const std::string& location, } void XPathDataModel::assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { + const Data& data, + const Arabica::DOM::Element<std::string>& dataElem) { // assert(false); // std::cout << location << " = " << data << std::endl; } void XPathDataModel::assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { + const std::string& expr, + const Arabica::DOM::Element<std::string>& dataElem) { std::string realExpr = (HAS_ATTR(dataElem, "expr") ? ATTR(dataElem, "expr") : expr); XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); XPathValue<std::string> value = _xpath.evaluate_expr(realExpr, _doc); @@ -219,8 +299,8 @@ void XPathDataModel::assign(const std::string& location, } void XPathDataModel::init(const std::string& location, - const Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem) { + const Document<std::string>& doc, + const Arabica::DOM::Element<std::string>& dataElem) { Element<std::string> container = _doc.createElement("data"); container.setAttribute("id", location); Element<std::string> data = doc.getDocumentElement(); @@ -229,7 +309,7 @@ void XPathDataModel::init(const std::string& location, container.appendChild(dataClone); } _datamodel.appendChild(container); - + // put data element into nodeset and bind to xpath variable NodeSet<std::string> nodeSet; nodeSet.push_back(container); @@ -237,11 +317,11 @@ void XPathDataModel::init(const std::string& location, } void XPathDataModel::init(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem) { + const std::string& expr, + const Arabica::DOM::Element<std::string>& dataElem) { Element<std::string> data = _doc.createElement("data"); data.setAttribute("id", location); - + if (expr.length() > 0) { Text<std::string> textNode = _doc.createTextNode(expr.c_str()); data.appendChild(textNode); @@ -255,182 +335,195 @@ void XPathDataModel::init(const std::string& location, } void XPathDataModel::init(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem) { - assert(false); + const Data& data, + const Arabica::DOM::Element<std::string>& dataElem) { +// XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); + init(location, data.atom, dataElem); } +#endif void XPathDataModel::assign(XPathValue<std::string>& key, - const XPathValue<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem) { + const XPathValue<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem) { switch (value.type()) { - case STRING: - assign(key, value.asString(), assignElem); - break; - case BOOL: - assign(key, value.asBool(), assignElem); - break; - case NUMBER: - assign(key, value.asNumber(), assignElem); - break; - case NODE_SET: - assign(key, value.asNodeSet(), assignElem); - break; - case ANY: - throw Event("error.execution", Event::PLATFORM); + case STRING: + assign(key, value.asString(), assignElem); + break; + case BOOL: + assign(key, value.asBool(), assignElem); + break; + case NUMBER: + assign(key, value.asNumber(), assignElem); + break; + case NODE_SET: + assign(key, value.asNodeSet(), assignElem); + break; + case ANY: + throw Event("error.execution", Event::PLATFORM); } } void XPathDataModel::assign(XPathValue<std::string>& key, - const std::string& value, - const Arabica::DOM::Element<std::string>& assignElem) { + const std::string& value, + const Arabica::DOM::Element<std::string>& assignElem) { switch (key.type()) { - case NODE_SET: { - if (key.asNodeSet().size() == 0) - return; - Node<std::string> node = key.asNodeSet()[0]; + case NODE_SET: { + if (key.asNodeSet().size() == 0) + return; + for (int i = 0; i < key.asNodeSet().size(); i++) { + Node<std::string> node = key.asNodeSet()[i]; switch (node.getNodeType()) { - case Node_base::ATTRIBUTE_NODE: { - Attr<std::string> attr(node); - attr.setValue(value); - break; - } - case Node_base::TEXT_NODE: { - Text<std::string> text(node); - text.setNodeValue(value); - break; - } - case Node_base::ELEMENT_NODE: { - Element<std::string> element(node); - if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "addattribute")) { - // addattribute: Add an attribute with the name specified by 'attr' - // and value specified by 'expr' to the node specified by 'location'. - if (!HAS_ATTR(assignElem, "attr")) - throw Event("error.execution", Event::PLATFORM); - element.setAttribute(ATTR(assignElem, "attr"), value); - } - break; + case Node_base::ATTRIBUTE_NODE: { + Attr<std::string> attr(node); + attr.setValue(value); + break; + } + case Node_base::TEXT_NODE: { + Text<std::string> text(node); + text.setNodeValue(value); + break; + } + case Node_base::ELEMENT_NODE: { + Element<std::string> element(node); + if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "addattribute")) { + // addattribute: Add an attribute with the name specified by 'attr' + // and value specified by 'expr' to the node specified by 'location'. + if (!HAS_ATTR(assignElem, "attr")) + throw Event("error.execution", Event::PLATFORM); + element.setAttribute(ATTR(assignElem, "attr"), value); + } else { + /// test 547 + while(element.hasChildNodes()) + element.removeChild(element.getChildNodes().item(0)); + Text<std::string> text = _doc.createTextNode(value); + element.appendChild(text); } - default: - throw Event("error.execution", Event::PLATFORM); - break; + break; + } + default: + throw Event("error.execution", Event::PLATFORM); + break; } - break; } - case STRING: - case BOOL: - case NUMBER: - case ANY: - throw Event("error.execution", Event::PLATFORM); - break; - default: - break; + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); + break; + default: + break; } } void XPathDataModel::assign(XPathValue<std::string>& key, - const double value, - const Arabica::DOM::Element<std::string>& assignElem) { + const double value, + const Arabica::DOM::Element<std::string>& assignElem) { + assign(key, toStr(value), assignElem); } void XPathDataModel::assign(XPathValue<std::string>& key, - const bool value, - const Arabica::DOM::Element<std::string>& assignElem) { + const bool value, + const Arabica::DOM::Element<std::string>& assignElem) { } void XPathDataModel::assign(XPathValue<std::string>& key, - const NodeSet<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem) { + const NodeSet<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem) { switch (key.type()) { - case NODE_SET: { - if (key.asNodeSet().size() == 0) - return; - Node<std::string> node = key.asNodeSet()[0]; + case NODE_SET: { + if (key.asNodeSet().size() == 0) + return; + for (int i = 0; i < key.asNodeSet().size(); i++) { + Node<std::string> node = key.asNodeSet()[i]; switch (node.getNodeType()) { - case Node_base::ELEMENT_NODE: { - Element<std::string> element(node); - if (false) { - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "firstchild")) { - // firstchild: Insert the value specified by 'expr' before all of the children at 'location'. - for (int i = value.size(); i; i--) { - Node<std::string> importedNode = _doc.importNode(value[i-1], true); - element.insertBefore(importedNode, element.getFirstChild()); - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "lastchild")) { - // lastchild: Insert the value specified by 'expr' after all of the children at 'location'. - for (int i = 0; i < value.size(); i++) { - Node<std::string> importedNode = _doc.importNode(value[i], true); - element.appendChild(importedNode); - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { - // previoussibling: Insert the value specified by 'expr' before the - // node specified by 'location', keeping the same parent. - Node<std::string> parent = element.getParentNode(); - if (!parent) - throw Event("error.execution", Event::PLATFORM); - for (int i = 0; i < value.size(); i++) { - Node<std::string> importedNode = _doc.importNode(value[i], true); - parent.insertBefore(importedNode, element); - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { - // nextsibling: Insert the value specified by 'expr' after the node - // specified by 'location', keeping the same parent. - Node<std::string> parent = element.getParentNode(); - if (!parent) - throw Event("error.execution", Event::PLATFORM); - for (int i = value.size(); i; i--) { - Node<std::string> importedNode = _doc.importNode(value[i-1], true); - Node<std::string> nextSibling = element.getNextSibling(); - if (nextSibling) { - parent.insertBefore(importedNode, element.getNextSibling()); - } else { - parent.appendChild(importedNode); - } - } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { - // replace: Replace the node specified by 'location' by the value specified by 'expr'. - Node<std::string> parent = element.getParentNode(); - if (!parent) - throw Event("error.execution", Event::PLATFORM); - if (value.size() != 1) - throw Event("error.execution", Event::PLATFORM); - Node<std::string> importedNode = _doc.importNode(value[0], true); - parent.replaceChild(importedNode, element); - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { - // delete: Delete the node specified by 'location'. ('expr' is ignored.). - Node<std::string> parent = element.getParentNode(); - if (!parent) - throw Event("error.execution", Event::PLATFORM); - parent.removeChild(element); - } else { - // replacechildren: Replace all the children at 'location' with the value specified by 'expr'. - while(element.hasChildNodes()) - element.removeChild(element.getChildNodes().item(0)); - for (int i = 0; i < value.size(); i++) { - Node<std::string> importedNode = _doc.importNode(value[i], true); - element.appendChild(importedNode); + case Node_base::ELEMENT_NODE: { + Element<std::string> element(node); + if (false) { + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "firstchild")) { + // firstchild: Insert the value specified by 'expr' before all of the children at 'location'. + for (int i = value.size(); i; i--) { + Node<std::string> importedNode = _doc.importNode(value[i-1], true); + element.insertBefore(importedNode, element.getFirstChild()); + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "lastchild")) { + // lastchild: Insert the value specified by 'expr' after all of the children at 'location'. + for (int i = 0; i < value.size(); i++) { + Node<std::string> importedNode = _doc.importNode(value[i], true); + element.appendChild(importedNode); + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { + // previoussibling: Insert the value specified by 'expr' before the + // node specified by 'location', keeping the same parent. + Node<std::string> parent = element.getParentNode(); + if (!parent) + throw Event("error.execution", Event::PLATFORM); + for (int i = 0; i < value.size(); i++) { + Node<std::string> importedNode = _doc.importNode(value[i], true); + parent.insertBefore(importedNode, element); + } + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { + // nextsibling: Insert the value specified by 'expr' after the node + // specified by 'location', keeping the same parent. + Node<std::string> parent = element.getParentNode(); + if (!parent) + throw Event("error.execution", Event::PLATFORM); + for (int i = value.size(); i; i--) { + Node<std::string> importedNode = _doc.importNode(value[i-1], true); + Node<std::string> nextSibling = element.getNextSibling(); + if (nextSibling) { + parent.insertBefore(importedNode, element.getNextSibling()); + } else { + parent.appendChild(importedNode); } } - break; + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { + // replace: Replace the node specified by 'location' by the value specified by 'expr'. + Node<std::string> parent = element.getParentNode(); + if (!parent) + throw Event("error.execution", Event::PLATFORM); + if (value.size() != 1) + throw Event("error.execution", Event::PLATFORM); + Node<std::string> importedNode = _doc.importNode(value[0], true); + parent.replaceChild(importedNode, element); + } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { + // delete: Delete the node specified by 'location'. ('expr' is ignored.). + Node<std::string> parent = element.getParentNode(); + if (!parent) + throw Event("error.execution", Event::PLATFORM); + parent.removeChild(element); + } else { + // replacechildren: Replace all the children at 'location' with the value specified by 'expr'. + while(element.hasChildNodes()) + element.removeChild(element.getChildNodes().item(0)); + for (int i = 0; i < value.size(); i++) { + Node<std::string> importedNode = _doc.importNode(value[i], true); + element.appendChild(importedNode); + } } - default: - throw Event("error.execution", Event::PLATFORM); - break; + break; + } + default: + throw Event("error.execution", Event::PLATFORM); + break; } - break; } - case STRING: - case BOOL: - case NUMBER: - case ANY: - throw Event("error.execution", Event::PLATFORM); - break; + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); + break; } } XPathValue<std::string> - NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri, - const std::string& name) const { +NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri, + const std::string& name) const { std::map<std::string, NodeSet<std::string> >::const_iterator n = _variables.find(name); if(n == _variables.end()) { throw Event("error.execution"); @@ -439,15 +532,15 @@ XPathValue<std::string> } XPathFunction<std::string>* - XPathFunctionResolver::resolveFunction(const std::string& namespace_uri, - const std::string& name, - const std::vector<XPathExpression<std::string> >& argExprs) const { +XPathFunctionResolver::resolveFunction(const std::string& namespace_uri, + const std::string& name, + const std::vector<XPathExpression<std::string> >& argExprs) const { if (boost::iequals(name, "in")) { return new XPathFunctionIn(1, -1, argExprs, _interpreter); } return _xpathFuncRes.resolveFunction(namespace_uri, name, argExprs); } - + std::vector<std::pair<std::string, std::string> > XPathFunctionResolver::validNames() const { std::vector<std::pair<std::string, std::string> > names = _xpathFuncRes.validNames(); names.push_back(std::make_pair("", "In")); @@ -455,7 +548,7 @@ std::vector<std::pair<std::string, std::string> > XPathFunctionResolver::validNa } bool XPathFunctionIn::doEvaluate(const Node<std::string>& context, - const ExecutionContext<std::string>& executionContext) const { + const ExecutionContext<std::string>& executionContext) const { for (int i = 0; i < argCount(); i++) { XPathValue<std::string> stateName = arg(i, context, executionContext); if (stateName.type() == STRING) { diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h index d028129..5f5952c 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h @@ -18,42 +18,44 @@ namespace uscxml { class XPathFunctionIn : public Arabica::XPath::BooleanXPathFunction<std::string> { public: XPathFunctionIn(int minArgs, - int maxArgs, - const std::vector<Arabica::XPath::XPathExpression<std::string> >& args, - InterpreterImpl* interpreter) : + int maxArgs, + const std::vector<Arabica::XPath::XPathExpression<std::string> >& args, + InterpreterImpl* interpreter) : BooleanXPathFunction(minArgs, maxArgs, args), _interpreter(interpreter) {} protected: bool doEvaluate(const Arabica::DOM::Node<std::string>& context, - const Arabica::XPath::ExecutionContext<std::string>& executionContext) const; + const Arabica::XPath::ExecutionContext<std::string>& executionContext) const; InterpreterImpl* _interpreter; }; class XPathFunctionResolver : public Arabica::XPath::FunctionResolver<std::string> { public: virtual ~XPathFunctionResolver() { } - - virtual Arabica::XPath::XPathFunction<std::string>* - resolveFunction(const std::string& namespace_uri, - const std::string& name, - const std::vector<Arabica::XPath::XPathExpression<std::string> >& argExprs) const; - - virtual std::vector<std::pair<std::string, std::string> > validNames() const; - void setInterpreter(InterpreterImpl* interpreter) { _interpreter = interpreter; } + + virtual Arabica::XPath::XPathFunction<std::string>* + resolveFunction(const std::string& namespace_uri, + const std::string& name, + const std::vector<Arabica::XPath::XPathExpression<std::string> >& argExprs) const; + + virtual std::vector<std::pair<std::string, std::string> > validNames() const; + void setInterpreter(InterpreterImpl* interpreter) { + _interpreter = interpreter; + } protected: Arabica::XPath::StandardXPathFunctionResolver<std::string> _xpathFuncRes; InterpreterImpl* _interpreter; }; - + class NodeSetVariableResolver : public Arabica::XPath::VariableResolver<std::string> { public: Arabica::XPath::XPathValue<std::string> resolveVariable(const std::string& namepaceUri, - const std::string& name) const; + const std::string& name) const; void setVariable(const std::string& name, const Arabica::XPath::NodeSet<std::string>& value) { _variables[name] = value; } - + private: std::map<std::string, Arabica::XPath::NodeSet<std::string> > _variables; }; @@ -80,25 +82,15 @@ public: virtual void popContext(); virtual void eval(const std::string& expr); - virtual void assign(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& assignElem); - virtual void assign(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& assignElem); - virtual void assign(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& assignElem); - - virtual void init(const std::string& location, - const Arabica::DOM::Document<std::string>& doc, - const Arabica::DOM::Element<std::string>& dataElem); - virtual void init(const std::string& location, - const std::string& expr, - const Arabica::DOM::Element<std::string>& dataElem); - virtual void init(const std::string& location, - const Data& data, - const Arabica::DOM::Element<std::string>& dataElem); + virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content); + virtual void assign(const std::string& location, const Data& data); + + virtual void init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content); + virtual void init(const std::string& location, const Data& data); virtual Data getStringAsData(const std::string& content); virtual bool isDeclared(const std::string& expr); @@ -114,21 +106,21 @@ protected: Arabica::DOM::Document<std::string> _doc; void assign(Arabica::XPath::XPathValue<std::string>& key, - const Arabica::XPath::XPathValue<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem); + const Arabica::XPath::XPathValue<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem); void assign(Arabica::XPath::XPathValue<std::string>& key, - const std::string& value, - const Arabica::DOM::Element<std::string>& assignElem); + const std::string& value, + const Arabica::DOM::Element<std::string>& assignElem); void assign(Arabica::XPath::XPathValue<std::string>& key, - const double value, - const Arabica::DOM::Element<std::string>& assignElem); + const double value, + const Arabica::DOM::Element<std::string>& assignElem); void assign(Arabica::XPath::XPathValue<std::string>& key, - const bool value, - const Arabica::DOM::Element<std::string>& assignElem); + const bool value, + const Arabica::DOM::Element<std::string>& assignElem); void assign(Arabica::XPath::XPathValue<std::string>& key, - const Arabica::XPath::NodeSet<std::string>& value, - const Arabica::DOM::Element<std::string>& assignElem); - + const Arabica::XPath::NodeSet<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem); + NodeSetVariableResolver _varResolver; XPathFunctionResolver _funcResolver; |