rdftemplate

Library for generating XML documents from RDF data using templates
git clone https://code.djc.id.au/git/rdftemplate/
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:
Msrc/main/antlr3/au/com/miskinhill/rdftemplate/selector/Selector.g | 33+++++++--------------------------
Asrc/main/java/au/com/miskinhill/rdftemplate/selector/AbstractAdaptation.java | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/Adaptation.java | 4++++
Asrc/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationFactory.java | 7+++++++
Dsrc/main/java/au/com/miskinhill/rdftemplate/selector/AdaptationResolver.java | 7-------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/AntlrSelectorFactory.java | 8++++----
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/ComparableLiteralValueAdaptation.java | 18+++++++-----------
Asrc/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationFactory.java | 30++++++++++++++++++++++++++++++
Dsrc/main/java/au/com/miskinhill/rdftemplate/selector/DefaultAdaptationResolver.java | 24------------------------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/FormattedDateTimeAdaptation.java | 32++++++++++++++------------------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/LiteralValueAdaptation.java | 17++++++-----------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/StringLiteralValueAdaptation.java | 16+++++-----------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/UriAdaptation.java | 16+++++-----------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/UriAnchorAdaptation.java | 17++++++-----------
Msrc/main/java/au/com/miskinhill/rdftemplate/selector/UriSliceAdaptation.java | 22+++++++++-------------
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);
     }