summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-05-01 23:25:28 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-05-01 23:25:28 (GMT)
commit0202a8780179c710b2596e25567d4cf480dca277 (patch)
tree4c33ead20947aad00bda5055648248e84842a4e7
parent1dc899c70362de2eed1f6dc074dc5238df0c7f3c (diff)
downloaduscxml-0202a8780179c710b2596e25567d4cf480dca277.zip
uscxml-0202a8780179c710b2596e25567d4cf480dca277.tar.gz
uscxml-0202a8780179c710b2596e25567d4cf480dca277.tar.bz2
More work on Prolog datamodel
-rw-r--r--README.md8
-rw-r--r--src/uscxml/Message.cpp12
-rw-r--r--src/uscxml/Message.h3
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp71
-rw-r--r--test/samples/uscxml/test-prolog.scxml185
-rw-r--r--test/samples/uscxml/test-prolog2.scxml40
6 files changed, 126 insertions, 193 deletions
diff --git a/README.md b/README.md
index fee588b..34683f8 100644
--- a/README.md
+++ b/README.md
@@ -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>