Author: davsclaus
Date: Wed Jan 20 13:32:34 2010
New Revision: 901192

URL: http://svn.apache.org/viewvc?rev=901192&view=rev
Log:
CAMEL-2391: JAXB data format not supports partial (not marshal/unmarshal the 
entire graph). Applied patch with much thanks to Lukasz Dywicik.

Added:
    
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
   (with props)
    
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
   (with props)
    
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
   (with props)
Modified:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
    
camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
    
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
 Wed Jan 20 13:32:34 2010
@@ -20,6 +20,7 @@
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.namespace.QName;
 
 import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.spi.DataFormat;
@@ -44,6 +45,12 @@
     @XmlAttribute(required = false)
     private String encoding;
 
+    // Partial encoding
+    @XmlAttribute(required = false)
+    private String partClass;
+    @XmlAttribute(required = false)
+    private String partNamespace;
+
     public JaxbDataFormat() {
         super("jaxb");
     }
@@ -84,7 +91,19 @@
     public void setFilterNonXmlChars(Boolean filterNonXmlChars) {
         this.filterNonXmlChars = filterNonXmlChars;
     }
-    
+
+    public String getPartClass() {
+        return partClass;
+    }
+
+    public void setPartClass(String partClass) {
+        this.partClass = partClass;
+    }
+
+    public void setPartNamespace(String partNamespace) {
+        this.partNamespace = partNamespace;
+    }
+
     @Override
     protected void configureDataFormat(DataFormat dataFormat) {
         Boolean answer = ObjectHelper.toBoolean(getPrettyPrint());
@@ -104,7 +123,13 @@
             setProperty(dataFormat, "filterNonXmlChars", Boolean.TRUE);
         } else { // the default value is false
             setProperty(dataFormat, "filterNonXmlChars", Boolean.FALSE);
-        }        
+        }
+        if (partClass != null) {
+            setProperty(dataFormat, "partClass", partClass);
+        }
+        if (partNamespace != null) {
+            setProperty(dataFormat, "partNamespace", 
QName.valueOf(partNamespace));
+        }
         if (encoding != null) {
             setProperty(dataFormat, "encoding", encoding);
         }

Modified: 
camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- 
camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
 (original)
+++ 
camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
 Wed Jan 20 13:32:34 2010
@@ -20,14 +20,20 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.stream.FactoryConfigurationError;
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.converter.IOConverter;
@@ -48,6 +54,10 @@
     private boolean ignoreJAXBElement = true;
     private boolean filterNonXmlChars;
     private String encoding;
+    // partial support
+    private QName partNamespace;
+    private String partClass;
+    private Class partialClass;
 
     public JaxbDataFormat() {
     }
@@ -85,26 +95,52 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
     void marshal(Exchange exchange, Object graph, OutputStream stream, 
Marshaller marshaller)
         throws XMLStreamException, JAXBException {
+
+        Object e = graph;
+        if (getPartClass() != null && getPartNamespace() != null) {
+            e = new JAXBElement(getPartNamespace(), getPartialClass(exchange), 
graph);
+        }
+
         if (needFiltering(exchange)) {
-            XMLStreamWriter writer = 
XMLOutputFactory.newInstance().createXMLStreamWriter(stream);
-            FilteringXmlStreamWriter filteringWriter = new 
FilteringXmlStreamWriter(writer);
-            marshaller.marshal(graph, filteringWriter);
+            marshaller.marshal(e, createFilteringWriter(stream));
         } else {
-            marshaller.marshal(graph, stream);
+            marshaller.marshal(e, stream);
         }
     }
-    
+
+    private FilteringXmlStreamWriter createFilteringWriter(OutputStream stream)
+        throws XMLStreamException, FactoryConfigurationError {
+        XMLStreamWriter writer = 
XMLOutputFactory.newInstance().createXMLStreamWriter(stream);
+        FilteringXmlStreamWriter filteringWriter = new 
FilteringXmlStreamWriter(writer);
+        return filteringWriter;
+    }
+
+    @SuppressWarnings("unchecked")
     public Object unmarshal(Exchange exchange, InputStream stream) throws 
