Repository: camel
Updated Branches:
  refs/heads/master 059aaf024 -> 94d527783


CAMEL-8250: camel-saxon add type converter for Saxon types. Thanks to Stephan 
Siano for the patch.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/94d52778
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/94d52778
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/94d52778

Branch: refs/heads/master
Commit: 94d527783719f495c05df4caea7dcece2113d065
Parents: 059aaf0
Author: Claus Ibsen <davscl...@apache.org>
Authored: Sat Jan 17 11:50:03 2015 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Sat Jan 17 11:50:03 2015 +0100

----------------------------------------------------------------------
 components/camel-saxon/pom.xml                  |   3 +-
 .../camel/converter/saxon/SaxonConverter.java   | 132 +++++++++++++++++
 .../services/org/apache/camel/TypeConverter     |  18 +++
 .../converter/saxon/SaxonConverterTest.java     | 143 +++++++++++++++++++
 4 files changed, 295 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/94d52778/components/camel-saxon/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-saxon/pom.xml b/components/camel-saxon/pom.xml
index d2da420..bc0cc9f 100644
--- a/components/camel-saxon/pom.xml
+++ b/components/camel-saxon/pom.xml
@@ -32,7 +32,8 @@
   <properties>
     <camel.osgi.export.pkg>
       org.apache.camel.component.xquery.*,
-      org.apache.camel.language.xquery.*
+      org.apache.camel.language.xquery.*,
+      org.apache.camel.converter.saxon.*
     </camel.osgi.export.pkg>
     <camel.osgi.export.service>
       org.apache.camel.spi.ComponentResolver;component=xquery,

http://git-wip-us.apache.org/repos/asf/camel/blob/94d52778/components/camel-saxon/src/main/java/org/apache/camel/converter/saxon/SaxonConverter.java
----------------------------------------------------------------------
diff --git 
a/components/camel-saxon/src/main/java/org/apache/camel/converter/saxon/SaxonConverter.java
 
