rdftemplate

Library for generating XML documents from RDF data using templates
git clone https://code.djc.id.au/git/rdftemplate/
commit 15f4ff3c9d77f061c86a4f60bd29d85bbc0fce3e
parent 29902dea0fa92d278277ad18ce69e906ab08d59d
Author: Dan Callaghan <djc@djc.id.au>
Date:   Sun, 29 Nov 2009 19:07:13 +1000

special case for iterating across rdf:Seqs

Diffstat:
Msrc/main/java/au/com/miskinhill/rdftemplate/ForAction.java | 16+++++++++++++++-
Msrc/main/java/au/com/miskinhill/rdftemplate/JoinAction.java | 18++++++++++++++++--
Msrc/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java | 34++++++++++++++++++++++++++++++++++
Msrc/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java | 20+++++++++++---------
Asrc/test/resources/au/com/miskinhill/rdftemplate/for-seq.xml | 11+++++++++++
Asrc/test/resources/au/com/miskinhill/rdftemplate/join-seq.xml | 9+++++++++
Msrc/test/resources/au/com/miskinhill/rdftemplate/test-data.xml | 15+++++++++++++++
7 files changed, 111 insertions(+), 12 deletions(-)
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/ForAction.java b/src/main/java/au/com/miskinhill/rdftemplate/ForAction.java
@@ -1,12 +1,17 @@
 package au.com.miskinhill.rdftemplate;
 
 import java.util.List;
+import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.XMLEvent;
 
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.vocabulary.RDF;
+
 import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.rdf.model.Seq;
 import org.apache.commons.lang.builder.ToStringBuilder;
 
 import au.com.miskinhill.rdftemplate.selector.Selector;
