commit 92acd9e1c4cb5b1a7a3807c01284c8507bc7f9bd parent 4f25607ea77ca8eb8953b99705c85de97ad9d984 Author: Dan Callaghan <djc@djc.id.au> Date: Tue, 6 Oct 2009 20:15:36 +1000 allow for user-defined adapatations, caching of selector parsing results Diffstat:
11 files changed, 220 insertions(+), 74 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 @@ -5,22 +5,18 @@ package au.com.miskinhill.rdftemplate.selector; } @parser::members { - public static Selector<?> parse(String expression) { - CharStream stream = new ANTLRStringStream(expression); - SelectorLexer lexer = new SelectorLexer(stream); - CommonTokenStream tokens = new CommonTokenStream(lexer); - SelectorParser parser = new SelectorParser(tokens); - try { - return parser.unionSelector(); - } catch (RecognitionException e) { - throw new InvalidSelectorSyntaxException(e); - } - } @Override public void reportError(RecognitionException e) { throw new InvalidSelectorSyntaxException(e); } + + private AdaptationResolver adaptationResolver; + + public void setAdaptationResolver(AdaptationResolver adaptationResolver) { + this.adaptationResolver = adaptationResolver; + } + } @lexer::header { @@ -53,20 +49,35 @@ unionSelector returns [Selector<?> result] ; selector returns [Selector<?> result] +@init { + Class<? extends Adaptation<?>> adaptationClass; + Adaptation<?> adaptation = null; +} : ' '* ( ts=traversingSelector { result = ts; } | { result = new NoopSelector(); } ) ( '#' - ( URI_ADAPTATION { result = new SelectorWithAdaptation(result, new UriAdaptation()); } - | URI_SLICE_ADAPTATION - '(' - startIndex=INTEGER { result = new SelectorWithAdaptation(result, - new UriSliceAdaptation(Integer.parseInt($startIndex.text))); } + adaptationName=XMLTOKEN { adaptationClass = adaptationResolver.getByName($adaptationName.text); } + ( '(' + startIndex=INTEGER { + try { + adaptation = adaptationClass.getConstructor(Integer.class) + .newInstance(Integer.parseInt($startIndex.text)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } ')' - | COMPARABLE_LV_ADAPTATION { result = new SelectorWithAdaptation(result, new ComparableLiteralValueAdaptation()); } - | LV_ADAPTATION { result = new SelectorWithAdaptation(result, new LiteralValueAdaptation()); } + | { + try { + adaptation = adaptationClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } ) + { $result = new SelectorWithAdaptation(result, adaptation); } | ) ' '* @@ -139,10 +150,6 @@ predicate returns [Predicate result] URI_PREFIX_PREDICATE : 'uri-prefix' ; TYPE_PREDICATE : 'type' ; FIRST_PREDICATE : 'first' ; -LV_ADAPTATION : 'lv' ; -COMPARABLE_LV_ADAPTATION : 'comparable-lv' ; -URI_SLICE_ADAPTATION : 'uri-slice' ; -URI_ADAPTATION : 'uri' ; XMLTOKEN : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')* ; INTEGER : ('0'..'9')+ ; diff --git a/src/main/java/au/com/miskinhill/rdftemplate/TemplateInterpolator.java b/src/main/java/au/com/miskinhill/rdftemplate/TemplateInterpolator.java @@ -34,7 +34,7 @@ import com.hp.hpl.jena.rdf.model.RDFNode; import org.apache.commons.lang.StringUtils; import au.com.miskinhill.rdftemplate.selector.Selector; -import au.com.miskinhill.rdftemplate.selector.SelectorParser; +import au.com.miskinhill.rdftemplate.selector.SelectorFactory; public class TemplateInterpolator { @@ -55,17 +55,20 @@ public class TemplateInterpolator { inputFactory.setProperty("javax.xml.stream.isCoalescing", true); } - private TemplateInterpolator() { + private final SelectorFactory selectorFactory; + + public TemplateInterpolator(SelectorFactory selectorFactory) { + this.selectorFactory = selectorFactory; } @SuppressWarnings("unchecked") - public static String interpolate(Reader reader, RDFNode node) throws XMLStreamException { + public String interpolate(Reader reader, RDFNode node) throws XMLStreamException { StringWriter writer = new StringWriter(); interpolate(inputFactory.createXMLEventReader(reader), node, outputFactory.createXMLEventWriter(writer)); return writer.toString(); } - public static void interpolate(Iterator<XMLEvent> reader, RDFNode node, XMLEventWriter writer) + public void interpolate(Iterator<XMLEvent> reader, RDFNode node, XMLEventWriter writer) throws XMLStreamException { while (reader.hasNext()) { XMLEvent event = reader.next(); @@ -76,7 +79,7 @@ public class TemplateInterpolator { 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()); + Selector<?> selector = selectorFactory.get(testAttribute.getValue()); if (selector.result(node).isEmpty()) { consumeTree(start, reader); break; @@ -92,7 +95,7 @@ public class TemplateInterpolator { Attribute contentAttribute = start.getAttributeByName(CONTENT_ACTION_QNAME); Attribute forAttribute = start.getAttributeByName(FOR_ACTION_QNAME); if (ifAttribute != null) { - Selector<?> selector = SelectorParser.parse(ifAttribute.getValue()); + Selector<?> selector = selectorFactory.get(ifAttribute.getValue()); if (selector.result(node).isEmpty()) { consumeTree(start, reader); break; @@ -104,12 +107,12 @@ public class TemplateInterpolator { } else if (contentAttribute != null) { consumeTree(start, reader); start = interpolateAttributes(start, node); - Selector<?> selector = SelectorParser.parse(contentAttribute.getValue()); + Selector<?> selector = selectorFactory.get(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); + Selector<RDFNode> selector = selectorFactory.get(forAttribute.getValue()).withResultType(RDFNode.class); for (RDFNode subNode : selector.result(node)) { interpolate(tree.iterator(), subNode, writer); } @@ -136,7 +139,7 @@ public class TemplateInterpolator { } } - private static List<XMLEvent> consumeTree(StartElement start, Iterator<XMLEvent> reader) throws XMLStreamException { + private List<XMLEvent> consumeTree(StartElement start, Iterator<XMLEvent> reader) throws XMLStreamException { List<XMLEvent> events = new ArrayList<XMLEvent>(); events.add(start); Deque<QName> elementStack = new LinkedList<QName>(); @@ -162,7 +165,7 @@ public class TemplateInterpolator { } @SuppressWarnings("unchecked") - private static StartElement interpolateAttributes(StartElement start, RDFNode node) { + private StartElement interpolateAttributes(StartElement start, RDFNode node) { Set<Attribute> replacementAttributes = new LinkedHashSet<Attribute>(); for (Iterator<Attribute> it = start.getAttributes(); it.hasNext(); ) { Attribute attribute = it.next(); @@ -186,7 +189,7 @@ public class TemplateInterpolator { } private static final Pattern SUBSTITUTION_PATTERN = Pattern.compile("\\$\\{([^}]*)\\}"); - public static String interpolateString(String template, RDFNode node) { + public String interpolateString(String template, RDFNode node) { if (!SUBSTITUTION_PATTERN.matcher(template).find()) { return template; // fast path } @@ -194,7 +197,7 @@ public class TemplateInterpolator { Matcher matcher = SUBSTITUTION_PATTERN.matcher(template); while (matcher.find()) { String expression = matcher.group(1); - Object replacement = SelectorParser.parse(expression).singleResult(node); + Object replacement = selectorFactory.get(expression).singleResult(node); String replacementValue; if (replacement instanceof RDFNode) { @@ -217,7 +220,7 @@ public class TemplateInterpolator { return substituted.toString(); } - private static void writeTreeForContent(XMLEventWriter writer, StartElement start, Object replacement) + private void writeTreeForContent(XMLEventWriter writer, StartElement start, Object replacement) throws XMLStreamException { if (replacement instanceof RDFNode) { RDFNode replacementNode = (RDFNode) replacement; @@ -254,7 +257,7 @@ public class TemplateInterpolator { } @SuppressWarnings("unchecked") - private static Set<Attribute> cloneAttributesWithout(StartElement start, QName omit) { + private Set<Attribute> cloneAttributesWithout(StartElement start, QName omit) { // clone attributes, but without rdf:content Set<Attribute> attributes = new LinkedHashSet<Attribute>(); for (Iterator<Attribute> it = start.getAttributes(); it.hasNext(); ) { @@ -265,7 +268,7 @@ public class TemplateInterpolator { return attributes; } - private static void writeXMLLiteral(NamespaceContext nsContext, String literal, XMLEventWriter writer) + private void writeXMLLiteral(NamespaceContext nsContext, String literal, XMLEventWriter writer) throws XMLStreamException { XMLEventReader reader = inputFactory.createXMLEventReader(new StringReader(literal)); while (reader.hasNext()) { diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java @@ -0,0 +1,7 @@ +package au.com.miskinhill.rdftemplate.selector; + +public interface AdaptationResolver { + + <T> Class<? extends Adaptation<?>> getByName(String name); + +} diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/AntlrSelectorFactory.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/AntlrSelectorFactory.java @@ -0,0 +1,34 @@ +package au.com.miskinhill.rdftemplate.selector; + +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; + +public class AntlrSelectorFactory implements SelectorFactory { + + private final AdaptationResolver adaptationResolver; + + public AntlrSelectorFactory() { + this.adaptationResolver = new DefaultAdaptationResolver(); + } + + public AntlrSelectorFactory(AdaptationResolver adaptationResolver) { + this.adaptationResolver = adaptationResolver; + } + + @Override + public Selector<?> get(String expression) { + CharStream stream = new ANTLRStringStream(expression); + SelectorLexer lexer = new SelectorLexer(stream); + CommonTokenStream tokens = new CommonTokenStream(lexer); + SelectorParser parser = new SelectorParser(tokens); + parser.setAdaptationResolver(adaptationResolver); + try { + return parser.unionSelector(); + } catch (RecognitionException e) { + throw new InvalidSelectorSyntaxException(e); + } + } + +} diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java @@ -0,0 +1,21 @@ +package au.com.miskinhill.rdftemplate.selector; + +import java.util.HashMap; +import java.util.Map; + +public class DefaultAdaptationResolver implements AdaptationResolver { + + private static final Map<String, Class<? extends Adaptation<?>>> ADAPTATIONS = new HashMap<String, Class<? extends Adaptation<?>>>(); + static { + ADAPTATIONS.put("uri", UriAdaptation.class); + ADAPTATIONS.put("uri-slice", UriSliceAdaptation.class); + ADAPTATIONS.put("lv", LiteralValueAdaptation.class); + ADAPTATIONS.put("comparable-lv", ComparableLiteralValueAdaptation.class); + } + + @Override + public Class<? extends Adaptation<?>> getByName(String name) { + return ADAPTATIONS.get(name); + } + +} diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/EternallyCachingSelectorFactory.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/EternallyCachingSelectorFactory.java @@ -0,0 +1,35 @@ +package au.com.miskinhill.rdftemplate.selector; + +import java.util.HashMap; +import java.util.Map; + +/** + * {@link SelectorFactory} implementation which indirects to a real + * implementation and caches its return values eternally. Do not use in + * situations where the set of input expressions can be unbounded (e.g. + * user-provided) as this will lead to unbounded cache growth. + * <p> + * A better implementation would use a LRU cache or similar, but I cbf. + */ +public class EternallyCachingSelectorFactory implements SelectorFactory { + + private final SelectorFactory real; + private final Map<String, Selector<?>> cache = new HashMap<String, Selector<?>>(); + + public EternallyCachingSelectorFactory(SelectorFactory real) { + this.real = real; + } + + @Override + public Selector<?> get(String expression) { + Selector<?> cached = cache.get(expression); + if (cached == null) { + Selector<?> fresh = real.get(expression); + cache.put(expression, fresh); + return fresh; + } else { + return cached; + } + } + +} diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/SelectorFactory.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/SelectorFactory.java @@ -0,0 +1,7 @@ +package au.com.miskinhill.rdftemplate.selector; + +public interface SelectorFactory { + + Selector<?> get(String expression); + +} diff --git a/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/TemplateInterpolatorUnitTest.java @@ -22,6 +22,7 @@ import org.junit.BeforeClass; import org.junit.Test; import au.com.miskinhill.rdftemplate.datatype.DateDataType; +import au.com.miskinhill.rdftemplate.selector.AntlrSelectorFactory; public class TemplateInterpolatorUnitTest { @@ -31,6 +32,7 @@ public class TemplateInterpolatorUnitTest { } private Model model; + private TemplateInterpolator templateInterpolator; @Before public void setUp() { @@ -38,12 +40,13 @@ public class TemplateInterpolatorUnitTest { InputStream stream = this.getClass().getResourceAsStream( "/au/com/miskinhill/rdftemplate/test-data.xml"); model.read(stream, ""); + templateInterpolator = new TemplateInterpolator(new AntlrSelectorFactory()); } @Test public void shouldReplaceSubtreesWithContent() throws Exception { Resource journal = model.getResource("http://miskinhill.com.au/journals/test/"); - String result = TemplateInterpolator.interpolate( + String result = templateInterpolator.interpolate( new InputStreamReader(this.getClass().getResourceAsStream("replace-subtree.xml")), journal); assertThat(result, containsString("<div xml:lang=\"en\" lang=\"en\">Test Journal of Good Stuff</div>")); assertThat(result, not(containsString("<p>This should all go <em>away</em>!</p>"))); @@ -52,7 +55,7 @@ public class TemplateInterpolatorUnitTest { @Test public void shouldHandleXMLLiterals() throws Exception { Resource journal = model.getResource("http://miskinhill.com.au/journals/test/"); - String result = TemplateInterpolator.interpolate( + String result = templateInterpolator.interpolate( new InputStreamReader(this.getClass().getResourceAsStream("replace-xml.xml")), journal); assertThat(result, containsString( "<div xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\"><p><em>Test Journal</em> is a journal.</p></div>")); @@ -61,14 +64,14 @@ public class TemplateInterpolatorUnitTest { @Test public void shouldHandleIfs() throws Exception { Resource author = model.getResource("http://miskinhill.com.au/authors/test-author"); - String result = TemplateInterpolator.interpolate( + 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( + result = templateInterpolator.interpolate( new InputStreamReader(this.getClass().getResourceAsStream("conditional.xml")), authorWithoutNotes); assertThat(result, not(containsString("attribute test"))); assertThat(result, not(containsString("element test"))); @@ -77,7 +80,7 @@ public class TemplateInterpolatorUnitTest { @Test public void shouldWork() throws Exception { Resource journal = model.getResource("http://miskinhill.com.au/journals/test/"); - String result = TemplateInterpolator.interpolate( + String result = templateInterpolator.interpolate( new InputStreamReader(this.getClass().getResourceAsStream("test-template.xml")), journal); String expected = exhaust(this.getClass().getResource("test-template.out.xml").toURI()); assertEquals(expected.trim(), result.trim()); diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/EternallyCachingSelectorFactoryUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/EternallyCachingSelectorFactoryUnitTest.java @@ -0,0 +1,18 @@ +package au.com.miskinhill.rdftemplate.selector; + +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +public class EternallyCachingSelectorFactoryUnitTest { + + @Test + public void shouldCacheSelectors() { + EternallyCachingSelectorFactory factory = new EternallyCachingSelectorFactory(new AntlrSelectorFactory()); + Selector<?> first = factory.get("dc:creator/foaf:name"); + Selector<?> second = factory.get("dc:creator/foaf:name"); + assertThat((Selector) first, sameInstance((Selector) second)); + } + +} diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorEvaluationUnitTest.java @@ -22,6 +22,7 @@ public class SelectorEvaluationUnitTest { private Model m; private Resource journal, issue, article, citedArticle, author, anotherAuthor, book, review, anotherReview, obituary, en, ru; + private SelectorFactory selectorFactory; @BeforeClass public static void ensureDatatypesRegistered() { @@ -45,24 +46,25 @@ public class SelectorEvaluationUnitTest { obituary = m.createResource("http://miskinhill.com.au/journals/test/1:1/in-memoriam-john-doe"); en = m.createResource("http://www.lingvoj.org/lang/en"); ru = m.createResource("http://www.lingvoj.org/lang/ru"); + selectorFactory = new AntlrSelectorFactory(); } @Test public void shouldEvaluateTraversal() { - RDFNode result = SelectorParser.parse("dc:creator").withResultType(RDFNode.class).singleResult(article); + RDFNode result = selectorFactory.get("dc:creator").withResultType(RDFNode.class).singleResult(article); assertThat(result, equalTo((RDFNode) author)); } @Test public void shouldEvaluateMultipleTraversals() throws Exception { - RDFNode result = SelectorParser.parse("dc:creator/foaf:name") + RDFNode result = selectorFactory.get("dc:creator/foaf:name") .withResultType(RDFNode.class).singleResult(article); assertThat(((Literal) result).getString(), equalTo("Test Author")); } @Test public void shouldEvaluateInverseTraversal() throws Exception { - List<RDFNode> results = SelectorParser.parse("!mhs:isIssueOf/!dc:isPartOf") + List<RDFNode> results = selectorFactory.get("!mhs:isIssueOf/!dc:isPartOf") .withResultType(RDFNode.class).result(journal); assertThat(results.size(), equalTo(4)); assertThat(results, hasItems((RDFNode) article, (RDFNode) review, (RDFNode) anotherReview, (RDFNode) obituary)); @@ -70,7 +72,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateSortOrder() throws Exception { - List<RDFNode> results = SelectorParser.parse("dc:language(lingvoj:iso1#comparable-lv)") + List<RDFNode> results = selectorFactory.get("dc:language(lingvoj:iso1#comparable-lv)") .withResultType(RDFNode.class).result(journal); assertThat(results.size(), equalTo(2)); assertThat(results.get(0), equalTo((RDFNode) en)); @@ -79,7 +81,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateReverseSortOrder() throws Exception { - List<RDFNode> results = SelectorParser.parse("dc:language(~lingvoj:iso1#comparable-lv)") + List<RDFNode> results = selectorFactory.get("dc:language(~lingvoj:iso1#comparable-lv)") .withResultType(RDFNode.class).result(journal); assertThat(results.size(), equalTo(2)); assertThat(results.get(0), equalTo((RDFNode) ru)); @@ -88,7 +90,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateComplexSortOrder() throws Exception { - List<RDFNode> results = SelectorParser.parse("!mhs:reviews(dc:isPartOf/mhs:publicationDate#comparable-lv)") + List<RDFNode> results = selectorFactory.get("!mhs:reviews(dc:isPartOf/mhs:publicationDate#comparable-lv)") .withResultType(RDFNode.class).result(book); assertThat(results.size(), equalTo(2)); assertThat(results.get(0), equalTo((RDFNode) review)); @@ -97,31 +99,31 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateUriAdaptation() throws Exception { - String result = SelectorParser.parse("mhs:coverThumbnail#uri") + String result = selectorFactory.get("mhs:coverThumbnail#uri") .withResultType(String.class).singleResult(issue); assertThat(result, equalTo("http://miskinhill.com.au/journals/test/1:1/cover.thumb.jpg")); } @Test public void shouldEvaluateBareUriAdaptation() throws Exception { - String result = SelectorParser.parse("#uri").withResultType(String.class).singleResult(journal); + String result = selectorFactory.get("#uri").withResultType(String.class).singleResult(journal); assertThat(result, equalTo("http://miskinhill.com.au/journals/test/")); } @Test public void shouldEvaluateUriSliceAdaptation() throws Exception { - String result = SelectorParser.parse("dc:identifier[uri-prefix='urn:issn:']#uri-slice(9)") + String result = selectorFactory.get("dc:identifier[uri-prefix='urn:issn:']#uri-slice(9)") .withResultType(String.class).singleResult(journal); assertThat(result, equalTo("12345678")); } @Test public void shouldEvaluateSubscript() throws Exception { - String result = SelectorParser.parse( + String result = selectorFactory.get( "!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)[0]/mhs:coverThumbnail#uri") .withResultType(String.class).singleResult(journal); assertThat(result, equalTo("http://miskinhill.com.au/journals/test/2:1/cover.thumb.jpg")); - result = SelectorParser.parse( + result = selectorFactory.get( "!mhs:isIssueOf(mhs:publicationDate#comparable-lv)[0]/mhs:coverThumbnail#uri") .withResultType(String.class).singleResult(journal); assertThat(result, equalTo("http://miskinhill.com.au/journals/test/1:1/cover.thumb.jpg")); @@ -129,7 +131,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateLVAdaptation() throws Exception { - List<Object> results = SelectorParser.parse("dc:language/lingvoj:iso1#lv") + List<Object> results = selectorFactory.get("dc:language/lingvoj:iso1#lv") .withResultType(Object.class).result(journal); assertThat(results.size(), equalTo(2)); assertThat(results, hasItems((Object) "en", (Object) "ru")); @@ -137,7 +139,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateTypePredicate() throws Exception { - List<RDFNode> results = SelectorParser.parse("!dc:creator[type=mhs:Review]") + List<RDFNode> results = selectorFactory.get("!dc:creator[type=mhs:Review]") .withResultType(RDFNode.class).result(author); assertThat(results.size(), equalTo(1)); assertThat(results, hasItems((RDFNode) review)); @@ -145,7 +147,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateAndCombinationOfPredicates() throws Exception { - List<RDFNode> results = SelectorParser.parse("!dc:creator[type=mhs:Article and uri-prefix='http://miskinhill.com.au/journals/']") + 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)); @@ -153,7 +155,7 @@ public class SelectorEvaluationUnitTest { @Test public void shouldEvaluateUnion() throws Exception { - List<RDFNode> results = SelectorParser.parse("!dc:creator | !mhs:translator") + 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)); diff --git a/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorParserUnitTest.java b/src/test/java/au/com/miskinhill/rdftemplate/selector/SelectorParserUnitTest.java @@ -1,5 +1,7 @@ package au.com.miskinhill.rdftemplate.selector; +import org.junit.Before; + import static au.com.miskinhill.rdftemplate.selector.AdaptationMatcher.*; import static au.com.miskinhill.rdftemplate.selector.PredicateMatcher.*; import static au.com.miskinhill.rdftemplate.selector.SelectorMatcher.*; @@ -11,15 +13,22 @@ import org.junit.Test; public class SelectorParserUnitTest { + private SelectorFactory factory; + + @Before + public void setUp() { + factory = new AntlrSelectorFactory(); + } + @Test public void shouldRecogniseSingleTraversal() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("dc:creator").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("dc:creator").withResultType(RDFNode.class); assertThat(selector, selector(traversal("dc", "creator"))); } @Test public void shouldRecogniseMultipleTraversals() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("dc:creator/foaf:name").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("dc:creator/foaf:name").withResultType(RDFNode.class); assertThat(selector, selector( traversal("dc", "creator"), traversal("foaf", "name"))); @@ -27,7 +36,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseInverseTraversal() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!dc:isPartOf/!dc:isPartOf").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!dc:isPartOf/!dc:isPartOf").withResultType(RDFNode.class); assertThat(selector, selector( traversal("dc", "isPartOf").inverse(), traversal("dc", "isPartOf").inverse())); @@ -35,7 +44,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseSortOrder() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!mhs:isIssueOf(mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!mhs:isIssueOf(mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class); assertThat(selector, selector( traversal("mhs", "isIssueOf").inverse() .withSortOrder(selector(traversal("mhs", "publicationDate")) @@ -44,7 +53,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseReverseSortOrder() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class); assertThat(selector, selector( traversal("mhs", "isIssueOf").inverse() .withSortOrder(selector(traversal("mhs", "publicationDate")) @@ -54,7 +63,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseComplexSortOrder() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!mhs:reviews(dc:isPartOf/mhs:publicationDate#comparable-lv)").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!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")) @@ -63,7 +72,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseUriAdaptation() throws Exception { - Selector<?> selector = SelectorParser.parse("mhs:coverThumbnail#uri"); + Selector<?> selector = factory.get("mhs:coverThumbnail#uri"); assertThat(selector, selector( traversal("mhs", "coverThumbnail")) .withAdaptation(uriAdaptation())); @@ -71,13 +80,13 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseBareUriAdaptation() throws Exception { - Selector<?> selector = SelectorParser.parse("#uri"); + Selector<?> selector = factory.get("#uri"); assertThat(selector, selector().withAdaptation(uriAdaptation())); } @Test public void shouldRecogniseUriSliceAdaptation() throws Exception { - Selector<?> selector = SelectorParser.parse("dc:identifier[uri-prefix='urn:issn:']#uri-slice(9)"); + Selector<?> selector = factory.get("dc:identifier[uri-prefix='urn:issn:']#uri-slice(9)"); assertThat(selector, selector( traversal("dc", "identifier") .withPredicate(uriPrefixPredicate("urn:issn:"))) @@ -86,7 +95,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseUriPrefixPredicate() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse( + Selector<RDFNode> selector = factory.get( "!mhs:isIssueOf[uri-prefix='http://miskinhill.com.au/journals/'](~mhs:publicationDate#comparable-lv)") .withResultType(RDFNode.class); assertThat(selector, selector( @@ -100,7 +109,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseSubscript() throws Exception { - Selector<String> selector = SelectorParser.parse( + Selector<String> selector = factory.get( "!mhs:isIssueOf(~mhs:publicationDate#comparable-lv)[0]/mhs:coverThumbnail#uri") .withResultType(String.class); assertThat(selector, selector( @@ -116,7 +125,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseLVAdaptation() throws Exception { - Selector<Object> selector = SelectorParser.parse("dc:language/lingvoj:iso1#lv").withResultType(Object.class); + Selector<Object> selector = factory.get("dc:language/lingvoj:iso1#lv").withResultType(Object.class); assertThat(selector, selector( traversal("dc", "language"), traversal("lingvoj", "iso1")) @@ -125,14 +134,14 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseTypePredicate() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!dc:creator[type=mhs:Review]").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!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); + Selector<RDFNode> selector = factory.get("!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( @@ -142,7 +151,7 @@ public class SelectorParserUnitTest { @Test public void shouldRecogniseUnion() throws Exception { - Selector<RDFNode> selector = SelectorParser.parse("!dc:creator | !mhs:translator").withResultType(RDFNode.class); + Selector<RDFNode> selector = factory.get("!dc:creator | !mhs:translator").withResultType(RDFNode.class); assertThat((UnionSelector<RDFNode>) selector, unionSelector( selector(traversal("dc", "creator").inverse()), selector(traversal("mhs", "translator").inverse()))); @@ -150,12 +159,12 @@ public class SelectorParserUnitTest { @Test(expected = InvalidSelectorSyntaxException.class) public void shouldThrowForInvalidSyntax() throws Exception { - SelectorParser.parse("dc:creator]["); // this is a parser error + factory.get("dc:creator]["); // this is a parser error } @Test(expected = InvalidSelectorSyntaxException.class) public void shouldThrowForUnrecognisedCharacter() throws Exception { - SelectorParser.parse("dc:cre&ator"); // ... and this is a lexer error + factory.get("dc:cre&ator"); // ... and this is a lexer error } }