diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-05-01 23:25:28 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-05-01 23:25:28 (GMT) |
commit | 0202a8780179c710b2596e25567d4cf480dca277 (patch) | |
tree | 4c33ead20947aad00bda5055648248e84842a4e7 | |
parent | 1dc899c70362de2eed1f6dc074dc5238df0c7f3c (diff) | |
download | uscxml-0202a8780179c710b2596e25567d4cf480dca277.zip uscxml-0202a8780179c710b2596e25567d4cf480dca277.tar.gz uscxml-0202a8780179c710b2596e25567d4cf480dca277.tar.bz2 |
More work on Prolog datamodel
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | src/uscxml/Message.cpp | 12 | ||||
-rw-r--r-- | src/uscxml/Message.h | 3 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp | 71 | ||||
-rw-r--r-- | test/samples/uscxml/test-prolog.scxml | 185 | ||||
-rw-r--r-- | test/samples/uscxml/test-prolog2.scxml | 40 |
6 files changed, 126 insertions, 193 deletions
@@ -9,10 +9,10 @@ There is no technical reason for it not to run on iOS and Android as well, but w the respective build-process and did not precompile required libraries. * <b>Datamodels</b> - * Full ECMAScript datamodel using Google's v8 and JavaScriptCore (JSC is incomplete) - * Full NULL datamodel with required <tt>In</tt> predicate - * Early Prolog datamodel using SWI prolog - * Rudimentary support for XPath datamodel (W3C tests not yet implementable) + * Full [ECMAScript datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/ecmascript) using Google's v8 and JavaScriptCore (JSC is incomplete) + * Full [NULL datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/null) with required <tt>In</tt> predicate + * Early [Prolog datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/prolog/swi) using SWI prolog + * Rudimentary support for [XPath datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/xpath) * <b>Invokers</b> * <tt>scxml</tt>: Invoke a nested scxml interpreter * <tt>dirmon</tt>: Watches a directory for changes to files diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index 67198ea..8a65ed2 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -111,6 +111,14 @@ Arabica::DOM::Document<std::string> Data::toDocument() { } Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const { + return getFirstDOMElement(dom); +} + +Arabica::DOM::Document<std::string> Event::getStrippedDOM() const { + return getStrippedDOM(dom); +} + +Arabica::DOM::Node<std::string> Event::getFirstDOMElement(const Arabica::DOM::Document<std::string> dom) { Arabica::DOM::Node<std::string> data = dom.getDocumentElement().getFirstChild(); while (data) { if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) { @@ -125,11 +133,11 @@ Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const { return data; } -Arabica::DOM::Document<std::string> Event::getStrippedDOM() const { +Arabica::DOM::Document<std::string> Event::getStrippedDOM(const Arabica::DOM::Document<std::string> dom) { Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); Arabica::DOM::Document<std::string> document = domFactory.createDocument("", "", 0); if (dom) { - document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(), true)); + document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true)); } return document; } diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 3bb30fc..1d8cb53 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -142,6 +142,9 @@ public: Arabica::DOM::Node<std::string> getFirstDOMElement() const; Arabica::DOM::Document<std::string> getStrippedDOM() const; + static Arabica::DOM::Node<std::string> getFirstDOMElement(const Arabica::DOM::Document<std::string> dom); + static Arabica::DOM::Document<std::string> getStrippedDOM(const Arabica::DOM::Document<std::string> dom); + std::string getRaw() { return raw; } diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 7e63174..b031c00 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -50,6 +50,13 @@ boost::shared_ptr<DataModelImpl> SWIDataModel::create(InterpreterImpl* interpret // load SWI XML parser PlCall("use_module", PlCompound("library", PlTerm("sgml"))); + + // load json parser + PlCall("use_module", PlCompound("library", PlTerm("http/json"))); + PlCall("use_module", PlCompound("library", PlTerm("http/json_convert"))); + + // use atoms for double quoted + PlCall("set_prolog_flag(double_quotes,atom)."); // set system variables PlCall("assert", PlCompound("sessionid", PlTerm(PlString(dm->_interpreter->getSessionId().c_str())))); @@ -336,21 +343,41 @@ void SWIDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem, 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<long>(arity))); - } else if(boost::iequals(type, "append")) { - callAssert = "assertz"; - } else if(boost::iequals(type, "prepend")) { - callAssert = "asserta"; - } + std::string callAssert = "assert"; + std::string type; + if (HAS_ATTR(assignElem, "type")) { + type = ATTR(assignElem, "type"); + if(boost::iequals(type, "append")) { + callAssert = "assertz"; + } else if(boost::iequals(type, "prepend")) { + callAssert = "asserta"; + } + } + + URL domUrl; + Data json; + if (!doc) + json = Data::fromJSON(expr); + if (doc) { + std::stringstream dataInitStr; + std::stringstream xmlDoc; + Arabica::DOM::Node<std::string> node = Event::getFirstDOMElement(doc); + while(node) { + xmlDoc << node; + node = node.getNextSibling(); } + domUrl = URL::toLocalFile(xmlDoc.str(), ".pl"); + if (boost::iequals(type, "retract")) + PlCall("retractall", PlCompound(predicate.c_str(), 1)); + dataInitStr << "load_xml_file('" << domUrl.asLocalFile(".pl") << "', XML), copy_term(XML,DATA), " << callAssert << "(" << predicate << "(DATA))"; + PlCall(dataInitStr.str().c_str()); + } else if (json) { + std::stringstream dataInitStr; + if (boost::iequals(type, "retract")) + PlCall("retractall", PlCompound(predicate.c_str(), 1)); + dataInitStr << "json_to_prolog(" << expr << ", JSON), assert(" << predicate << "(JSON))"; + PlCall(dataInitStr.str().c_str()); + } else { // treat content as . seperated facts std::stringstream factStream(content); std::string item; @@ -358,12 +385,22 @@ void SWIDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem, std::string fact = boost::trim_copy(item); if (fact.length() == 0) continue; - PlCall((callAssert + "(" + functor + "(" + fact + "))").c_str()); + PlCall((callAssert + "(" + predicate + "(" + fact + "))").c_str()); } - } } else if (expr.length() > 0) { - eval(expr); + if (boost::equals(TAGNAME(assignElem), "data")) { + eval(expr); + } else { + std::stringstream exprStream(expr); + std::string item; + while(std::getline(exprStream, item, '.')) { + std::string plExpr = boost::trim_copy(item); + if (plExpr.length() == 0) + continue; + PlCall(plExpr.c_str()); + } + } } } diff --git a/test/samples/uscxml/test-prolog.scxml b/test/samples/uscxml/test-prolog.scxml index e802c8e..54734cf 100644 --- a/test/samples/uscxml/test-prolog.scxml +++ b/test/samples/uscxml/test-prolog.scxml @@ -1,131 +1,56 @@ -<?xml version="1.0"?> -<scxml datamodel="prolog" initial="start" binding="late"> - <!-- - % see http://www.swi-prolog.org/FAQ/Multifile.html - :- multifile animal/1. - --> - <datamodel> - <!-- - Various possible uses for the data element - --> - - <!-- if no id is given, we assume assertion mode --> - <data> - :- multifile father/2. - :- multifile mother/2. - father(bob, jim). - father(bob, john). - father(bob, jack). - mother(martha, jim). - mother(martha, john). - mother(martha, jack). - </data> - <!-- if id is given, we treat it the name of a predicate --> - <!-- data id="sibling/2"> - jim, john. - jim, jack. - john, jack. - </data --> - <!-- if an id is given, json data is transformed into a prolog compound term --> - <!-- data id="john"> - { - "name": "John", - "age": 25, - "address": { - "streetAddress": "21 2nd Street", - "city": "New York", - }, - "phoneNumbers": [ - { - "type": "home", - "number": "212 555-1234" - }, - { - "type": "fax", - "number": "646 555-4567" - } - ] - } - </data --> - <!-- If an id is given, parse XML as nested compund terms --> - <!--data id="jack"> - <person name="jack" age="27"> - <address> - <street>23 3rd Street</street> - <city>New York</city> - </address> - <phone type="mobile"> - 384 234-5534 - </phone> - </person> - </data --> - </datamodel> - <!-- - scripts are executed in assertion mode - --> - <script> - :- multifile older/2. - older(bob, martha). - older(bob, john). - older(bob, jack). - older(bob, jim). - </script> - <state id="start"> - <onentry> - <!-- - Evaluation to string will return a list of valid solutions for the free variables. - --> - <log label="SessionId" expr="sessionid(X)"/> - <log label="Name" expr="name(X)"/> - - <send event="foo">This is a foo event.</send> - </onentry> - <!-- boolean expressions are true if there is a solution--> - <transition event="foo" cond="older(bob, martha)." target="sending"/> - </state> - <state id="sending"> - <onentry> - <send event="bar" type="basichttp" targetexpr="ioprocessors(basichttp(location(X)))"> - <param name="foo" expr="name(X)" /> - <param name="bar" expr="name(X)" /> - <param name="bar" expr="sessionid(X)" /> - <content> - <person name="jack" age="27"> - <address> - <street>23 3rd Street</street> - <city>New York</city> - </address> - <phone type="mobile"> - 384 234-5534 - </phone> - </person> - </content> - </send> - </onentry> - <transition event="bar" cond="event(name(X)), X='bar'." target="assigning"/> - </state> - <state id="assigning"> - <onentry> - <log label="Index" expr="listing." /> - <foreach array="father(bob, X)" - item="child" - index="index"> - <log label="child" expr="child(X)" /> - <log label="index" expr="index(X)" /> - </foreach> - <raise event="baz" /> - <!-- assigning with retract attribute --> - <!--assign id="older/2" retract="older/2"> - older(jim, john). - older(jim, jack). - older(john, jack). - </assign--> - </onentry> - <transition event="baz" cond="in('assigning')" target="end"/> - </state> - <state id="end" final="true"> - <onentry> - <log label="Listing" expr="listing."/> - </onentry> - </state> +<scxml datamodel="prolog"> + <datamodel> + <data id="father"> + bob, jim. + bob, john. + </data> + <data id=""> + mother(martha, jim). + mother(martha, john). + </data> + <data id="household"> + { + name: "The Bobsons", + members: ['bob', 'martha', 'jim', 'john'] + } + </data> + <data id="childs"> + <child name="jim" father="bob" /> + <child name="john" father="bob" /> + </data> + </datamodel> + <state id="s1"> + <onentry> + <assign location=""> + retract(father(bob, jim)). + assert(father(steve, jim)). + assert(father(bob, jack)). + </assign> + <log label="index" expr="listing." /> + <foreach array="father(bob, X)" + item="child" + index="index"> + <log label="index" expr="index(X)" /> + <log label="child" expr="child(X)" /> + </foreach> + </onentry> + <transition target="s2" + cond="mother(martha, X), father(bob, X)"/> + </state> + <state id="s2"> + <onentry> + <send type="basichttp" + targetexpr="ioprocessors(basichttp(location(X)))" + event="foo"> + <content> + <p>Snippet of XML</p> + </content> + </send> + </onentry> + <transition + target="end" + event="foo" + cond="member(element('p',_,_), X), event(data(X))" /> + </state> + <state id="end" final="true" /> </scxml> diff --git a/test/samples/uscxml/test-prolog2.scxml b/test/samples/uscxml/test-prolog2.scxml deleted file mode 100644 index 50dd1b3..0000000 --- a/test/samples/uscxml/test-prolog2.scxml +++ /dev/null @@ -1,40 +0,0 @@ -<scxml datamodel="prolog"> - <datamodel> - <data id="father/2"> - bob, jim. - bob, john. - </data> - <data> - mother(martha, jim). - mother(martha, john). - </data> - </datamodel> - <state id="s1"> - <onentry> - <foreach array="father(bob, X)" - item="child" - index="index"> - <log label="index" expr="index(X)" /> - <log label="child" expr="child(X)" /> - </foreach> - </onentry> - <transition target="s2" - cond="mother(martha, X), father(bob, X)"/> - </state> - <state id="s2"> - <onentry> - <send type="basichttp" - targetexpr="ioprocessors(basichttp(location(X)))" - event="foo"> - <content> - <p>Snippet of XML</p> - </content> - </send> - </onentry> - <transition - target="end" - event="foo" - cond="member(element('p',_,_), X), event(data(X))" /> - </state> - <state id="end" final="true" /> -</scxml> |