@@ -15,6 +20,7 @@ public class ForAction extends TemplateAction {
     
     public static final String ACTION_NAME = "for";
     public static final QName ACTION_QNAME = new QName(TemplateInterpolator.NS, ACTION_NAME);
+    private static final Logger LOG = Logger.getLogger(ForAction.class.getName());
     
     private final List<XMLEvent> tree;
     private final Selector<RDFNode> selector;
@@ -26,7 +32,15 @@ public class ForAction extends TemplateAction {
     
     public void evaluate(TemplateInterpolator interpolator, RDFNode node, XMLEventDestination writer)
             throws XMLStreamException {
-        for (RDFNode eachNode: selector.result(node)) {
+        List<RDFNode> result = selector.result(node);
+        if (result.size() == 1 && result.get(0).canAs(Resource.class)) {
+            if (result.get(0).as(Resource.class).hasProperty(RDF.type, RDF.Seq)) {
+                LOG.fine("Apply rdf:Seq special case for " + result.get(0));
+                result = result.get(0).as(Seq.class).iterator().toList();
+                LOG.fine("Resulting sequence is " + result);
+            }
+        }
+        for (RDFNode eachNode: result) {
             interpolator.interpolate(tree.iterator(), eachNode, writer);
         }
     }
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/JoinAction.java b/src/main/java/au/com/miskinhill/rdftemplate/JoinAction.java
@@ -1,15 +1,20 @@
 package au.com.miskinhill.rdftemplate;
 
 import java.util.List;
+import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLEventFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.XMLEvent;
 
-import org.apache.commons.lang.builder.ToStringBuilder;
+import com.hp.hpl.jena.vocabulary.RDF;
+
+import com.hp.hpl.jena.rdf.model.Resource;
 
 import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.rdf.model.Seq;
+import org.apache.commons.lang.builder.ToStringBuilder;
 
 import au.com.miskinhill.rdftemplate.selector.Selector;
 
@@ -17,6 +22,7 @@ public class JoinAction extends TemplateAction {
     
     public static final String ACTION_NAME = "join";
     public static final QName ACTION_QNAME = new QName(TemplateInterpolator.NS, ACTION_NAME);
+    private static final Logger LOG = Logger.getLogger(JoinAction.class.getName());
     
     private final List<XMLEvent> tree;
     private final Selector<RDFNode> selector;
@@ -30,8 +36,16 @@ public class JoinAction extends TemplateAction {
     
     public void evaluate(TemplateInterpolator interpolator, RDFNode node, XMLEventDestination writer, XMLEventFactory eventFactory)
             throws XMLStreamException {
+        List<RDFNode> result = selector.result(node);
+        if (result.size() == 1 && result.get(0).canAs(Resource.class)) {
+            if (result.get(0).as(Resource.class).hasProperty(RDF.type, RDF.Seq)) {
+                LOG.fine("Apply rdf:Seq special case for " + result.get(0));
+                result = result.get(0).as(Seq.class).iterator().toList();
+                LOG.fine("Resulting sequence is " + result);
+            }
+        }
         boolean first = true;
-        for (RDFNode eachNode: selector.result(node)) {
+        for (RDFNode eachNode: result) {
             if (!first) {
                 writer.add(eventFactory.createCharacters(separator));
             }
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java
@@ -103,4 +103,38 @@ public class TemplateInterpolatorUnitTest {
         assertThat(result, not(containsString("rdf:")));
     }
     
+    @Test
+    public void forShouldIterateRdfSeqsInOrder() throws Exception {
+        Resource article = model.getResource("http://miskinhill.com.au/journals/test/1:1/multi-author-article");
+        String result = templateInterpolator.interpolate(
+                new InputStreamReader(this.getClass().getResourceAsStream("for-seq.xml")), article);
+        assertThat(result, containsString("Another Author\n\nTest Author"));
+    }
+    
+    @Test
+    public void joinShouldIterateRdfSeqsInOrder() throws Exception {
+        Resource article = model.getResource("http://miskinhill.com.au/journals/test/1:1/multi-author-article");
+        String result = templateInterpolator.interpolate(
+                new InputStreamReader(this.getClass().getResourceAsStream("join-seq.xml")), article);
+        assertThat(result, containsString("<p><a href=\"http://miskinhill.com.au/authors/another-author\">Another Author</a>, " +
+        		"<a href=\"http://miskinhill.com.au/authors/test-author\">Test Author</a></p>"));
+    }
+    
+    @Test
+    public void forShouldWorkForSingleResult() throws Exception {
+        Resource journal = model.getResource("http://miskinhill.com.au/cited/journals/asdf/");
+        String result = templateInterpolator.interpolate(
+                new InputStreamReader(this.getClass().getResourceAsStream("for.xml")), journal);
+        assertThat(result, containsString("<span>http://miskinhill.com.au/cited/journals/asdf/1:1/</span>"));
+        assertThat(result, containsString("<p>http://miskinhill.com.au/cited/journals/asdf/1:1/</p>"));
+    }
+    
+    @Test
+    public void joinShouldWorkForSingleResult() throws Exception {
+        Resource review = model.getResource("http://miskinhill.com.au/journals/test/1:1/reviews/review");
+        String result = templateInterpolator.interpolate(
+                new InputStreamReader(this.getClass().getResourceAsStream("join.xml")), review);
+        assertThat(result, containsString("<p><a href=\"http://miskinhill.com.au/authors/test-author\">Test Author</a></p>"));
+    }
+    
 }
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java
@@ -23,7 +23,7 @@ import au.com.miskinhill.rdftemplate.datatype.DateTimeDataType;
 public class SelectorEvaluationUnitTest {
     
     private Model m;
-    private Resource journal, issue, article, citedArticle, author, anotherAuthor, book, review, anotherReview, obituary, en, ru, forum;
+    private Resource journal, issue, article, multiAuthorArticle, citedArticle, author, anotherAuthor, book, review, anotherReview, obituary, en, ru, forum;
     private AntlrSelectorFactory selectorFactory;
     
     @BeforeClass
@@ -40,6 +40,7 @@ public class SelectorEvaluationUnitTest {
         journal = m.createResource("http://miskinhill.com.au/journals/test/");
         issue = m.createResource("http://miskinhill.com.au/journals/test/1:1/");
         article = m.createResource("http://miskinhill.com.au/journals/test/1:1/article");
+        multiAuthorArticle = m.createResource("http://miskinhill.com.au/journals/test/1:1/multi-author-article");
         citedArticle = m.createResource("http://miskinhill.com.au/cited/journals/asdf/1:1/article");
         author = m.createResource("http://miskinhill.com.au/authors/test-author");
         anotherAuthor = m.createResource("http://miskinhill.com.au/authors/another-author");
@@ -71,8 +72,8 @@ public class SelectorEvaluationUnitTest {
     public void shouldEvaluateInverseTraversal() throws Exception {
         List<RDFNode> results = selectorFactory.get("!dc:isPartOf")
                 .withResultType(RDFNode.class).result(issue);
-        assertThat(results.size(), equalTo(3));
-        assertThat(results, hasItems((RDFNode) article, (RDFNode) review, (RDFNode) obituary));
+        assertThat(results.size(), equalTo(4));
+        assertThat(results, hasItems((RDFNode) article, (RDFNode) multiAuthorArticle, (RDFNode) review, (RDFNode) obituary));
     }
     
     @Test
@@ -161,16 +162,16 @@ public class SelectorEvaluationUnitTest {
     public void shouldEvaluateAndCombinationOfPredicates() throws Exception {
         List<RDFNode> results = selectorFactory.get("!dc:creator[type=mhs:Article and uri-prefix='http://miskinhill.com.au/journals/']")
                 .withResultType(RDFNode.class).result(author);
-        assertThat(results.size(), equalTo(1));
-        assertThat(results, hasItems((RDFNode) article));
+        assertThat(results.size(), equalTo(2));
+        assertThat(results, hasItems((RDFNode) article, (RDFNode) multiAuthorArticle));
     }
     
     @Test
     public void shouldEvaluateUnion() throws Exception {
         List<RDFNode> results = selectorFactory.get("!dc:creator | !mhs:translator")
                 .withResultType(RDFNode.class).result(anotherAuthor);
-        assertThat(results.size(), equalTo(3));
-        assertThat(results, hasItems((RDFNode) article, (RDFNode) citedArticle, (RDFNode) anotherReview));
+        assertThat(results.size(), equalTo(4));
+        assertThat(results, hasItems((RDFNode) article, (RDFNode) multiAuthorArticle, (RDFNode) citedArticle, (RDFNode) anotherReview));
     }
     
     @Test
@@ -178,10 +179,11 @@ public class SelectorEvaluationUnitTest {
         List<RDFNode> results = selectorFactory.get("!dc:creator[uri-prefix='http://miskinhill.com.au/journals/']" +
         		"(~dc:isPartOf/mhs:publicationDate#comparable-lv,mhs:startPage#comparable-lv)")
                 .withResultType(RDFNode.class).result(author);
-        assertThat(results.size(), equalTo(3));
+        assertThat(results.size(), equalTo(4));
         assertThat(results.get(0), equalTo((RDFNode) obituary));
         assertThat(results.get(1), equalTo((RDFNode) article));
-        assertThat(results.get(2), equalTo((RDFNode) review));
+        assertThat(results.get(2), equalTo((RDFNode) multiAuthorArticle));
+        assertThat(results.get(3), equalTo((RDFNode) review));
     }
     
     @Test
diff --git a/src/test/resources/au/com/miskinhill/rdftemplate/for-seq.xml b/src/test/resources/au/com/miskinhill/rdftemplate/for-seq.xml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
+<body>
+
+<rdf:for each="mhs:authorOrder">
+${foaf:name}
+</rdf:for>
+
+</body>
+</html>
+\ No newline at end of file
diff --git a/src/test/resources/au/com/miskinhill/rdftemplate/join-seq.xml b/src/test/resources/au/com/miskinhill/rdftemplate/join-seq.xml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
+<body>
+
+<p><rdf:join each="mhs:authorOrder" separator=", "><a href="${#uri}" rdf:content="foaf:name" /></rdf:join></p>
+
+</body>
+</html>
+\ No newline at end of file
diff --git a/src/test/resources/au/com/miskinhill/rdftemplate/test-data.xml b/src/test/resources/au/com/miskinhill/rdftemplate/test-data.xml
@@ -97,6 +97,21 @@
     <foaf:givenNames>Test</foaf:givenNames>
     <mhs:biographicalNotes>This person does stuff.</mhs:biographicalNotes>
   </mhs:Author>
+  <mhs:Article rdf:about="http://miskinhill.com.au/journals/test/1:1/multi-author-article">
+    <dc:isPartOf rdf:resource="http://miskinhill.com.au/journals/test/1:1/"/>
+    <dc:creator rdf:resource="http://miskinhill.com.au/authors/test-author"/>
+    <dc:creator rdf:resource="http://miskinhill.com.au/authors/another-author"/>
+    <dc:title>Multi-author article</dc:title>
+    <mhs:startPage rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">36</mhs:startPage>
+    <mhs:endPage rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">75</mhs:endPage>
+    <mhs:authorOrder>
+      <rdf:Description>
+        <rdf:_1 rdf:resource="http://miskinhill.com.au/authors/another-author"/>
+        <rdf:_2 rdf:resource="http://miskinhill.com.au/authors/test-author"/>
+        <rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"/>
+      </rdf:Description>
+    </mhs:authorOrder>
+  </mhs:Article>
   <mhs:Journal rdf:about="http://miskinhill.com.au/cited/journals/asdf/">
     <dc:title xml:lang="en">A Cited Journal</dc:title>
     <dc:identifier rdf:resource="urn:issn:87654321"/>