b/components/camel-saxon/src/main/java/org/apache/camel/converter/saxon/SaxonConverter.java
new file mode 100644
index 0000000..5e18e64
--- /dev/null
+++ 
b/components/camel-saxon/src/main/java/org/apache/camel/converter/saxon/SaxonConverter.java
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.saxon;
+
+import java.util.LinkedList;
+import java.util.List;
+import javax.xml.transform.dom.DOMSource;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import net.sf.saxon.Configuration;
+import net.sf.saxon.dom.DOMNodeList;
+import net.sf.saxon.dom.NodeOverNodeInfo;
+import net.sf.saxon.om.DocumentInfo;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.type.Type;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.FallbackConverter;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+@Converter
+public final class SaxonConverter {
+
+    private SaxonConverter() {
+    }
+
+    @Converter
+    public static Document toDOMDocument(NodeInfo node) throws XPathException {
+        switch (node.getNodeKind()) {
+        case Type.DOCUMENT:
+            // DOCUMENT type nodes can be wrapped directly
+            return (Document) NodeOverNodeInfo.wrap(node);
+        case Type.ELEMENT:
+            // ELEMENT nodes need to build a new DocumentInfo before wrapping
+            Configuration config = node.getConfiguration();
+            DocumentInfo documentInfo = config.buildDocument(node);
+            return (Document) NodeOverNodeInfo.wrap(documentInfo);
+        default:
+            return null;
+        }
+    }
+
+    @Converter
+    public static Node toDOMNode(NodeInfo node) {
+        return NodeOverNodeInfo.wrap(node);
+    }
+
+    @Converter
+    public static DOMSource toDOMSourceFromNodeInfo(NodeInfo nodeInfo) {
+        return new DOMSource(toDOMNode(nodeInfo));
+    }
+
+    @Converter
+    public static NodeList toDOMNodeList(List<? extends NodeInfo> nodeList) {
+        List<Node> domNodeList = new LinkedList<Node>();
+        if (nodeList != null) {
+            for (NodeInfo ni : nodeList) {
+                domNodeList.add(NodeOverNodeInfo.wrap(ni));
+            }
+        }
+        return new DOMNodeList(domNodeList);
+    }
+
+    @FallbackConverter
+    public static <T> T convertTo(Class<T> type, Exchange exchange, Object 
value, TypeConverterRegistry registry) {
+        if (NodeInfo.class.isAssignableFrom(value.getClass())) {
+            // use a fallback type converter so we can convert the embedded 
body if the value is NodeInfo
+            NodeInfo ni = (NodeInfo) value;
+            // first try to find a Converter for Node
+            TypeConverter tc = registry.lookup(type, Node.class);
+            if (tc != null) {
+                Node node = NodeOverNodeInfo.wrap(ni);
+                return tc.convertTo(type, exchange, node);
+            }
+            // if this does not exist we can also try NodeList (there are some 
type converters for that) as
+            // the default Xerces Node implementation also implements NodeList.
+            tc = registry.lookup(type, NodeList.class);
+            if (tc != null) {
+                List<NodeInfo> nil = new LinkedList<NodeInfo>();
+                nil.add((NodeInfo) value);
+                return tc.convertTo(type, exchange, toDOMNodeList(nil));
+            }
+        } else if (List.class.isAssignableFrom(value.getClass())) {
+            TypeConverter tc = registry.lookup(type, NodeList.class);
+            if (tc != null) {
+                List<NodeInfo> lion = new LinkedList<NodeInfo>();
+                for (Object o : (List<?>) value) {
+                    if (o instanceof NodeInfo) {
+                        lion.add((NodeInfo) o);
+                    }
+                }
+                if (lion.size() > 0) {
+                    NodeList nl = toDOMNodeList(lion);
+                    return tc.convertTo(type, exchange, nl);
+                }
+            }
+        } else if (NodeOverNodeInfo.class.isAssignableFrom(value.getClass())) {
+            // NodeOverNode info is a read-only Node implementation from 
Saxon. In contrast to the JDK
+            // com.sun.org.apache.xerces.internal.dom.NodeImpl class it does 
not implement NodeList, but
+            // many Camel type converters are based on that interface. 
Therefore we convert to NodeList and
+            // try type conversion in the fallback type converter.
+            TypeConverter tc = registry.lookup(type, NodeList.class);
+            if (tc != null) {
+                List<Node> domNodeList = new LinkedList<Node>();
+                domNodeList.add((NodeOverNodeInfo) value);
+                return tc.convertTo(type, exchange, new 
DOMNodeList(domNodeList));
+            }
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/94d52778/components/camel-saxon/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
----------------------------------------------------------------------
diff --git 
a/components/camel-saxon/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
 
b/components/camel-saxon/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
new file mode 100644
index 0000000..b666928
--- /dev/null
+++ 
b/components/camel-saxon/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.camel.converter.saxon.SaxonConverter
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/94d52778/components/camel-saxon/src/test/java/org/apache/camel/converter/saxon/SaxonConverterTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-saxon/src/test/java/org/apache/camel/converter/saxon/SaxonConverterTest.java
 
b/components/camel-saxon/src/test/java/org/apache/camel/converter/saxon/SaxonConverterTest.java
new file mode 100644
index 0000000..5509dc3
--- /dev/null
+++ 
b/components/camel-saxon/src/test/java/org/apache/camel/converter/saxon/SaxonConverterTest.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.saxon;
+
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.xpath.XPathEvaluator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.StringSource;
+import org.apache.camel.builder.xml.DefaultNamespaceContext;
+import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SaxonConverterTest extends CamelTestSupport {
+    private static final String CONTENT = "<a 
xmlns=\"http://www.apache.org/test\";><b 
foo=\"bar\">test</b><c><d>foobar</d></c></a>";
+    private static final String CONTENT_B = "<b 
xmlns=\"http://www.apache.org/test\"; foo=\"bar\">test</b>";
+    private static final NamespaceContext NS_CONTEXT = (new 
DefaultNamespaceContext()).add("ns1", "http://www.apache.org/test";);
+
+    private Exchange exchange;
+    private XPathEvaluator evaluator;
+    private NodeInfo doc;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        exchange = new DefaultExchange(context);
+        evaluator = new XPathEvaluator();
+        doc = evaluator.setSource(new StringSource(CONTENT));
+    }
+
+    @Test
+    public void convertToDOMSource() throws XPathException {
+        DOMSource source = 
context.getTypeConverter().convertTo(DOMSource.class, exchange, doc);
+        assertNotNull(source);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, source);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertToDocument() throws XPathException {
+        Document document = 
context.getTypeConverter().convertTo(Document.class, exchange, doc);
+        assertNotNull(document);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, document);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertSubNodeToDocument() throws XPathException, 
XPathExpressionException {
+        evaluator.setNamespaceContext(NS_CONTEXT);
+        Object nodeObj = evaluator.evaluate("/ns1:a/ns1:b", doc, 
XPathConstants.NODE);
+        assertNotNull(nodeObj);
+        Document document = 
context.getTypeConverter().convertTo(Document.class, exchange, nodeObj);
+        assertNotNull(document);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, document);
+        assertEquals(CONTENT_B, string);
+    }
+
+    @Test
+    public void convertSubNodeSetToDocument() throws XPathException, 
XPathExpressionException {
+        evaluator.setNamespaceContext(NS_CONTEXT);
+        Object nodeObj = evaluator.evaluate("/ns1:a/ns1:b", doc, 
XPathConstants.NODESET);
+        assertNotNull(nodeObj);
+        Document document = 
context.getTypeConverter().convertTo(Document.class, exchange, nodeObj);
+        assertNotNull(document);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, document);
+        assertEquals(CONTENT_B, string);
+    }
+
+    @Test
+    public void convertToNode() throws XPathException {
+        Node node = context.getTypeConverter().convertTo(Node.class, exchange, 
doc);
+        assertNotNull(node);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, node);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertToNodeList() throws XPathException {
+        List<NodeInfo> nil = new LinkedList<NodeInfo>();
+        nil.add(doc);
+        NodeList nodeList = 
context.getTypeConverter().convertTo(NodeList.class, exchange, nil);
+        assertNotNull(nodeList);
+        assertEquals(1, nodeList.getLength());
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, nodeList);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertToInputStream() throws XPathException {
+        InputStream is = 
context.getTypeConverter().convertTo(InputStream.class, exchange, doc);
+        assertNotNull(is);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, is);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertToByteArray() throws XPathException {
+        byte[] ba = context.getTypeConverter().convertTo(byte[].class, 
exchange, doc);
+        assertNotNull(ba);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, ba);
+        assertEquals(CONTENT, string);
+    }
+
+    @Test
+    public void convertToNodeAndByteArray() throws XPathException {
+        Node node = context.getTypeConverter().convertTo(Node.class, exchange, 
doc);
+        assertNotNull(node);
+        byte[] ba = context.getTypeConverter().convertTo(byte[].class, 
exchange, node);
+        assertNotNull(ba);
+        String string = context.getTypeConverter().convertTo(String.class, 
exchange, ba);
+        assertEquals(CONTENT, string);
+    }
+}

Reply via email to