From 3d3f434c5be68a7e2b86ecccbaba40887852db99 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Sun, 28 Apr 2013 22:59:38 +0200 Subject: More work on prolog datamodel --- CMakeLists.txt | 4 +- src/uscxml/Message.cpp | 24 ++++++ src/uscxml/Message.h | 4 +- .../plugins/datamodel/prolog/swi/SWIDataModel.cpp | 96 ++++++++++++++++++---- .../ioprocessor/basichttp/BasicHTTPIOProcessor.cpp | 18 +++- test/samples/uscxml/test-prolog.scxml | 33 +++++--- test/samples/uscxml/test-prolog2.scxml | 38 +++++++++ 7 files changed, 183 insertions(+), 34 deletions(-) create mode 100644 test/samples/uscxml/test-prolog2.scxml diff --git a/CMakeLists.txt b/CMakeLists.txt index 3475c4d..bdd2f45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,7 +327,9 @@ if (NOT WIN32) set(XML_LIBRARIES ${LIBXML2_LIBRARIES}) list (APPEND USCXML_CORE_LIBS "dl") list (APPEND USCXML_CORE_LIBS "pthread") - list (APPEND USCXML_CORE_LIBS "rt") + if (NOT APPLE) + list (APPEND USCXML_CORE_LIBS "rt") + endif() elseif(WIN32) list (APPEND XML_LIBRARIES "Ws2_32") list (APPEND XML_LIBRARIES "Winmm") diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index 27e01e2..67198ea 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -308,6 +308,30 @@ Data Data::fromJSON(const std::string& jsonString) { return data; } +void Event::initContent(const std::string& content) { + // try to parse as JSON + Data json = Data::fromJSON(content); + if (json) { + data = json; + return; + } + + // try to parse as XML + Arabica::SAX2DOM::Parser parser; + Arabica::SAX::CatchErrorHandler errorHandler; + parser.setErrorHandler(errorHandler); + + std::istringstream is(content); + Arabica::SAX::InputSource inputSource; + inputSource.setByteStream(is); + if (parser.parse(inputSource)) { + dom = parser.getDocument(); + return; + } + + this->content = content; +} + Event Event::fromXML(const std::string& xmlString) { Arabica::SAX2DOM::Parser eventParser; Arabica::SAX::CatchErrorHandler errorHandler; diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index ea1e8ab..3bb30fc 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -173,10 +173,12 @@ public: Data getData() { return data; } - void setData(const Data& invokeId) { + void setData(const Data& data) { this->data = data; } + void initContent(const std::string& content); + static Event fromXML(const std::string& xmlString); Arabica::DOM::Document toDocument(); std::string toXMLString() { diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 0c65fa9..7e63174 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -124,10 +124,10 @@ void SWIDataModel::setEvent(const Event& event) { PlCall("retractall(event(_))"); // simple values - PlCall("assert", PlCompound("event", PlCompound("name", PlString(event.name.c_str())))); + PlCall("assert", PlCompound("event", PlCompound("name", PlTerm(event.name.c_str())))); PlCall("assert", PlCompound("event", PlCompound("origin", PlString(event.origin.c_str())))); PlCall("assert", PlCompound("event", PlCompound("origintype", PlString(event.invokeid.c_str())))); - PlCall("assert", PlCompound("event", PlCompound("invokeid", PlString(event.origintype.c_str())))); + PlCall("assert", PlCompound("event", PlCompound("invokeid", PlTerm(event.origintype.c_str())))); PlCall("assert", PlCompound("event", PlCompound("raw", PlString(event.raw.c_str())))); // event.type @@ -143,11 +143,11 @@ void SWIDataModel::setEvent(const Event& event) { type = "external"; break; } - PlCall("assert", PlCompound("event", PlCompound("type", PlString(type.c_str())))); + PlCall("assert", PlCompound("event", PlCompound("type", PlTerm(type.c_str())))); // event.sendid if (!event.hideSendId) - PlCall("assert", PlCompound("event", PlCompound("sendid", PlString(event.sendid.c_str())))); + PlCall("assert", PlCompound("event", PlCompound("sendid", PlTerm(event.sendid.c_str())))); // event.data URL domUrl; @@ -170,9 +170,9 @@ void SWIDataModel::setEvent(const Event& event) { paramIter = event.params.upper_bound(paramIter->first); } if (uniqueKeys > 0) { - std::stringstream paramArray; paramIter = event.params.begin(); for(int i = 0; paramIter != event.params.end(); i++) { + std::stringstream paramArray; Event::params_t::const_iterator lastValueIter = event.params.upper_bound(paramIter->first); paramArray << paramIter->first << "(["; @@ -185,7 +185,8 @@ void SWIDataModel::setEvent(const Event& event) { } paramArray << "])"; std::stringstream paramExpr; - paramExpr << "assert(event(param(" << paramArray << ")))"; + paramExpr << "assert(event(param(" << paramArray.str() << ")))"; + //std::cout << paramExpr.str() << std::endl; PlCall(paramExpr.str().c_str()); paramIter = lastValueIter; @@ -208,15 +209,46 @@ bool SWIDataModel::validate(const std::string& location, const std::string& sche } uint32_t SWIDataModel::getLength(const std::string& expr) { -// std::cout << "SWIDataModel::getLength" << std::endl; - return 0; + 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); + uint32_t length = 0; + while(query.next_solution() > 0) + length++; + return length; } void SWIDataModel::setForeach(const std::string& item, const std::string& array, const std::string& index, uint32_t iteration) { - // std::cout << "SWIDataModel::setForeach" << std::endl; + PlCompound compound(array.c_str()); + PlCompound orig(array.c_str()); + PlTermv termv(compound.arity()); + for (int i = 0; i < compound.arity(); i++) { + termv[i] = compound[i + 1]; + } + { + int tmp = iteration + 1; + PlQuery query(compound.name(), termv); + while (tmp) { + query.next_solution(); + tmp--; + } + } + PlCall("retractall", PlCompound(index.c_str(), 1)); + PlCall("retractall", PlCompound(item.c_str(), 1)); + PlCall("assert", PlCompound(index.c_str(), PlTerm((long)iteration))); + + std::map vars = resolveAtoms(compound, orig); + std::map::iterator varIter = vars.begin(); + while(varIter != vars.end()) { + PlCall("assert", PlCompound(item.c_str(), varIter->second)); + varIter++; + } } void SWIDataModel::eval(const std::string& expr) { @@ -294,11 +326,45 @@ void SWIDataModel::assign(const Arabica::DOM::Element& assignElem, const Arabica::DOM::Document& doc, const std::string& content) { std::string expr = content; + std::string predicate; if (HAS_ATTR(assignElem, "expr")) { expr = ATTR(assignElem, "expr"); } - if (expr.length() > 0) + if (HAS_ATTR(assignElem, "id")) + predicate = ATTR(assignElem, "id"); + if (HAS_ATTR(assignElem, "location")) + predicate = ATTR(assignElem, "location"); + + if (predicate.size() > 0) { + size_t aritySep = predicate.find_first_of("/"); + if (aritySep != std::string::npos) { + std::string functor = predicate.substr(0, aritySep); + std::string arity = predicate.substr(aritySep + 1); + std::string callAssert = "assert"; + if (HAS_ATTR(assignElem, "type")) { + std::string type = ATTR(assignElem, "type"); + if (boost::iequals(type, "retract")) { + PlCall("retractall", PlCompound(functor.c_str(), strTo(arity))); + } else if(boost::iequals(type, "append")) { + callAssert = "assertz"; + } else if(boost::iequals(type, "prepend")) { + callAssert = "asserta"; + } + } + // treat content as . seperated facts + std::stringstream factStream(content); + std::string item; + while(std::getline(factStream, item, '.')) { + std::string fact = boost::trim_copy(item); + if (fact.length() == 0) + continue; + PlCall((callAssert + "(" + functor + "(" + fact + "))").c_str()); + } + + } + } else if (expr.length() > 0) { eval(expr); + } } void SWIDataModel::assign(const std::string& location, const Data& data) { @@ -308,15 +374,11 @@ void SWIDataModel::assign(const std::string& location, const Data& data) { void SWIDataModel::init(const Arabica::DOM::Element& dataElem, const Arabica::DOM::Document& doc, const std::string& content) { - std::string key; - if (HAS_ATTR(dataElem, "id")) { - key = ATTR(dataElem, "id"); - } else if (HAS_ATTR(dataElem, "location")) { - key = ATTR(dataElem, "location"); - } assign(dataElem, doc, content); } -void SWIDataModel::init(const std::string& location, const Data& data) {} +void SWIDataModel::init(const std::string& location, const Data& data) { + assign(location, data); +} bool SWIDataModel::isDeclared(const std::string& expr) { return true; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index c8d86fa..6ddb83c 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -84,6 +84,8 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { std::string value = evhttp_decode_uri(term.substr(split + 1).c_str()); if (boost::iequals(key, "_scxmleventname")) { reqEvent.name = value; + } else if (boost::iequals(key, "content")) { + reqEvent.initContent(value); } else { reqEvent.data.compound[key] = value; reqEvent.params.insert(std::make_pair(key, value)); @@ -187,11 +189,19 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { } // content - if (kvps.str().size() > 0) { - targetURL.setOutContent(kvps.str()); - } else if (req.content.size() > 0) { - targetURL.setOutContent(req.content); + + if (req.content.size() > 0) { + kvps << kvpSeperator << evhttp_encode_uri("content") << "=" << evhttp_encode_uri(req.content.c_str()); + kvpSeperator = "&"; + } + if (req.dom) { + std::stringstream xmlStream; + xmlStream << req.dom; + kvps << kvpSeperator << evhttp_encode_uri("content") << "=" << evhttp_encode_uri(xmlStream.str().c_str()); + kvpSeperator = "&"; } + targetURL.setOutContent(kvps.str()); + targetURL.setRequestType("post"); targetURL.addMonitor(this); diff --git a/test/samples/uscxml/test-prolog.scxml b/test/samples/uscxml/test-prolog.scxml index 8d171e6..e802c8e 100644 --- a/test/samples/uscxml/test-prolog.scxml +++ b/test/samples/uscxml/test-prolog.scxml @@ -11,6 +11,8 @@ + :- multifile father/2. + :- multifile mother/2. father(bob, jim). father(bob, john). father(bob, jack). @@ -19,13 +21,13 @@ mother(martha, jack). - + - + - +