commit b92ca8a1aec86a440acc1f46c2d8e5c7517e083f
parent 4e6988d678b18170a3300b968eb271333abf03a5
Author: Dan Callaghan <djc@djc.id.au>
Date: Sun, 4 Apr 2010 12:25:38 +1000
move instantiation of Adaptations from the parser into the AdaptationFactory, to allow for Spring prototype beans
--HG--
rename : src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java => src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationFactory.java
rename : src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java => src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationFactory.java
Diffstat:
15 files changed, 162 insertions(+), 147 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
@@ -12,12 +12,12 @@ import java.util.Map;
throw new InvalidSelectorSyntaxException(e);
}
- private AdaptationResolver adaptationResolver;
+ private AdaptationFactory adaptationFactory;
private PredicateResolver predicateResolver;
private Map<String, String> namespacePrefixMap;
- public void setAdaptationResolver(AdaptationResolver adaptationResolver) {
- this.adaptationResolver = adaptationResolver;
+ public void setAdaptationFactory(AdaptationFactory adaptationFactory) {
+ this.adaptationFactory = adaptationFactory;
}
public void setPredicateResolver(PredicateResolver predicateResolver) {
@@ -71,7 +71,6 @@ unionSelector returns [Selector<?> result]
selector returns [Selector<?> result]
@init {
- Class<? extends Adaptation<?>> adaptationClass;
Adaptation<?> adaptation = null;
}
: ( ts=traversingSelector { result = ts; }
@@ -80,36 +79,18 @@ selector returns [Selector<?> result]
( '#'
adaptationName=XMLTOKEN
{
- adaptationClass = adaptationResolver.getByName($adaptationName.text);
- if (adaptationClass == null)
- throw new InvalidSelectorSyntaxException("No adaptation named " + $adaptationName.text);
+ adaptation = adaptationFactory.getByName($adaptationName.text);
}
( '('
( startIndex=INTEGER {
- try {
- adaptation = adaptationClass.getConstructor(Integer.class)
- .newInstance(Integer.parseInt($startIndex.text));
- } catch (Exception e) {
- throw new InvalidSelectorSyntaxException(e);
- }
+ adaptation.setArgs(new Object[] { Integer.parseInt($startIndex.text) });
}
| sq=SINGLE_QUOTED {
- try {
- adaptation = adaptationClass.getConstructor(String.class)
- .newInstance($sq.text);
- } catch (Exception e) {
- throw new InvalidSelectorSyntaxException(e);
- }
+ adaptation.setArgs(new Object[] { $sq.text });
}
)
')'
- | {
- try {
- adaptation = adaptationClass.newInstance();
- } catch (Exception e) {
- throw new InvalidSelectorSyntaxException(e);
- }
- }
+ |
)
{ $result = new SelectorWithAdaptation(result, adaptation); }
|
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/AbstractAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/AbstractAdaptation.java
@@ -0,0 +1,58 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+import java.util.Arrays;
+
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+public abstract class AbstractAdaptation<DestType, NodeType extends RDFNode> implements Adaptation<DestType> {
+
+ private final Class<DestType> destinationType;
+ private final Class<?>[] argTypes;
+ private final Class<NodeType> nodeType;
+
+ protected AbstractAdaptation(Class<DestType> destinationType, Class<?>[] argTypes, Class<NodeType> nodeType) {
+ this.destinationType = destinationType;
+ this.argTypes = argTypes;
+ this.nodeType = nodeType;
+ }
+
+ @Override
+ public Class<DestType> getDestinationType() {
+ return destinationType;
+ }
+
+ @Override
+ public Class<?>[] getArgTypes() {
+ return argTypes;
+ }
+
+ @Override
+ public void setArgs(Object[] args) {
+ if (args.length != argTypes.length)
+ throw new SelectorEvaluationException("Expected args of types " + Arrays.toString(argTypes) +
+ " but invoked with " + Arrays.toString(args));
+ for (int i = 0; i < args.length; i ++) {
+ if (!argTypes[i].isAssignableFrom(args[i].getClass()))
+ throw new SelectorEvaluationException("Arg " + i + ": expected type " + argTypes[i] +
+ " but was " + args[i].getClass());
+ }
+ setCheckedArgs(args);
+ }
+
+ protected void setCheckedArgs(Object[] args) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DestType adapt(RDFNode node) {
+ if (!nodeType.equals(RDFNode.class)) {
+ if (!node.canAs(nodeType))
+ throw new SelectorEvaluationException("Adaptation can only be applied to " + nodeType +
+ " but was applied to " + node);
+ }
+ return doAdapt(node.as(nodeType));
+ }
+
+ protected abstract DestType doAdapt(NodeType node);
+
+}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/Adaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/Adaptation.java
@@ -6,6 +6,10 @@ public interface Adaptation<T> {
Class<T> getDestinationType();
+ Class<?>[] getArgTypes();
+
+ void setArgs(Object[] args);
+
T adapt(RDFNode node);
}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationFactory.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationFactory.java
@@ -0,0 +1,7 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+public interface AdaptationFactory {
+
+ Adaptation<?> getByName(String name);
+
+}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java
@@ -1,7 +0,0 @@
-package au.com.miskinhill.rdftemplate.selector;
-
-public interface AdaptationResolver {
-
- 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
@@ -10,15 +10,15 @@ import org.antlr.runtime.RecognitionException;
public class AntlrSelectorFactory implements SelectorFactory {
- private AdaptationResolver adaptationResolver = new DefaultAdaptationResolver();
+ private AdaptationFactory adaptationFactory = new DefaultAdaptationFactory();
private PredicateResolver predicateResolver = new DefaultPredicateResolver();
private Map<String, String> namespacePrefixMap = Collections.emptyMap();
public AntlrSelectorFactory() {
}
- public void setAdaptationResolver(AdaptationResolver adaptationResolver) {
- this.adaptationResolver = adaptationResolver;
+ public void setAdaptationFactory(AdaptationFactory adaptationFactory) {
+ this.adaptationFactory = adaptationFactory;
}
public void setPredicateResolver(PredicateResolver predicateResolver) {
@@ -35,7 +35,7 @@ public class AntlrSelectorFactory implements SelectorFactory {
SelectorLexer lexer = new SelectorLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SelectorParser parser = new SelectorParser(tokens);
- parser.setAdaptationResolver(adaptationResolver);
+ parser.setAdaptationFactory(adaptationFactory);
parser.setPredicateResolver(predicateResolver);
parser.setNamespacePrefixMap(namespacePrefixMap);
try {
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/ComparableLiteralValueAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/ComparableLiteralValueAdaptation.java
@@ -1,21 +1,17 @@
package au.com.miskinhill.rdftemplate.selector;
import com.hp.hpl.jena.rdf.model.Literal;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-public class ComparableLiteralValueAdaptation implements Adaptation<Comparable> {
+@SuppressWarnings("unchecked")
+public class ComparableLiteralValueAdaptation extends AbstractAdaptation<Comparable, Literal> {
- @Override
- public Class<Comparable> getDestinationType() {
- return Comparable.class;
+ public ComparableLiteralValueAdaptation() {
+ super(Comparable.class, new Class<?>[] { }, Literal.class);
}
-
+
@Override
- public Comparable<?> adapt(RDFNode node) {
- if (!node.isLiteral()) {
- throw new SelectorEvaluationException("Attempted to apply #comparable-lv to non-literal node " + node);
- }
- Object literalValue = ((Literal) node).getValue();
+ protected Comparable<?> doAdapt(Literal node) {
+ Object literalValue = node.getValue();
if (!(literalValue instanceof Comparable<?>)) {
throw new SelectorEvaluationException("Attempted to apply #comparable-lv to non-Comparable node " + node +
" with literal value of type " + literalValue.getClass());
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationFactory.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationFactory.java
@@ -0,0 +1,30 @@
+package au.com.miskinhill.rdftemplate.selector;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.BeanUtils;
+
+public class DefaultAdaptationFactory implements AdaptationFactory {
+
+ 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("uri-anchor", UriAnchorAdaptation.class);
+ ADAPTATIONS.put("lv", LiteralValueAdaptation.class);
+ ADAPTATIONS.put("comparable-lv", ComparableLiteralValueAdaptation.class);
+ ADAPTATIONS.put("string-lv", StringLiteralValueAdaptation.class);
+ ADAPTATIONS.put("formatted-dt", FormattedDateTimeAdaptation.class);
+ }
+
+ @Override
+ public Adaptation<?> getByName(String name) {
+ Class<? extends Adaptation<?>> adaptationClass = ADAPTATIONS.get(name);
+ if (adaptationClass == null) {
+ throw new InvalidSelectorSyntaxException("No adaptation named " + name);
+ }
+ return BeanUtils.instantiate(adaptationClass);
+ }
+
+}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java
@@ -1,24 +0,0 @@
-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("uri-anchor", UriAnchorAdaptation.class);
- ADAPTATIONS.put("lv", LiteralValueAdaptation.class);
- ADAPTATIONS.put("comparable-lv", ComparableLiteralValueAdaptation.class);
- ADAPTATIONS.put("string-lv", StringLiteralValueAdaptation.class);
- ADAPTATIONS.put("formatted-dt", FormattedDateTimeAdaptation.class);
- }
-
- @Override
- public Class<? extends Adaptation<?>> getByName(String name) {
- return ADAPTATIONS.get(name);
- }
-
-}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/FormattedDateTimeAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/FormattedDateTimeAdaptation.java
@@ -1,21 +1,25 @@
package au.com.miskinhill.rdftemplate.selector;
import org.apache.commons.lang.builder.ToStringBuilder;
-
-import com.hp.hpl.jena.rdf.model.Literal;
-import com.hp.hpl.jena.rdf.model.RDFNode;
import org.joda.time.ReadableInstant;
import org.joda.time.ReadablePartial;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
-public class FormattedDateTimeAdaptation implements Adaptation<String> {
+import com.hp.hpl.jena.rdf.model.Literal;
+
+public class FormattedDateTimeAdaptation extends AbstractAdaptation<String, Literal> {
+
+ private String pattern;
+ private DateTimeFormatter formatter;
- private final String pattern;
- private final DateTimeFormatter formatter;
+ public FormattedDateTimeAdaptation() {
+ super(String.class, new Class<?>[] { String.class }, Literal.class);
+ }
- public FormattedDateTimeAdaptation(String pattern) {
- this.pattern = pattern;
+ @Override
+ protected void setCheckedArgs(Object[] args) {
+ this.pattern = (String) args[0];
this.formatter = DateTimeFormat.forPattern(pattern.replace("\"", "'")); // for convenience in XML
}
@@ -24,16 +28,8 @@ public class FormattedDateTimeAdaptation implements Adaptation<String> {
}
@Override
- public Class<String> getDestinationType() {
- return String.class;
- }
-
- @Override
- public String adapt(RDFNode node) {
- if (!node.isLiteral()) {
- throw new SelectorEvaluationException("Attempted to apply #formatted-dt to non-literal node " + node);
- }
- Object lv = ((Literal) node).getValue();
+ protected String doAdapt(Literal node) {
+ Object lv = node.getValue();
if (lv instanceof ReadableInstant) {
ReadableInstant instant = (ReadableInstant) lv;
return formatter.print(instant);
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/LiteralValueAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/LiteralValueAdaptation.java
@@ -1,21 +1,16 @@
package au.com.miskinhill.rdftemplate.selector;
import com.hp.hpl.jena.rdf.model.Literal;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-public class LiteralValueAdaptation implements Adaptation<Object> {
+public class LiteralValueAdaptation extends AbstractAdaptation<Object, Literal> {
- @Override
- public Class<Object> getDestinationType() {
- return Object.class;
+ public LiteralValueAdaptation() {
+ super(Object.class, new Class<?>[] { }, Literal.class);
}
-
+
@Override
- public Object adapt(RDFNode node) {
- if (!node.isLiteral()) {
- throw new SelectorEvaluationException("Attempted to apply #lv to non-literal node " + node);
- }
- return ((Literal) node).getValue();
+ protected Object doAdapt(Literal node) {
+ return node.getValue();
}
}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/StringLiteralValueAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/StringLiteralValueAdaptation.java
@@ -8,23 +8,17 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import com.hp.hpl.jena.rdf.model.Literal;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-public class StringLiteralValueAdaptation implements Adaptation<String> {
+public class StringLiteralValueAdaptation extends AbstractAdaptation<String, Literal> {
private static final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
- @Override
- public Class<String> getDestinationType() {
- return String.class;
+ public StringLiteralValueAdaptation() {
+ super(String.class, new Class<?>[] { }, Literal.class);
}
-
+
@Override
- public String adapt(RDFNode node) {
- if (!node.isLiteral()) {
- throw new SelectorEvaluationException("Attempted to apply #lv to non-literal node " + node);
- }
- Literal literal = node.as(Literal.class);
+ protected String doAdapt(Literal literal) {
if (literal.isWellFormedXML()) {
try {
return stripTags(literal.getLexicalForm());
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/UriAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/UriAdaptation.java
@@ -2,21 +2,15 @@ package au.com.miskinhill.rdftemplate.selector;
import com.hp.hpl.jena.rdf.model.Resource;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-
-public class UriAdaptation implements Adaptation<String> {
+public class UriAdaptation extends AbstractAdaptation<String, Resource> {
- @Override
- public Class<String> getDestinationType() {
- return String.class;
+ public UriAdaptation() {
+ super(String.class, new Class<?>[] { }, Resource.class);
}
@Override
- public String adapt(RDFNode node) {
- if (!node.isResource()) {
- throw new SelectorEvaluationException("Attempted to apply #uri to non-resource node " + node);
- }
- return ((Resource) node).getURI();
+ protected String doAdapt(Resource node) {
+ return node.getURI();
}
}
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/UriAnchorAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/UriAnchorAdaptation.java
@@ -1,25 +1,20 @@
package au.com.miskinhill.rdftemplate.selector;
-import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
/**
* Returns the anchor component of the node's URI (excluding initial #), or the
* empty string if it has no anchor component.
*/
-public class UriAnchorAdaptation implements Adaptation<String> {
+public class UriAnchorAdaptation extends AbstractAdaptation<String, Resource> {
- @Override
- public Class<String> getDestinationType() {
- return String.class;
+ public UriAnchorAdaptation() {
+ super(String.class, new Class<?>[] { }, Resource.class);
}
-
+
@Override
- public String adapt(RDFNode node) {
- if (!node.isResource()) {
- throw new SelectorEvaluationException("Attempted to apply #uri-anchor to non-resource node " + node);
- }
- String uri = ((Resource) node).getURI();
+ protected String doAdapt(Resource node) {
+ String uri = node.getURI();
int hashIndex = uri.lastIndexOf('#');
if (hashIndex < 0)
return "";
diff --git a/src/main/java/au/com/miskinhill/rdftemplate/selector/UriSliceAdaptation.java b/src/main/java/au/com/miskinhill/rdftemplate/selector/UriSliceAdaptation.java
@@ -1,14 +1,13 @@
package au.com.miskinhill.rdftemplate.selector;
-import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
-public class UriSliceAdaptation implements Adaptation<String> {
+public class UriSliceAdaptation extends AbstractAdaptation<String, Resource> {
- private final Integer startIndex;
+ private Integer startIndex;
- public UriSliceAdaptation(Integer startIndex) {
- this.startIndex = startIndex;
+ public UriSliceAdaptation() {
+ super(String.class, new Class<?>[] { Integer.class }, Resource.class);
}
public Integer getStartIndex() {
@@ -16,16 +15,13 @@ public class UriSliceAdaptation implements Adaptation<String> {
}
@Override
- public Class<String> getDestinationType() {
- return String.class;
+ protected void setCheckedArgs(Object[] args) {
+ this.startIndex = (Integer) args[0];
}
-
+
@Override
- public String adapt(RDFNode node) {
- if (!node.isResource()) {
- throw new SelectorEvaluationException("Attempted to apply #uri-slice to non-resource node " + node);
- }
- String uri = ((Resource) node).getURI();
+ protected String doAdapt(Resource node) {
+ String uri = node.getURI();
return uri.substring(startIndex);
}