You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by si...@apache.org on 2010/06/26 19:07:08 UTC
svn commit: r958243 - in /cocoon/cocoon3/trunk/cocoon-optional/src:
main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/
test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/
Author: simonetripodi
Date: Sat Jun 26 17:07:07 2010
New Revision: 958243
URL: http://svn.apache.org/viewvc?rev=958243&view=rev
Log:
added the collection generic type support
Added:
cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java (with props)
Modified:
cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java
Added: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java?rev=958243&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java (added)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java Sat Jun 26 17:07:07 2010
@@ -0,0 +1,72 @@
+/*
+ * 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.cocoon.optional.pipeline.components.sax.jaxb;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * @version $Id$
+ */
+class GenericUtils {
+
+ /**
+ * This class can't be instantiated.
+ */
+ private GenericUtils() {
+ // do nothing
+ }
+
+ /**
+ * Returns the type from super class's type parameter.
+ */
+ public static Type getSuperclassTypeParameter(Class<?> subclass) {
+ Type superclass = subclass.getGenericSuperclass();
+ if (!(superclass instanceof ParameterizedType)) {
+ throw new RuntimeException("Missing type parameter.");
+ }
+ ParameterizedType parameterized = (ParameterizedType) superclass;
+ return parameterized.getActualTypeArguments()[0];
+ }
+
+ /**
+ * Get the class of the parameter of the provided parameterized type. If the
+ * type is a Class, then <code>null</code> is returned. If the type is
+ * ParameterizedType, then the actual type argument is returned.
+ * <p>
+ * E.g. if type is <code>String.class</code>, then <code>null</code> is
+ * returned. If type is <code>List<String></code>, then
+ * <code>String.class</code> is returned.
+ * <p>
+ * In case the type has more than one parameter, only the type of the first
+ * parameter is returned by this method.
+ *
+ * @param type the type to return the class of the parameter for
+ * @return the class of the generic parameter of type
+ */
+ public static Class<?> getGenericParamType(Type type) {
+ Class<?> generic = null;
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+ generic = (Class<?>) actualTypeArguments[0];
+ }
+ return generic;
+ }
+}
Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/GenericUtils.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java?rev=958243&r1=958242&r2=958243&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java Sat Jun 26 17:07:07 2010
@@ -18,6 +18,8 @@
*/
package org.apache.cocoon.optional.pipeline.components.sax.jaxb;
+import java.lang.reflect.Type;
+
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@@ -32,7 +34,7 @@ import org.xml.sax.helpers.AttributesImp
/**
* SAX generator that produces SAX events from Object using the JAXB marshaller.
*/
-public final class JAXBGenerator extends AbstractSAXGenerator implements CachingPipelineComponent {
+public abstract class JAXBGenerator<T> extends AbstractSAXGenerator implements CachingPipelineComponent {
private static final String DEFAULT = "##default";
@@ -42,17 +44,36 @@ public final class JAXBGenerator extends
private final InMemoryLRUMarshallerCache marshallerCache = InMemoryLRUMarshallerCache.getInstance();
- private final Object toBeMarshalled;
+ private final T toBeMarshalled;
+
+ private final Class<?> type;
private String charset = UTF_8;
private boolean formattedOutput = false;
- public JAXBGenerator(Object toBeMarshalled) {
+ private boolean pluralize = false;
+
+ public JAXBGenerator(T toBeMarshalled) {
if (toBeMarshalled == null) {
throw new IllegalArgumentException("Argument 'toBeMarshalled' must not be null");
}
this.toBeMarshalled = toBeMarshalled;
+ Class<?> rawType = toBeMarshalled.getClass();
+ // analyze generics for collections
+ if (Iterable.class.isAssignableFrom(rawType)) {
+ Type type = GenericUtils.getSuperclassTypeParameter(this.getClass());
+ if (type == null) {
+ throw new IllegalArgumentException("Generic type is not defined");
+ }
+ this.type = GenericUtils.getGenericParamType(type);
+ this.pluralize = true;
+ } else if (rawType.isArray()) { // else get array type
+ this.pluralize = true;
+ this.type = rawType.getComponentType();
+ } else { // otherwise is the passed argument type
+ this.type = rawType;
+ }
}
public String getCharset() {
@@ -71,26 +92,14 @@ public final class JAXBGenerator extends
this.formattedOutput = formattedOutput;
}
- public void execute() {
+ public final void execute() {
// retrieve the right type has to be marshaled
String xmlRootElementName = null;
String xmlRootElementNameSpace = null;
- boolean pluralize = false;
- Class<?> type = this.toBeMarshalled.getClass();
-
- // analyze generics for collections
- if (Iterable.class.isAssignableFrom(type)) {
- pluralize = true;
- // TODO extract the generic type!!!
- } else if (type.isArray()) { // else get array type
- pluralize = true;
- type = type.getComponentType();
- }
- // otherwise is the passed argument type
// validate the type can be marshaled using JAXB
- if (!type.isAnnotationPresent(XmlRootElement.class)
- && !type.isAnnotationPresent(XmlType.class)) {
+ if (!this.type.isAnnotationPresent(XmlRootElement.class)
+ && !this.type.isAnnotationPresent(XmlType.class)) {
throw new IllegalArgumentException("Object of type "
+ type.getName()
+ " can't be marshalled since neither of "
@@ -101,14 +110,14 @@ public final class JAXBGenerator extends
}
// get the root element name if needed
- if (pluralize) {
+ if (this.pluralize) {
String name = null;
- if (type.isAnnotationPresent(XmlRootElement.class)) {
- XmlRootElement xmlRootElement = type.getAnnotation(XmlRootElement.class);
+ if (this.type.isAnnotationPresent(XmlRootElement.class)) {
+ XmlRootElement xmlRootElement = this.type.getAnnotation(XmlRootElement.class);
name = xmlRootElement.name();
xmlRootElementNameSpace = xmlRootElement.namespace();
- } else if (type.isAnnotationPresent(XmlType.class)) {
- XmlType xmlType = type.getAnnotation(XmlType.class);
+ } else if (this.type.isAnnotationPresent(XmlType.class)) {
+ XmlType xmlType = this.type.getAnnotation(XmlType.class);
name = xmlType.name();
xmlRootElementNameSpace = xmlType.namespace();
}
@@ -123,20 +132,19 @@ public final class JAXBGenerator extends
xmlRootElementNameSpace = EMPTY;
}
- // pluralize
// TODO has to be improved, see PluralStemmers reference impl
xmlRootElementName += 's';
}
try {
- Marshaller xmlMarshaller = marshallerCache.getMarshaller(type);
+ Marshaller xmlMarshaller = this.marshallerCache.getMarshaller(type);
if (this.charset != null) {
xmlMarshaller.setProperty(Marshaller.JAXB_ENCODING, this.charset);
}
xmlMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, this.formattedOutput);
// setup the Marshaler if a collection has to be marshaled
- if (pluralize) {
+ if (this.pluralize) {
xmlMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
this.getSAXConsumer().startDocument();
this.getSAXConsumer().startElement(xmlRootElementNameSpace, xmlRootElementName, xmlRootElementName, new AttributesImpl());
Modified: cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java?rev=958243&r1=958242&r2=958243&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java (original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java Sat Jun 26 17:07:07 2010
@@ -21,6 +21,8 @@ package org.apache.cocoon.optional.pipel
import static junit.framework.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.cocoon.pipeline.NonCachingPipeline;
import org.apache.cocoon.pipeline.Pipeline;
@@ -29,9 +31,12 @@ import org.apache.cocoon.sax.component.X
import org.custommonkey.xmlunit.Diff;
import org.junit.Test;
+/**
+ * $Id$
+ */
public final class JAXBGeneratorTestCase {
- // @Test
+ @Test
public void testPipelineWithBean() throws Exception {
Animal animal = new Animal();
animal.setAge(5);
@@ -40,7 +45,8 @@ public final class JAXBGeneratorTestCase
animal.setLatinName("Mustela putoris furo");
animal.setName("Lector");
- this.internalAssert(animal, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal>");
+ this.internalAssert(new JAXBGenerator<Animal>(animal) {},
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal>");
}
@Test
@@ -52,13 +58,30 @@ public final class JAXBGeneratorTestCase
animal.setLatinName("Mustela putoris furo");
animal.setName("Lector");
- this.internalAssert(new Animal[]{ animal, animal },
+ this.internalAssert(new JAXBGenerator<Animal[]>(new Animal[]{ animal, animal }) {},
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animals><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal></animals>");
+ }
+
+ @Test
+ public void testPipelineWithBeanList() throws Exception {
+ Animal animal = new Animal();
+ animal.setAge(5);
+ animal.setCall("Dook");
+ animal.setColour("albino");
+ animal.setLatinName("Mustela putoris furo");
+ animal.setName("Lector");
+
+ List<Animal> animals = new ArrayList<Animal>();
+ animals.add(animal);
+ animals.add(animal);
+
+ this.internalAssert(new JAXBGenerator<List<Animal>>(animals) {},
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><animals><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal><animal><call>Dook</call><colour>albino</colour><latinName>Mustela putoris furo</latinName><name>Lector</name><age>5</age></animal></animals>");
}
- private void internalAssert(Object toBeMarshalled, String expected) throws Exception {
+ private void internalAssert(JAXBGenerator<?> generator, String expected) throws Exception {
Pipeline<SAXPipelineComponent> pipeline = new NonCachingPipeline<SAXPipelineComponent>();
- pipeline.addComponent(new JAXBGenerator(toBeMarshalled));
+ pipeline.addComponent(generator);
pipeline.addComponent(new XMLSerializer());
ByteArrayOutputStream baos = new ByteArrayOutputStream();