commit 4f25607ea77ca8eb8953b99705c85de97ad9d984
parent b68f599d66065f4a9997216495960fb69629b543
Author: Dan Callaghan <djc@djc.id.au>
Date: Sun, 4 Oct 2009 16:22:01 +1000
added support for: type predicate, boolean combination of predicates, unions
Diffstat:
12 files changed, 347 insertions(+), 43 deletions(-)
diff --git a/src/main/antlr3/au/com/miskinhill/rdftemplate/selector/Selector.g b/src/main/antlr3/au/com/miskinhill/rdftemplate/selector/Selector.g
@@ -11,7 +11,7 @@ package au.com.miskinhill.rdftemplate.selector;
CommonTokenStream tokens = new CommonTokenStream(lexer);
SelectorParser parser = new SelectorParser(tokens);
try {
- return parser.selector();
+ return parser.unionSelector();
} catch (RecognitionException e) {
throw new InvalidSelectorSyntaxException(e);
}
@@ -34,10 +34,27 @@ package au.com.miskinhill.rdftemplate.selector;
}
}
-start : selector ;
+start : unionSelector ;
+
+unionSelector returns [Selector<?> result]
+@init {
+ List<Selector<?>> selectors = new ArrayList<Selector<?>>();
+}
+ : s=selector { selectors.add(s); }
+ ( '|'
+ s=selector { selectors.add(s); }
+ )*
+ {
+ if (selectors.size() > 1)
+ result = new UnionSelector(selectors);
+ else
+ result = selectors.get(0);
+ }
+ ;
selector returns [Selector<?> result]
- : ( ts=traversingSelector { result = ts; }
+ : ' '*
+ ( ts=traversingSelector { result = ts; }
| { result = new NoopSelector(); }
)
( '#'
@@ -52,6 +69,7 @@ selector returns [Selector<?> result]
)
|
)
+ ' '*
;
traversingSelector returns [TraversingSelector result]
@@ -75,9 +93,7 @@ traversal returns [Traversal result]
':'
localname=XMLTOKEN { $result.setPropertyLocalName($localname.text); }
( '['
- URI_PREFIX_PREDICATE
- '='
- uriPrefix=SINGLE_QUOTED { $result.setPredicate(new UriPrefixPredicate($uriPrefix.text)); }
+ p=booleanPredicate { $result.setPredicate(p); }
']'
| // optional
)
@@ -96,7 +112,32 @@ traversal returns [Traversal result]
)
;
+booleanPredicate returns [Predicate result]
+ : ( p=predicate { result = p; }
+ | left=predicate
+ ' '+
+ 'and'
+ ' '+
+ right=booleanPredicate
+ { result = new BooleanAndPredicate(left, right); }
+ )
+ ;
+
+predicate returns [Predicate result]
+ : ( URI_PREFIX_PREDICATE
+ '='
+ uriPrefix=SINGLE_QUOTED { result = new UriPrefixPredicate($uriPrefix.text); }
+ | TYPE_PREDICATE
+ '='
+ nsprefix=XMLTOKEN
+ ':'
+ localname=XMLTOKEN
+ { result = new TypePredicate($nsprefix.text, $localname.text); }
+ )
+ ;
+
URI_PREFIX_PREDICATE : 'uri-prefix' ;
+TYPE_PREDICATE : 'type' ;
FIRST_PREDICATE : 'first' ;
LV_ADAPTATION : 'lv' ;
COMPARABLE_LV_ADAPTATION : 'comparable-lv' ;
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/TemplateInterpolator.java b/src/main/java/au/com/miskinhill/rdftemplate/TemplateInterpolator.java
@@ -43,6 +43,8 @@ public class TemplateInterpolator {
private static final QName CONTENT_ACTION_QNAME = new QName(NS, CONTENT_ACTION);
public static final String FOR_ACTION = "for";
private static final QName FOR_ACTION_QNAME = new QName(NS, FOR_ACTION);
+ public static final String IF_ACTION = "if";
+ private static final QName IF_ACTION_QNAME = new QName(NS, IF_ACTION);
private static final QName XML_LANG_QNAME = new QName(XMLConstants.XML_NS_URI, "lang", XMLConstants.XML_NS_PREFIX);
private static final String XHTML_NS_URI = "http://www.w3.org/1999/xhtml";
@@ -70,25 +72,51 @@ public class TemplateInterpolator {
switch (event.getEventType()) {
case XMLStreamConstants.START_ELEMENT: {
StartElement start = (StartElement) event;
- Attribute contentAttribute = start.getAttributeByName(CONTENT_ACTION_QNAME);
- Attribute forAttribute = start.getAttributeByName(FOR_ACTION_QNAME);
- if (contentAttribute != null && forAttribute != null) {
- throw new TemplateSyntaxException("rdf:for and rdf:content cannot both be present on an element");
- } else if (contentAttribute != null) {
- consumeTree(start, reader);
- start = interpolateAttributes(start, node);
- Selector<?> selector = SelectorParser.parse(contentAttribute.getValue());
- writeTreeForContent(writer, start, selector.singleResult(node));
- } else if (forAttribute != null) {
- start = cloneStartWithAttributes(start, cloneAttributesWithout(start, FOR_ACTION_QNAME));
- List<XMLEvent> tree = consumeTree(start, reader);
- Selector<RDFNode> selector = SelectorParser.parse(forAttribute.getValue()).withResultType(RDFNode.class);
- for (RDFNode subNode : selector.result(node)) {
- interpolate(tree.iterator(), subNode, writer);
+ if (start.getName().equals(IF_ACTION_QNAME)) {
+ Attribute testAttribute = start.getAttributeByName(new QName("test"));
+ if (testAttribute == null)
+ throw new TemplateSyntaxException("rdf:if must have a test attribute");
+ Selector<?> selector = SelectorParser.parse(testAttribute.getValue());
+ if (selector.result(node).isEmpty()) {
+ consumeTree(start, reader);
+ break;
+ } else {
+ List<XMLEvent> events = consumeTree(start, reader);
+ // discard the enclosing rdf:if element
+ events.remove(events.size() - 1);
+ events.remove(0);
+ interpolate(events.iterator(), node, writer);
}
} else {
- start = interpolateAttributes(start, node);
- writer.add(start);
+ Attribute ifAttribute = start.getAttributeByName(IF_ACTION_QNAME);
+ Attribute contentAttribute = start.getAttributeByName(CONTENT_ACTION_QNAME);
+ Attribute forAttribute = start.getAttributeByName(FOR_ACTION_QNAME);
+ if (ifAttribute != null) {
+ Selector<?> selector = SelectorParser.parse(ifAttribute.getValue());
+ if (selector.result(node).isEmpty()) {
+ consumeTree(start, reader);
+ break;
+ }
+ start = cloneStartWithAttributes(start, cloneAttributesWithout(start, IF_ACTION_QNAME));
+ }
+ if (contentAttribute != null && forAttribute != null) {
+ throw new TemplateSyntaxException("rdf:for and rdf:content cannot both be present on an element");
+ } else if (contentAttribute != null) {
+ consumeTree(start, reader);
+ start = interpolateAttributes(start, node);
+ Selector<?> selector = SelectorParser.parse(contentAttribute.getValue());
+ writeTreeForContent(writer, start, selector.singleResult(node));
+ } else if (forAttribute != null) {
+ start = cloneStartWithAttributes(start, cloneAttributesWithout(start, FOR_ACTION_QNAME));
+ List<XMLEvent> tree = consumeTree(start, reader);
+ Selector<RDFNode> selector = SelectorParser.parse(forAttribute.getValue()).withResultType(RDFNode.class);
+ for (RDFNode subNode : selector.result(node)) {
+ interpolate(tree.iterator(), subNode, writer);
+ }
+ } else {
+ start = interpolateAttributes(start, node);
+ writer.add(start);
+ }
}
break;
}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/BooleanAndPredicate.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/BooleanAndPredicate.java
@@ -0,0 +1,34 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+public class BooleanAndPredicate implements Predicate {
+
+ private final Predicate left;
+ private final Predicate right;
+
+ public BooleanAndPredicate(Predicate left, Predicate right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ public Predicate getLeft() {
+ return left;
+ }
+
+ public Predicate getRight() {
+ return right;
+ }
+
+ @Override
+ public boolean evaluate(RDFNode node) {
+ return left.evaluate(node) && right.evaluate(node);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append(left).append(right).toString();
+ }
+
+}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/TypePredicate.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/TypePredicate.java
@@ -0,0 +1,52 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+import java.util.Set;
+
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.vocabulary.RDF;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import au.com.miskinhill.rdftemplate.NamespacePrefixMapper;
+
+public class TypePredicate implements Predicate {
+
+ private final String namespacePrefix;
+ private final String localName;
+
+ public TypePredicate(String namespacePrefix, String localName) {
+ this.namespacePrefix = namespacePrefix;
+ this.localName = localName;
+ }
+
+ public String getNamespacePrefix() {
+ return namespacePrefix;
+ }
+
+ public String getLocalName() {
+ return localName;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean evaluate(RDFNode node) {
+ if (!node.isResource()) {
+ throw new SelectorEvaluationException("Attempted to apply [type] to non-resource node " + node);
+ }
+ Resource resource = (Resource) node;
+ Resource type = resource.getModel().createResource(
+ NamespacePrefixMapper.getInstance().get(namespacePrefix) + localName);
+ for (Statement statement: (Set<Statement>) resource.listProperties(RDF.type).toSet()) {
+ if (statement.getObject().equals(type))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append(namespacePrefix).append(localName).toString();
+ }
+
+}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/UnionSelector.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/UnionSelector.java
@@ -0,0 +1,45 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+public class UnionSelector<T> extends AbstractSelector<T> {
+
+ private final List<Selector<? extends T>> selectors;
+
+ public UnionSelector(List<Selector<? extends T>> selectors) {
+ super(null);
+ this.selectors = selectors;
+ }
+
+ @Override
+ public List<T> result(RDFNode node) {
+ LinkedHashSet<T> results = new LinkedHashSet<T>();
+ for (Selector<? extends T> selector: selectors) {
+ results.addAll(selector.result(node));
+ }
+ return new ArrayList<T>(results);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append(selectors).toString();
+ }
+
+ public List<Selector<? extends T>> getSelectors() {
+ return selectors;
+ }
+
+ @Override
+ public <Other> Selector<Other> withResultType(Class<Other> otherType) {
+ for (Selector<? extends T> selector: selectors) {
+ selector.withResultType(otherType); // class cast exception?
+ }
+ return (Selector<Other>) this;
+ }
+
+}
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java
@@ -59,6 +59,22 @@ public class TemplateInterpolatorUnitTest {
}
@Test
+ public void shouldHandleIfs() throws Exception {
+ Resource author = model.getResource("http://miskinhill.com.au/authors/test-author");
+ String result = TemplateInterpolator.interpolate(
+ new InputStreamReader(this.getClass().getResourceAsStream("conditional.xml")), author);
+ assertThat(result, containsString("attribute test"));
+ assertThat(result, containsString("element test"));
+ assertThat(result, not(containsString("rdf:if")));
+
+ Resource authorWithoutNotes = model.getResource("http://miskinhill.com.au/authors/another-author");
+ result = TemplateInterpolator.interpolate(
+ new InputStreamReader(this.getClass().getResourceAsStream("conditional.xml")), authorWithoutNotes);
+ assertThat(result, not(containsString("attribute test")));
+ assertThat(result, not(containsString("element test")));
+ }
+
+ @Test
public void shouldWork() throws Exception {
Resource journal = model.getResource("http://miskinhill.com.au/journals/test/");
String result = TemplateInterpolator.interpolate(
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/PredicateMatcher.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/PredicateMatcher.java
@@ -2,6 +2,8 @@ package au.com.miskinhill.rdftemplate.selector;
import static org.hamcrest.CoreMatchers.equalTo;
+import org.hamcrest.Matcher;
+
public class PredicateMatcher<T extends Predicate> extends BeanPropertyMatcher<T> {
private PredicateMatcher(Class<T> type) {
@@ -13,5 +15,20 @@ public class PredicateMatcher<T extends Predicate> extends BeanPropertyMatcher<T
m.addRequiredProperty("prefix", equalTo(prefix));
return m;
}
+
+ public static PredicateMatcher<TypePredicate> typePredicate(String namespacePrefix, String localName) {
+ PredicateMatcher<TypePredicate> m = new PredicateMatcher<TypePredicate>(TypePredicate.class);
+ m.addRequiredProperty("namespacePrefix", equalTo(namespacePrefix));
+ m.addRequiredProperty("localName", equalTo(localName));
+ return m;
+ }
+
+ public static PredicateMatcher<BooleanAndPredicate> booleanAndPredicate(
+ Matcher<? extends Predicate> left, Matcher<? extends Predicate> right) {
+ PredicateMatcher<BooleanAndPredicate> m = new PredicateMatcher<BooleanAndPredicate>(BooleanAndPredicate.class);
+ m.addRequiredProperty("left", left);
+ m.addRequiredProperty("right", right);
+ return m;
+ }
}
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java
@@ -1,9 +1,8 @@
package au.com.miskinhill.rdftemplate.selector;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
import java.io.InputStream;
import java.util.List;
@@ -22,7 +21,7 @@ import au.com.miskinhill.rdftemplate.datatype.DateDataType;
public class SelectorEvaluationUnitTest {
private Model m;
- private Resource journal, issue, article, author, book, review, anotherReview, obituary, en, ru;
+ private Resource journal, issue, article, citedArticle, author, anotherAuthor, book, review, anotherReview, obituary, en, ru;
@BeforeClass
public static void ensureDatatypesRegistered() {
@@ -37,7 +36,9 @@ 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");
+ 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");
book = m.createResource("http://miskinhill.com.au/cited/books/test");
review = m.createResource("http://miskinhill.com.au/journals/test/1:1/reviews/review");
anotherReview = m.createResource("http://miskinhill.com.au/journals/test/2:1/reviews/another-review");
@@ -134,4 +135,28 @@ public class SelectorEvaluationUnitTest {
assertThat(results, hasItems((Object) "en", (Object) "ru"));
}
+ @Test
+ public void shouldEvaluateTypePredicate() throws Exception {
+ List<RDFNode> results = SelectorParser.parse("!dc:creator[type=mhs:Review]")
+ .withResultType(RDFNode.class).result(author);
+ assertThat(results.size(), equalTo(1));
+ assertThat(results, hasItems((RDFNode) review));
+ }
+
+ @Test
+ public void shouldEvaluateAndCombinationOfPredicates() throws Exception {
+ List<RDFNode> results = SelectorParser.parse("!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));
+ }
+
+ @Test
+ public void shouldEvaluateUnion() throws Exception {
+ List<RDFNode> results = SelectorParser.parse("!dc:creator | !mhs:translator")
+ .withResultType(RDFNode.class).result(anotherAuthor);
+ assertThat(results.size(), equalTo(3));
+ assertThat(results, hasItems((RDFNode) article, (RDFNode) citedArticle, (RDFNode) anotherReview));
+ }
+
}
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorMatcher.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorMatcher.java
@@ -1,8 +1,8 @@
package au.com.miskinhill.rdftemplate.selector;
-
import static org.junit.matchers.JUnitMatchers.hasItems;
+import com.hp.hpl.jena.rdf.model.RDFNode;
import org.hamcrest.Matcher;
public class SelectorMatcher<T extends Selector<?>> extends BeanPropertyMatcher<T> {
@@ -11,15 +11,21 @@ public class SelectorMatcher<T extends Selector<?>> extends BeanPropertyMatcher<
super(type);
}
- public static SelectorMatcher<Selector<?>> selector(Matcher<Traversal>... traversals) {
+ public static SelectorMatcher<Selector<RDFNode>> selector(Matcher<Traversal>... traversals) {
if (traversals.length == 0) {
- return new SelectorMatcher<Selector<?>>(NoopSelector.class);
+ return new SelectorMatcher<Selector<RDFNode>>(NoopSelector.class);
}
- SelectorMatcher<Selector<?>> m = new SelectorMatcher<Selector<?>>(TraversingSelector.class);
+ SelectorMatcher<Selector<RDFNode>> m = new SelectorMatcher<Selector<RDFNode>>(TraversingSelector.class);
m.addRequiredProperty("traversals", hasItems(traversals));
return m;
}
+ public static <R> SelectorMatcher<UnionSelector<R>> unionSelector(Matcher<Selector<R>>... selectors) {
+ SelectorMatcher<UnionSelector<R>> m = new SelectorMatcher(UnionSelector.class);
+ m.addRequiredProperty("selectors", hasItems(selectors));
+ return m;
+ }
+
public <A> SelectorMatcher<Selector<?>> withAdaptation(Matcher<? extends Adaptation<A>> adaptation) {
SelectorMatcher<Selector<?>> m = new SelectorMatcher(SelectorWithAdaptation.class);
m.addRequiredProperty("baseSelector", this);
diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorParserUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorParserUnitTest.java
@@ -2,24 +2,24 @@ package au.com.miskinhill.rdftemplate.selector;
import static au.com.miskinhill.rdftemplate.selector.AdaptationMatcher.*;
import static au.com.miskinhill.rdftemplate.selector.PredicateMatcher.*;
-import static au.com.miskinhill.rdftemplate.selector.SelectorMatcher.selector;
+import static au.com.miskinhill.rdftemplate.selector.SelectorMatcher.*;
import static au.com.miskinhill.rdftemplate.selector.TraversalMatcher.traversal;
-
import static org.junit.Assert.assertThat;
+import com.hp.hpl.jena.rdf.model.RDFNode;
import org.junit.Test;
public class SelectorParserUnitTest {
@Test
public void shouldRecogniseSingleTraversal() throws Exception {
- Selector<?> selector = SelectorParser.parse("dc:creator");
+ Selector<RDFNode> selector = SelectorParser.parse("dc:creator").withResultType(RDFNode.class);
assertThat(selector, selector(traversal("dc", "creator")));
}
@Test
public void shouldRecogniseMultipleTraversals() throws Exception {
- Selector<?> selector = SelectorParser.parse("dc:creator/foaf:name");
+ Selector<RDFNode> selector = SelectorParser.parse("dc:creator/foaf:name").withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("dc", "creator"),
traversal("foaf", "name")));
@@ -27,7 +27,7 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseInverseTraversal() throws Exception {
- Selector<?> selector = SelectorParser.parse("!dc:isPartOf/!dc:isPartOf");
+ Selector<RDFNode> selector = SelectorParser.parse("!dc:isPartOf/!dc:isPartOf").withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("dc", "isPartOf").inverse(),
traversal("dc", "isPartOf").inverse()));
@@ -35,7 +35,7 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseSortOrder() throws Exception {
- Selector<?> selector = SelectorParser.parse("!mhs:isIssueOf(mhs:publicationDate#comparable-lv)");
+ Selector<RDFNode> selector = SelectorParser.parse("!mhs:isIssueOf(mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("mhs", "isIssueOf").inverse()
.withSortOrder(selector(traversal("mhs", "publicationDate"))
@@ -44,7 +44,7 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseReverseSortOrder() throws Exception {
- Selector<?> selector = SelectorParser.parse("!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)");
+ Selector<RDFNode> selector = SelectorParser.parse("!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("mhs", "isIssueOf").inverse()
.withSortOrder(selector(traversal("mhs", "publicationDate"))
@@ -54,7 +54,7 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseComplexSortOrder() throws Exception {
- Selector<?> selector = SelectorParser.parse("!mhs:reviews(dc:isPartOf/mhs:publicationDate#comparable-lv)");
+ Selector<RDFNode> selector = SelectorParser.parse("!mhs:reviews(dc:isPartOf/mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("mhs", "reviews")
.withSortOrder(selector(traversal("dc", "isPartOf"), traversal("mhs", "publicationDate"))
@@ -86,8 +86,9 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseUriPrefixPredicate() throws Exception {
- Selector<?> selector = SelectorParser.parse(
- "!mhs:isIssueOf[uri-prefix='http://miskinhill.com.au/journals/'](~mhs:publicationDate#comparable-lv)");
+ Selector<RDFNode> selector = SelectorParser.parse(
+ "!mhs:isIssueOf[uri-prefix='http://miskinhill.com.au/journals/'](~mhs:publicationDate#comparable-lv)")
+ .withResultType(RDFNode.class);
assertThat(selector, selector(
traversal("mhs", "isIssueOf")
.inverse()
@@ -99,8 +100,9 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseSubscript() throws Exception {
- Selector<?> selector = SelectorParser.parse(
- "!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)[0]/mhs:coverThumbnail#uri");
+ Selector<String> selector = SelectorParser.parse(
+ "!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)[0]/mhs:coverThumbnail#uri")
+ .withResultType(String.class);
assertThat(selector, selector(
traversal("mhs", "isIssueOf")
.inverse()
@@ -114,13 +116,38 @@ public class SelectorParserUnitTest {
@Test
public void shouldRecogniseLVAdaptation() throws Exception {
- Selector<?> selector = SelectorParser.parse("dc:language/lingvoj:iso1#lv");
+ Selector<Object> selector = SelectorParser.parse("dc:language/lingvoj:iso1#lv").withResultType(Object.class);
assertThat(selector, selector(
traversal("dc", "language"),
traversal("lingvoj", "iso1"))
.withAdaptation(lvAdaptation()));
}
+ @Test
+ public void shouldRecogniseTypePredicate() throws Exception {
+ Selector<RDFNode> selector = SelectorParser.parse("!dc:creator[type=mhs:Review]").withResultType(RDFNode.class);
+ assertThat(selector, selector(
+ traversal("dc", "creator").inverse().withPredicate(typePredicate("mhs", "Review"))));
+ }
+
+ @Test
+ public void shouldRecogniseAndCombinationOfPredicates() throws Exception {
+ Selector<RDFNode> selector = SelectorParser.parse("!dc:creator[type=mhs:Review and uri-prefix='http://miskinhill.com.au/journals/']").withResultType(RDFNode.class);
+ assertThat(selector, selector(
+ traversal("dc", "creator").inverse()
+ .withPredicate(booleanAndPredicate(
+ typePredicate("mhs", "Review"),
+ uriPrefixPredicate("http://miskinhill.com.au/journals/")))));
+ }
+
+ @Test
+ public void shouldRecogniseUnion() throws Exception {
+ Selector<RDFNode> selector = SelectorParser.parse("!dc:creator | !mhs:translator").withResultType(RDFNode.class);
+ assertThat((UnionSelector<RDFNode>) selector, unionSelector(
+ selector(traversal("dc", "creator").inverse()),
+ selector(traversal("mhs", "translator").inverse())));
+ }
+
@Test(expected = InvalidSelectorSyntaxException.class)
public void shouldThrowForInvalidSyntax() throws Exception {
SelectorParser.parse("dc:creator]["); // this is a parser error
diff --git a/src/test/resources/au/com/miskinhill/rdftemplate/conditional.xml b/src/test/resources/au/com/miskinhill/rdftemplate/conditional.xml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
+<body>
+
+<span rdf:if="mhs:biographicalNotes">attribute test</span>
+
+<rdf:if test="mhs:biographicalNotes">element test</rdf:if>
+
+</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
@@ -52,6 +52,7 @@
<mhs:Article rdf:about="http://miskinhill.com.au/journals/test/1:1/article">
<dc:isPartOf rdf:resource="http://miskinhill.com.au/journals/test/1:1/"/>
<dc:creator rdf:resource="http://miskinhill.com.au/authors/test-author"/>
+ <mhs:translator rdf:resource="http://miskinhill.com.au/authors/another-author"/>
<dc:title rdf:parseType="Literal"><span xmlns="http://www.w3.org/1999/xhtml" lang="en"><em>Moscow 1937</em>: the interpreter’s story</span></dc:title>
<mhs:startPage rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">5</mhs:startPage>
<mhs:endPage rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">35</mhs:endPage>
@@ -60,6 +61,7 @@
<foaf:name>Test Author</foaf:name>
<foaf:surname>Author</foaf:surname>
<foaf:givenNames>Test</foaf:givenNames>
+ <mhs:biographicalNotes>This person does stuff.</mhs:biographicalNotes>
</mhs:Author>
<mhs:Journal rdf:about="http://miskinhill.com.au/cited/journals/asdf/">
<dc:title xml:lang="en">A Cited Journal</dc:title>