IOException {
         try {
             // must create a new instance of unmarshaller as its not thread 
safe
             Object answer;
             Unmarshaller unmarshaller = getContext().createUnmarshaller();
-            if (needFiltering(exchange)) {
-                answer = unmarshaller.unmarshal(new NonXmlFilterReader(new 
InputStreamReader(stream, IOConverter.getCharsetName(exchange))));
-            } else  {
-                answer = unmarshaller.unmarshal(stream);
+
+            if (getPartClass() != null) {
+                // partial unmarshalling
+                Source source;
+                if (needFiltering(exchange)) {
+                    source = new 
StreamSource(createNonXmlFilterReader(exchange, stream));
+                } else {
+                    source = new StreamSource(stream);
+                }
+                answer = unmarshaller.unmarshal(source, 
getPartialClass(exchange));
+            } else {
+                if (needFiltering(exchange)) {
+                    NonXmlFilterReader reader = 
createNonXmlFilterReader(exchange, stream);
+                    answer = unmarshaller.unmarshal(reader);
+                } else  {
+                    answer = unmarshaller.unmarshal(stream);
+                }
             }
 
             if (answer instanceof JAXBElement && isIgnoreJAXBElement()) {
@@ -115,12 +151,23 @@
             throw IOHelper.createIOException(e);
         }
     }
-    
+
+    private NonXmlFilterReader createNonXmlFilterReader(Exchange exchange, 
InputStream stream) throws UnsupportedEncodingException {
+        return new NonXmlFilterReader(new InputStreamReader(stream, 
IOConverter.getCharsetName(exchange)));
+    }
+
     protected boolean needFiltering(Exchange exchange) {
         // exchange property takes precedence over data format property
         return exchange == null ? filterNonXmlChars : 
exchange.getProperty(Exchange.FILTER_NON_XML_CHARS, filterNonXmlChars, 
Boolean.class);
     }
 
+    private synchronized Class getPartialClass(Exchange exchange) {
+        if (partialClass == null) {
+            partialClass = 
exchange.getContext().getClassResolver().resolveClass(getPartClass());
+        }
+        return partialClass;
+    }
+
     // Properties
     // 
-------------------------------------------------------------------------
     public boolean isIgnoreJAXBElement() {        
@@ -174,6 +221,22 @@
         this.encoding = encoding;
     }
 
+    public final QName getPartNamespace() {
+        return partNamespace;
+    }
+
+    public final void setPartNamespace(QName partNamespace) {
+        this.partNamespace = partNamespace;
+    }
+
+    public final String getPartClass() {
+        return partClass;
+    }
+
+    public final void setPartClass(String partClass) {
+        this.partClass = partClass;
+    }
+
     protected JAXBContext createContext() throws JAXBException {
         if (contextPath != null) {
             return JAXBContext.newInstance(contextPath);

Added: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java?rev=901192&view=auto
==============================================================================
--- 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
 (added)
+++ 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
 Wed Jan 20 13:32:34 2010
@@ -0,0 +1,81 @@
+/**
+ * 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.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Partial element without XmlRootElement annotation for partial testing.
+ */
+...@xmlaccessortype(XmlAccessType.FIELD)
+...@xmltype(name = "Partial")
+public class Partial {
+
+    @XmlAttribute
+    private String name;
+
+    @XmlElement
+    private String location;
+
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(String name) {
+        this.name = name;
+    }
+
+    public final String getLocation() {
+        return location;
+    }
+
+    public final void setLocation(String location) {
+        this.location = location;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Partial partial = (Partial) o;
+
+        if (location != null ? !location.equals(partial.location) : 
partial.location != null) {
+            return false;
+        }
+        if (name != null ? !name.equals(partial.name) : partial.name != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (location != null ? location.hashCode() : 0);
+        return result;
+    }
+}

Propchange: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java?rev=901192&view=auto
==============================================================================
--- 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
 (added)
+++ 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
 Wed Jan 20 13:32:34 2010
@@ -0,0 +1,71 @@
+/**
+ * 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.example;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.language.MethodCallExpression;
+import org.apache.camel.model.language.XPathExpression;
+import org.apache.camel.test.junit4.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Partial operations test.
+ */
+public class SpringDataFormatPartialTest extends CamelSpringTestSupport {
+
+    @Test
+    public void testPartialMarshal() throws Exception {
+        PurchaseOrder bean = new PurchaseOrder();
+        bean.setName("Beer");
+        bean.setAmount(23);
+        bean.setPrice(2.5);
+
+        MockEndpoint mock = resolveMandatoryEndpoint("mock:marshal", 
MockEndpoint.class);
+        mock.expectedMessageCount(1);
+
+        XPathExpression xpath = new XPathExpression("count(//*[namespace-uri() 
= 'http://example.camel.org/apache' and local-name() = 'po']) = 1");
+        xpath.setResultType(Boolean.class);
+        mock.allMessages().body().matches(xpath);
+
+        template.sendBody("direct:marshal", bean);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testPartialUnmarshal() throws Exception {
+        MockEndpoint mock = resolveMandatoryEndpoint("mock:unmarshal", 
MockEndpoint.class);
+        mock.expectedMessageCount(1);
+
+        Partial partial = new Partial();
+        partial.setName("mock");
+        partial.setLocation("org.apache.camel");
+        mock.expectedBodyReceived().constant(partial);
+
+        String xml = "<Partial 
name=\"mock\"><location>org.apache.camel</location></Partial>";
+        template.sendBody("direct:unmarshal", xml);
+
+        mock.assertIsSatisfied();
+    }
+
+    protected ClassPathXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/example/springDataFormatPartial.xml");
+    }
+
+}
\ No newline at end of file

Propchange: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index
 (original)
+++ 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index
 Wed Jan 20 13:32:34 2010
@@ -14,4 +14,5 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 ## ------------------------------------------------------------------------
-PurchaseOrder
\ No newline at end of file
+PurchaseOrder
+Partial
\ No newline at end of file

Added: 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml?rev=901192&view=auto
==============================================================================
--- 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
 (added)
+++ 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
 Wed Jan 20 13:32:34 2010
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+    <!-- START SNIPPET: example -->
+    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring";>
+        <route>
+            <from uri="direct:marshal"/>
+            <marshal>
+                <jaxb prettyPrint="false" 
contextPath="org.apache.camel.example"
+                    partClass="org.apache.camel.example.PurchaseOrder"
+                    partNamespace="{http://example.camel.org/apache}po"; />
+            </marshal>
+            <to uri="mock:marshal"/>
+        </route>
+        <route>
+            <from uri="direct:unmarshal"/>
+            <unmarshal>
+                <jaxb prettyPrint="false" 
contextPath="org.apache.camel.example"
+                    partClass="org.apache.camel.example.Partial" />
+            </unmarshal>
+            <to uri="mock:unmarshal"/>
+        </route>
+    </camelContext>
+    <!-- END SNIPPET: example -->
+
+</beans>

Propchange: 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: 
camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml


Reply via email to