practicalxml-commits Mailing List for Practical XML (Page 9)
Brought to you by:
kdgregory
You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(6) |
Nov
(4) |
Dec
(35) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
(5) |
Feb
|
Mar
|
Apr
(7) |
May
|
Jun
|
Jul
(12) |
Aug
(24) |
Sep
(39) |
Oct
(16) |
Nov
(4) |
Dec
(7) |
| 2010 |
Jan
(10) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(4) |
Dec
(3) |
| 2011 |
Jan
(1) |
Feb
|
Mar
(1) |
Apr
(1) |
May
(3) |
Jun
|
Jul
|
Aug
(1) |
Sep
(10) |
Oct
(1) |
Nov
(1) |
Dec
(7) |
| 2012 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
(9) |
Jun
|
Jul
(5) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(16) |
Jul
|
Aug
(6) |
Sep
(10) |
Oct
|
Nov
(2) |
Dec
|
| 2014 |
Jan
(5) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
| 2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(5) |
| 2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-17 17:13:45
|
Revision: 109
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=109&view=rev
Author: kdgregory
Date: 2009-08-17 17:13:36 +0000 (Mon, 17 Aug 2009)
Log Message:
-----------
implement XML->Bean conversions
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java
Added Paths:
-----------
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java
Removed Paths:
-------------
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -32,6 +32,21 @@
*/
public class ConversionHelper
{
+ private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS
+ = new HashMap<String,Class<?>>();
+ static
+ {
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:string", String.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:boolean", Boolean.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:byte", Byte.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:short", Short.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:int", Integer.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:long", Long.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class);
+ XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class);
+ }
+
+
// this is not static because the helpers are inner classes
private Map<Class<?>,ConversionHandler<?>> _helpers
= new HashMap<Class<?>,ConversionHandler<?>>();
@@ -48,6 +63,14 @@
_helpers.put(BigInteger.class, new BigIntegerConversionHandler());
_helpers.put(BigDecimal.class, new BigDecimalConversionHandler());
_helpers.put(Date.class, new DateConversionHandler());
+
+ _helpers.put(Boolean.TYPE, new BooleanConversionHandler());
+ _helpers.put(Byte.TYPE, new ByteConversionHandler());
+ _helpers.put(Short.TYPE, new ShortConversionHandler());
+ _helpers.put(Integer.TYPE, new IntegerConversionHandler());
+ _helpers.put(Long.TYPE, new LongConversionHandler());
+ _helpers.put(Float.TYPE, new FloatConversionHandler());
+ _helpers.put(Double.TYPE, new DoubleConversionHandler());
}
private boolean _useXsdFormatting;
@@ -85,6 +108,16 @@
ConversionHandler<?> helper = _helpers.get(klass);
return (helper == null) ? null : helper.getXsiType();
}
+
+
+ /**
+ * Returns the Java type that best matches the given Schema type name,
+ * <code>null</code> if we do not have an appropriate mapping.
+ */
+ public Class<?> getJavaType(String xsdTypename)
+ {
+ return XSD_TYPE_TO_JAVA_CLASS.get(xsdTypename);
+ }
/**
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -14,22 +14,434 @@
package net.sf.practicalxml.converter.xml2bean;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.xml.XMLConstants;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.converter.ConversionException;
+import net.sf.practicalxml.converter.ConversionHelper;
+import net.sf.practicalxml.internal.StringUtils;
+
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
/**
- * Driver class for converting an XML DOM into a Java bean, using a {@link
- * Xml2BeanHandler} to manage data conversion.
+ * Driver class for converting an XML DOM into a Java bean. Normal usage is
+ * to create a single instance of this class with desired options, then use
+ * it for multiple conversions. This class is thread-safe.
+ * <p>
+ * This class assumes that the source XML will be in the form produced by
+ * {@link Bean2XmlDriver}: each element either contains child elements, or
+ * a text node containing the element's value. However, conversion is
+ * driven by the parameters passed to {@link #convert}, not by the content
+ * of the XML document; this can lead to some unexpected behavior:
+ * <ul>
+ * <li> Bean classes are introspected, and recursively processed base on
+ * the property descriptors. If the bean has multiple setter methods
+ * for a property, the method selected is arbitrarily chosen by the
+ * JavaBeans introspector. You can pass an option that looks for a
+ * setters using <code>String</code>, but this is not recommended
+ * from a performance perspective.
+ * <li> JDK collection types do not carry type information, so the only
+ * way to properly convert them is using an <code>xsi:type</code>
+ * attribute on the child elements. If this attribute is missing
+ * or cannot be interpreted, the element will be processed as if
+ * it is a <code>String</code>.
+ * <li> The converter will to pick an appropriate implementation class
+ * if given one of the JDK collections interfaces: <code>
+ * ArrayList</code> for <code>List</code> or <code>Collection</code>,
+ * <code>TreeSet</code> for <code>SortedSet</code>, <code>HashSet</code>
+ * for any other <code>Set</code>, and likewise <code>TreeMap</code> and
+ * <code>HashMap</code> for <code>SortedMap</code> and <code>Map</code>.
+ * </ul>
*/
public class Xml2BeanDriver
{
+ private EnumSet<Xml2BeanOptions> _options;
+ private ConversionHelper _helper;
+ private Map<Class<?>,Map<String,Method>> _introspectedClasses;
+
+
+ public Xml2BeanDriver(Xml2BeanOptions... options)
+ {
+ _options = EnumSet.noneOf(Xml2BeanOptions.class);
+ for (Xml2BeanOptions option : options)
+ _options.add(option);
+
+ _helper = new ConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT));
+ _introspectedClasses = new HashMap<Class<?>,Map<String,Method>>();
+ }
+
+
+//----------------------------------------------------------------------------
+// Public Methods
+//----------------------------------------------------------------------------
+
/**
- * Fills a bean-style object from an XML element. For each child of the
- * passed element, tries to find a property with the same name, invokes
- * the appropriate conversion handler method, and sets the property from
- * the result.
+ * Attempts to convert the passed DOM subtree into an object of the
+ * specified class.
*/
- public void dispatch(Element elem, Object bean)
+ public <T> T convert(Element elem, Class<T> klass)
{
+ return klass.cast(convertWithoutCast(elem, klass));
}
+
+
+//----------------------------------------------------------------------------
+// Internal Conversion Methods
+//----------------------------------------------------------------------------
+
+
+
+ /**
+ * Attempts to convert the passed DOM subtree into an object of the
+ * specified class. Note that this version does not use generics,
+ * and does not try to cast the result, whereas the public version
+ * does. Internally, we want to treat <code>Integer.TYPE</code> the
+ * same as <code>Integer.class</code>, and the cast prevents that.
+ */
+ public Object convertWithoutCast(Element elem, Class<?> klass)
+ {
+ validateXsiType(elem, klass);
+ if (isAllowableNull(elem))
+ return null;
+
+ Object obj = tryConvertAsPrimitive(elem, klass);
+ if (obj == null)
+ obj = tryConvertAsArray(elem, klass);
+ if (obj == null)
+ obj = tryConvertAsSimpleCollection(elem, klass);
+ if (obj == null)
+ obj = tryConvertAsMap(elem, klass);
+ if (obj == null)
+ obj = tryConvertAsBean(elem, klass);
+ return obj;
+ }
+
+
+ private boolean isAllowableNull(Element elem)
+ {
+ String text = getText(elem);
+ if ((text != null) || hasElementChildren(elem))
+ return false;
+
+ if (_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL))
+ {
+ String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
+ if (!attr.equals("true"))
+ throw new ConversionException(
+ "missing xsi:nil: " + DomUtil.getAbsolutePath(elem));
+ }
+
+ return true;
+ }
+
+
+ private Object tryConvertAsPrimitive(Element elem, Class<?> klass)
+ {
+ if (_helper.getXsdType(klass) == null)
+ return null;
+
+ if (hasElementChildren(elem))
+ throw new ConversionException(
+ "expecting primitive; has children: " + DomUtil.getAbsolutePath(elem));
+
+ return _helper.parse(getText(elem), klass);
+ }
+
+
+ private Object tryConvertAsArray(Element elem, Class<?> klass)
+ {
+ Class<?> childKlass = klass.getComponentType();
+ if (childKlass == null)
+ return null;
+
+ List<Element> children = DomUtil.getChildren(elem);
+ Object result = Array.newInstance(childKlass, children.size());
+ int idx = 0;
+ for (Element child : children)
+ {
+ Array.set(result, idx++, convertWithoutCast(child, childKlass));
+ }
+ return result;
+ }
+
+
+ private Object tryConvertAsSimpleCollection(Element elem, Class<?> klass)
+ {
+ Collection<Object> result = instantiateCollection(klass);
+ if (result == null)
+ return null;
+
+ List<Element> children = DomUtil.getChildren(elem);
+ for (Element child : children)
+ {
+ Class<?> childClass = getClassFromXsiType(child);
+ if (childClass == null)
+ childClass = String.class;
+ result.add(convertWithoutCast(child, childClass));
+ }
+ return result;
+ }
+
+
+ private Object tryConvertAsMap(Element elem, Class<?> klass)
+ {
+ Map<Object,Object> result = instantiateMap(klass);
+ if (result == null)
+ return null;
+
+ List<Element> children = DomUtil.getChildren(elem);
+ for (Element child : children)
+ {
+ String key = child.getAttribute("key");
+ if (StringUtils.isEmpty(key))
+ key = DomUtil.getLocalName(child);
+ Class<?> childClass = getClassFromXsiType(child);
+ if (childClass == null)
+ childClass = String.class;
+ result.put(key, convertWithoutCast(child, childClass));
+ }
+ return result;
+ }
+
+
+ private Object tryConvertAsBean(Element elem, Class<?> klass)
+ {
+ Object bean = instantiateBean(elem, klass);
+
+ List<Element> children = DomUtil.getChildren(elem);
+ for (Element child : children)
+ {
+ Method setter = getSetterMethod(klass, child);
+ if (setter == null)
+ continue;
+
+ Class<?> childClass = setter.getParameterTypes()[0];
+ Object childValue = convertWithoutCast(child, childClass);
+ invokeSetter(elem, bean, setter, childValue);
+ }
+ return bean;
+ }
+
+
+//----------------------------------------------------------------------------
+// Other Internals
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the text content of an element, applying appropriate options.
+ */
+ private String getText(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ if (StringUtils.isBlank(text)
+ && _options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL))
+ text = null;
+ return text;
+ }
+
+
+ /**
+ * Returns the <code>xsi:type</code> attribute value, <code>null</code> if
+ * it's not set.
+ */
+ private String getXsiType(Element elem)
+ {
+ String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
+ return StringUtils.isEmpty(xsiType)
+ ? null
+ : xsiType;
+ }
+
+
+ /**
+ * Examines an element's <code>xsi:type</code> attribute, if any, and
+ * returns the Java class corresponding to it. Used when converting
+ * collection types, which don't have type information that can be
+ * introspected, and also to validate non-XSD types.
+ */
+ private Class<?> getClassFromXsiType(Element elem)
+ {
+ String xsiType = getXsiType(elem);
+ if (xsiType == null)
+ return null;
+
+ if (xsiType.startsWith("java:"))
+ {
+ String javaType = xsiType.substring(5);
+ try
+ {
+ return Class.forName(javaType);
+ }
+ catch (ClassNotFoundException ee)
+ {
+ throw new ConversionException(
+ "invalid Java type specification (" + javaType + "): "
+ + DomUtil.getAbsolutePath(elem),
+ ee);
+ }
+ }
+ return _helper.getJavaType(xsiType);
+ }
+
+
+ private void validateXsiType(Element elem, Class<?> klass)
+ {
+ if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE))
+ return;
+
+ String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
+ if (StringUtils.isEmpty(xsiType))
+ throw new ConversionException(
+ "missing xsi:type: " + DomUtil.getAbsolutePath(elem));
+
+ if (xsiType.equals(_helper.getXsdType(klass)))
+ return;
+
+ Class<?> xsiKlass = getClassFromXsiType(elem);
+ if (klass.isAssignableFrom(xsiKlass))
+ return;
+
+ throw new ConversionException(
+ "invalid xsi:type (\"" + xsiType + "\" for " + klass.getName() + "): "
+ + DomUtil.getAbsolutePath(elem));
+ }
+
+
+ private boolean hasElementChildren(Element elem)
+ {
+ Node child = elem.getFirstChild();
+ while (child != null)
+ {
+ if (child instanceof Element)
+ return true;
+ child = child.getNextSibling();
+ }
+ return false;
+ }
+
+
+ private Method getSetterMethod(Class<?> beanKlass, Element child)
+ {
+ Map<String,Method> methodMap = _introspectedClasses.get(beanKlass);
+ if (methodMap == null)
+ methodMap = introspect(beanKlass);
+
+ Method setter = methodMap.get(DomUtil.getLocalName(child));
+ if ((setter == null) && !_options.contains(Xml2BeanOptions.IGNORE_MISSING_PROPERTIES))
+ {
+ throw new ConversionException(
+ "can't find property setter in " + beanKlass.getName() + ": "
+ + DomUtil.getAbsolutePath(child));
+ }
+
+ return setter;
+ }
+
+
+ private Map<String,Method> introspect(Class<?> klass)
+ {
+ Map<String,Method> methodMap = new HashMap<String,Method>();
+ try
+ {
+ BeanInfo info = Introspector.getBeanInfo(klass, Object.class);
+ for (PropertyDescriptor propDesc : info.getPropertyDescriptors())
+ {
+ Method setter = propDesc.getWriteMethod();
+ if (setter != null)
+ methodMap.put(propDesc.getName(), setter);
+ }
+ }
+ catch (IntrospectionException e)
+ {
+ throw new ConversionException("unable to introspect", e);
+ }
+
+ _introspectedClasses.put(klass, methodMap);
+ return methodMap;
+ }
+
+
+ /**
+ * Attempts to create a <code>Collection</code> instance appropriate for
+ * the passed class, returns <code>null</code> if unable.
+ */
+ private Collection<Object> instantiateCollection(Class<?> klass)
+ {
+ if (SortedSet.class.isAssignableFrom(klass))
+ return new TreeSet<Object>();
+ else if (Set.class.isAssignableFrom(klass))
+ return new HashSet<Object>();
+ else if (List.class.isAssignableFrom(klass))
+ return new ArrayList<Object>();
+ else if (Collection.class.isAssignableFrom(klass))
+ return new ArrayList<Object>();
+ else
+ return null;
+ }
+
+
+ /**
+ * Attempts to create a <code>Map</code> instance appropriate for the
+ * passed class, returns <code>null</code> if unable.
+ */
+ private Map<Object,Object> instantiateMap(Class<?> klass)
+ {
+ if (SortedMap.class.isAssignableFrom(klass))
+ return new TreeMap<Object,Object>();
+ else if (Map.class.isAssignableFrom(klass))
+ return new HashMap<Object,Object>();
+ else
+ return null;
+ }
+
+
+ private Object instantiateBean(Element elem, Class<?> klass)
+ {
+ try
+ {
+ return klass.newInstance();
+ }
+ catch (Exception ee)
+ {
+ throw new ConversionException(
+ "unable to instantiate bean: " + DomUtil.getAbsolutePath(elem),
+ ee);
+ }
+ }
+
+
+ private void invokeSetter(Element elem, Object bean, Method setter, Object value)
+ {
+ try
+ {
+ setter.invoke(bean, value);
+ }
+ catch (Exception ee)
+ {
+ throw new ConversionException(
+ "unable to set property: " + DomUtil.getAbsolutePath(elem),
+ ee);
+ }
+ }
}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -30,25 +30,22 @@
/**
- * If present, the converter ignores elements that don't correspond to
- * settable properties of the bean.
+ * Expect data (in particular, dates) to be formatted per XML Schema spec.
*/
- IGNORE_MISSING_PROPERTIES,
+ EXPECT_XSD_FORMAT,
/**
- * If present, the converter will ignore any objects that cannot be
- * converted (many of the JDK-provided classes fall into this category,
- * because they're not bean-structured).
+ * If present, the converter ignores elements that don't correspond to
+ * settable properties of the bean.
*/
- IGNORE_UNCONVERTIBLE_OBJECTS,
+ IGNORE_MISSING_PROPERTIES,
/**
- * If present, the converter will use a setter method taking a String, in
- * preference to any other type. Default behavior is to pick the method
- * with the most restrictive type (and considering numeric types as more
- * restrictive than <code>String</code>).
+ * If present, the converter will look for a setter method taking a
+ * <code>String</code>, in preference to a non-string method returned
+ * from the bean introspector.
*/
PREFER_STRING_SETTER,
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -81,7 +81,7 @@
new PrimitiveValue(Double.valueOf(1234567890.5), "xsd:decimal", "1234567890.5"),
new PrimitiveValue(new BigInteger("123456789012345"), "xsd:decimal", "123456789012345"),
new PrimitiveValue(new BigDecimal("123456789012345.123456789012345"), "xsd:decimal", "123456789012345.123456789012345"),
- new PrimitiveValue(new Date(1247551703704L), "xsd:dateTime", "2009-07-14T06:08:23")
+ new PrimitiveValue(new Date(1247551703000L), "xsd:dateTime", "2009-07-14T06:08:23")
};
@@ -170,23 +170,23 @@
assertXsiType(message, elem, expectedType);
assertXsiNil(message, elem, isNil);
}
-
+
protected void assertNameTypeValue(
- Element elem,
+ Element elem,
String expectedName, String expectedType, String expectedValue)
{
assertNameTypeValue("", elem, expectedName, expectedType, expectedValue);
}
-
-
+
+
protected void assertNameTypeValue(
- String message, Element elem,
+ String message, Element elem,
String expectedName, String expectedType, String expectedValue)
{
if (message.length() > 0)
message += " ";
-
+
assertName(message + "name", elem, expectedName);
assertXsiType(message + "xsi:type", elem, expectedType);
assertValue(message + "value", elem, expectedValue);
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -54,6 +54,20 @@
// Test Cases
//----------------------------------------------------------------------------
+ public void testClassToXsdType() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:string", helper.getXsdType(String.class));
+ assertEquals("xsd:string", helper.getXsdType(Character.class));
+ assertEquals(String.class, helper.getJavaType("xsd:string"));
+
+ assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
+ assertEquals(Boolean.class, helper.getJavaType("xsd:boolean"));
+
+ }
+
+
public void testUnknownClass() throws Exception
{
ConversionHelper helper = new ConversionHelper();
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -0,0 +1,708 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+import javax.xml.XMLConstants;
+import org.w3c.dom.Element;
+
+import net.sf.practicalxml.converter.xml2bean.Xml2BeanDriver;
+import net.sf.practicalxml.converter.xml2bean.Xml2BeanOptions;
+
+
+import static net.sf.practicalxml.builder.XmlBuilder.*;
+
+
+public class TestXml2BeanDriver
+extends AbstractBeanConverterTestCase
+{
+ public TestXml2BeanDriver(String name)
+ {
+ super(name);
+ }
+
+
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ private static Element createTestData(net.sf.practicalxml.builder.Node... childNodes)
+ {
+ return element("root", childNodes)
+ .toDOM().getDocumentElement();
+ }
+
+
+ private static net.sf.practicalxml.builder.Node xsiType(String typeName)
+ {
+ return attribute(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI,
+ "type",
+ typeName);
+ }
+
+
+ private static net.sf.practicalxml.builder.Node xsiNil(boolean isNil)
+ {
+ return attribute(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI,
+ "nil",
+ isNil ? "true" : "false");
+ }
+
+
+ private static void assertConversionError(
+ String message, Xml2BeanDriver driver, Element elem, Class<?> klass)
+ {
+ try
+ {
+ driver.convert(elem, klass);
+ fail(message);
+ }
+ catch (ConversionException ee)
+ { /* success */ }
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Classes
+//----------------------------------------------------------------------------
+
+ public static class ReadOnlyBean
+ {
+ private String _sval;
+ public String getSval() { return _sval; }
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ public void testConvertPrimitivesDefault() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ for (PrimitiveValue value : PRIMITIVE_VALUES)
+ {
+ Element src = createTestData(text(value.getDefaultText()));
+ Object dst = driver.convert(src, value.getKlass());
+ assertEquals(value.getKlass().getName(), value.getValue(), dst);
+ }
+ }
+
+
+ public void testConvertPrimitivesXsdFormat() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.EXPECT_XSD_FORMAT);
+
+ for (PrimitiveValue value : PRIMITIVE_VALUES)
+ {
+ Element src = createTestData(text(value.getXsdText()));
+ Object dst = driver.convert(src, value.getKlass());
+ assertEquals(value.getKlass().getName(), value.getValue(), dst);
+ }
+ }
+
+
+ public void testConvertPrimitivesRequireXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element valid = createTestData(text("foo"), xsiType("xsd:string"));
+ Object dst = driver.convert(valid, String.class);
+ assertEquals("foo", dst);
+
+ Element invalid = createTestData(text("foo"));
+ assertConversionError("converted element missing xsi:type",
+ driver, invalid, String.class);
+ }
+
+
+ public void testConvertPrimitiveWithWrongXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element invalid = createTestData(text("foo"), xsiType("xsd:int"));
+ assertConversionError("converted element with incorrect xsi:type",
+ driver, invalid, String.class);
+ }
+
+
+ public void testConvertPrimitiveWithChildElement() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element invalid = createTestData(text("foo"), element("bar"));
+ assertConversionError("converted primitive with element content",
+ driver, invalid, String.class);
+ }
+
+
+ public void testConvertNullDefault() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element src = createTestData();
+ assertNull(driver.convert(src, String.class));
+ }
+
+
+ public void testConvertNullRequireXsiNull() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_NIL);
+
+ Element valid = createTestData(xsiNil(true));
+ assertNull(driver.convert(valid, String.class));
+
+ Element invalid = createTestData();
+ assertConversionError("able to convert null data with REQUIRE_XSI_NIL set",
+ driver, invalid, String.class);
+ }
+
+
+ public void testConvertEmptyStringDefault() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ String str = " \n \t ";
+ Element src = createTestData(text(str));
+ Object dst = driver.convert(src, String.class);
+ assertEquals(str, dst);
+ }
+
+
+ public void testConvertEmptyStringToNull() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.CONVERT_BLANK_AS_NULL);
+
+ Element src = createTestData(text(" \n\t "));
+ assertNull(driver.convert(src, String.class));
+ }
+
+
+ public void testConvertEmptyStringToNullAndRequireXsiNull() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(
+ Xml2BeanOptions.CONVERT_BLANK_AS_NULL,
+ Xml2BeanOptions.REQUIRE_XSI_NIL);
+
+ Element valid = createTestData(text(" \t "), xsiNil(true));
+ assertNull(driver.convert(valid, String.class));
+
+ Element invalid = createTestData(text(" \t "));
+ assertConversionError("able to convert blank data with CONVERT_BLANK_AS_NULL and REQUIRE_XSI_NIL set",
+ driver, invalid, String.class);
+ }
+
+
+ public void testConvertPrimitiveArray() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // note that the child element names shouldn't matter ... doesn't
+ // have to be the "data" of Bean2Xml
+ Element data = createTestData(
+ element("foo", text("12")),
+ element("bar", text("78")),
+ element("baz", text("-17")));
+
+ int[] result = driver.convert(data, int[].class);
+ assertEquals(3, result.length);
+ assertEquals(12, result[0]);
+ assertEquals(78, result[1]);
+ assertEquals(-17, result[2]);
+ }
+
+
+ public void testConvertPrimitiveArrayRequireXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element valid = createTestData(
+ xsiType("java:" + int[].class.getName()),
+ element("foo", text("12"), xsiType("xsd:int")));
+
+ int[] result = driver.convert(valid, int[].class);
+ assertEquals(1, result.length);
+ assertEquals(12, result[0]);
+
+ Element invalid = createTestData(
+ element("foo", text("12"), xsiType("xsd:int")));
+
+ assertConversionError("able to convert with REQUIRE_XSI_TYPE set",
+ driver, invalid, int[].class);
+ }
+
+
+ public void testConvertListAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // note that the child element names shouldn't matter ... doesn't
+ // have to be the "data" of Bean2Xml
+ Element data = createTestData(
+ element("a", text("foo")),
+ element("b", text("bar")),
+ element("b", text("baz")),
+ element("c", text("bar")));
+
+ List<?> result = driver.convert(data, List.class);
+ assertEquals(4, result.size());
+
+ Iterator<?> itx = result.iterator();
+ assertEquals("foo", itx.next());
+ assertEquals("bar", itx.next());
+ assertEquals("baz", itx.next());
+ assertEquals("bar", itx.next());
+ }
+
+
+ public void testConvertListWithXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo"), xsiType("xsd:string")),
+ element("b", text("123"), xsiType("xsd:int")),
+ element("b", text("123.0"), xsiType("xsd:decimal")),
+ element("c", text("456"), xsiType("xsd:string")));
+
+ List<?> result = driver.convert(data, List.class);
+ assertEquals(4, result.size());
+
+ Iterator<?> itx = result.iterator();
+ assertEquals("foo", itx.next());
+ assertEquals(Integer.valueOf(123), itx.next());
+ assertEquals(new BigDecimal("123.0"), itx.next());
+ assertEquals("456", itx.next());
+ }
+
+ public void testConvertListWithJavaType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("1234"),
+ xsiType("java:java.math.BigInteger")));
+
+ List<?> result = driver.convert(data, List.class);
+ assertEquals(1, result.size());
+ assertEquals(new BigInteger("1234"), result.iterator().next());
+
+ }
+
+
+ public void testConvertListWithBogusJavaType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo"), xsiType("java:foo")));
+
+ assertConversionError("converted unknown type",
+ driver, data, List.class);
+ }
+
+
+ public void testConvertSortedSetAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo")),
+ element("b", text("bar")),
+ element("b", text("baz")),
+ element("c", text("bar")));
+
+ SortedSet<?> result = driver.convert(data, SortedSet.class);
+ assertEquals(3, result.size());
+
+ Iterator<?> itx = result.iterator();
+ assertEquals("bar", itx.next());
+ assertEquals("baz", itx.next());
+ assertEquals("foo", itx.next());
+ }
+
+
+ public void testConvertSetAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo")),
+ element("b", text("bar")),
+ element("b", text("baz")),
+ element("c", text("bar")));
+
+ Set<?> result = driver.convert(data, Set.class);
+ assertEquals(3, result.size());
+ assertTrue(result.contains("bar"));
+ assertTrue(result.contains("baz"));
+ assertTrue(result.contains("foo"));
+ }
+
+
+ public void testConvertCollectionAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo")),
+ element("b", text("bar")),
+ element("b", text("baz")),
+ element("c", text("bar")));
+
+ Collection<?> result = driver.convert(data, Collection.class);
+ assertEquals(4, result.size());
+
+ Iterator<?> itx = result.iterator();
+ assertEquals("foo", itx.next());
+ assertEquals("bar", itx.next());
+ assertEquals("baz", itx.next());
+ assertEquals("bar", itx.next());
+ }
+
+
+ // this handles the case where we're processing a bean that uses interfaces
+ // but the source document has a concrete type
+ public void testConvertCollectionRequireXsiTypeWithConcreteType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element data = createTestData(
+ xsiType("java:java.util.ArrayList"),
+ element("a", text("foo"), xsiType("xsd:string")),
+ element("b", text("123"), xsiType("xsd:int")));
+
+ Collection<?> result = driver.convert(data, Collection.class);
+ assertEquals(2, result.size());
+
+ Iterator<?> itx = result.iterator();
+ assertEquals("foo", itx.next());
+ assertEquals(Integer.valueOf(123), itx.next());
+ }
+
+
+
+ public void testConvertMapDefaultKeyAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // we want distinct child names -- and overlapping ones -- because
+ // the converter should ignore them -- also note duplicate key
+ Element data = createTestData(
+ element("a", text("foo"), attribute("key", "argle")),
+ element("b", text("bar"), attribute("key", "bargle")),
+ element("b", text("baz"), attribute("key", "argle")),
+ element("c", text("bar"), attribute("key", "wargle")));
+
+ Map<?,?> result = driver.convert(data, Map.class);
+ assertEquals(3, result.size());
+ assertEquals("baz", result.get("argle"));
+ assertEquals("bar", result.get("bargle"));
+ assertEquals("bar", result.get("wargle"));
+ }
+
+
+ public void testConvertSortedMapDefaultKeyAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("a", text("foo"), attribute("key", "argle")),
+ element("b", text("bar"), attribute("key", "bargle")),
+ element("c", text("arb"), attribute("key", "wargle")),
+ element("b", text("baz"), attribute("key", "argle")));
+
+ SortedMap<?,?> result = driver.convert(data, SortedMap.class);
+ assertEquals(3, result.size());
+
+ Iterator<?> itx = result.keySet().iterator();
+ assertEquals("argle", itx.next());
+ assertEquals("bargle", itx.next());
+ assertEquals("wargle", itx.next());
+
+ assertEquals("baz", result.get("argle"));
+ assertEquals("bar", result.get("bargle"));
+ assertEquals("arb", result.get("wargle"));
+ }
+
+
+ public void testConvertMapNameAsKeyAssumingString() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // no attributes this time, but note the duplicate element name
+ Element data = createTestData(
+ element("a", text("foo")),
+ element("b", text("bar")),
+ element("b", text("baz")),
+ element("c", text("bar")));
+
+ Map<?,?> result = driver.convert(data, Map.class);
+ assertEquals(3, result.size());
+ assertEquals("foo", result.get("a"));
+ assertEquals("baz", result.get("b"));
+ assertEquals("bar", result.get("c"));
+ }
+
+
+ public void testConvertMapNameAsKeyUsingXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // this time we have unique element names
+ Element data = createTestData(
+ element("a", text("foo"), xsiType("xsd:string")),
+ element("b", text("123"), xsiType("xsd:int")),
+ element("c", text("123.0"), xsiType("xsd:decimal")),
+ element("d", text("456"), xsiType("xsd:string")));
+
+ Map<?,?> result = driver.convert(data, Map.class);
+ assertEquals(4, result.size());
+ assertEquals("foo", result.get("a"));
+ assertEquals(Integer.valueOf(123), result.get("b"));
+ assertEquals(new BigDecimal("123.0"), result.get("c"));
+ assertEquals("456", result.get("d"));
+ }
+
+
+ public void testConvertMapNameAsKeyUsingJavaType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ // this time we have unique element names
+ Element data = createTestData(
+ element("b", text("123"), xsiType("java:java.lang.Integer")));
+
+ Map<?,?> result = driver.convert(data, Map.class);
+ assertEquals(1, result.size());
+ assertEquals(Integer.valueOf(123), result.get("b"));
+ }
+
+
+ public void testSimpleBeanDefault() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("sval", text("foo")),
+ element("ival", text("123")),
+ element("dval", text("123.456")),
+ element("bval", text("true")));
+
+ SimpleBean result = driver.convert(data, SimpleBean.class);
+ assertEquals("foo", result.getSval());
+ assertEquals(123, result.getIval());
+ assertEquals(new BigDecimal("123.456"), result.getDval());
+ assertEquals(true, result.isBval());
+ }
+
+
+ public void testSimpleBeanWithMissingValues() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("sval", text("foo")),
+ element("ival", text("123")));
+
+ SimpleBean result = driver.convert(data, SimpleBean.class);
+ assertEquals("foo", result.getSval());
+ assertEquals(123, result.getIval());
+ assertNull(result.getDval());
+ assertEquals(false, result.isBval());
+ }
+
+
+ public void testSimpleBeanRequireXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element valid = createTestData(
+ xsiType("java:" + SimpleBean.class.getName()),
+ element("sval", text("foo"), xsiType("xsd:string")),
+ element("ival", text("123"), xsiType("xsd:int")),
+ element("dval", text("123.456"),xsiType("xsd:decimal")),
+ element("bval", text("true"), xsiType("xsd:boolean")));
+
+ SimpleBean result = driver.convert(valid, SimpleBean.class);
+ assertEquals("foo", result.getSval());
+ assertEquals(123, result.getIval());
+ assertEquals(new BigDecimal("123.456"), result.getDval());
+ assertEquals(true, result.isBval());
+
+ Element invalid1 = createTestData(
+ element("sval", text("foo"), xsiType("xsd:string")),
+ element("ival", text("123"), xsiType("xsd:int")),
+ element("dval", text("123.456"),xsiType("xsd:decimal")),
+ element("bval", text("true"), xsiType("xsd:boolean")));
+ assertConversionError("didn't throw when missing xsi:type on top level",
+ driver, invalid1, SimpleBean.class);
+
+ Element invalid2 = createTestData(
+ xsiType("java:" + SimpleBean.class.getName()),
+ element("sval", text("foo")),
+ element("ival", text("123")),
+ element("dval", text("123.456")),
+ element("bval", text("true")));
+ assertConversionError("didn't throw when missing xsi:type on component level",
+ driver, invalid2, SimpleBean.class);
+ }
+
+
+ public void testSimpleBeanWithExtraValues() throws Exception
+ {
+ Element data = createTestData(
+ element("sval", text("foo")),
+ element("ival", text("123")),
+ element("zippy", text("pinhead")));
+
+ Xml2BeanDriver driver1 = new Xml2BeanDriver();
+
+ assertConversionError("converted bean when extra fields present in XML",
+ driver1, data, SimpleBean.class);
+
+ Xml2BeanDriver driver2 = new Xml2BeanDriver(Xml2BeanOptions.IGNORE_MISSING_PROPERTIES);
+
+ SimpleBean result = driver2.convert(data, SimpleBean.class);
+ assertEquals("foo", result.getSval());
+ assertEquals(123, result.getIval());
+ assertNull(result.getDval());
+ assertEquals(false, result.isBval());
+ }
+
+
+ public void testBeanArray() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("idx0",
+ element("sval", text("foo")),
+ element("ival", text("123")),
+ element("dval", text("123.456")),
+ element("bval", text("true"))),
+ element("idx1",
+ element("sval", text("bar")),
+ element("ival", text("456")),
+ element("dval", text("456.789")),
+ element("bval", text("false"))));
+
+ SimpleBean[] result = driver.convert(data, SimpleBean[].class);
+ assertEquals(2, result.length);
+
+ assertEquals("foo", result[0].getSval());
+ assertEquals(123, result[0].getIval());
+ assertEquals(new BigDecimal("123.456"), result[0].getDval());
+ assertEquals(true, result[0].isBval());
+
+ assertEquals("bar", result[1].getSval());
+ assertEquals(456, result[1].getIval());
+ assertEquals(new BigDecimal("456.789"), result[1].getDval());
+ assertEquals(false, result[1].isBval());
+ }
+
+
+ public void testConvertCompoundBean() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+
+ Element data = createTestData(
+ element("simple",
+ element("sval", text("foo")),
+ element("ival", text("123")),
+ element("dval", text("456")),
+ element("bval", text("true"))),
+ element("primArray",
+ element("idx1", text("1")),
+ element("idx2", text("2")),
+ element("idx3", text("3"))),
+ element("stringList",
+ element("idx1", text("foo")),
+ element("idx2", text("bar")),
+ element("idx3", text("baz"))));
+
+ CompoundBean result = driver.convert(data, CompoundBean.class);
+
+ assertEquals("foo", result.getSimple().getSval());
+ assertEquals(123, result.getSimple().getIval());
+ assertEquals(456, result.getSimple().getDval().intValue()); // laziness prevails
+ assertEquals(true, result.getSimple().isBval());
+ assertEquals(1, result.getPrimArray()[0]);
+ assertEquals(2, result.getPrimArray()[1]);
+ assertEquals(3, result.getPrimArray()[2]);
+ assertEquals("foo", result.getStringList().get(0));
+ assertEquals("bar", result.getStringList().get(1));
+ assertEquals("baz", result.getStringList().get(2));
+ }
+
+
+ public void testConvertCompoundBeanRequireXsiType() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE);
+
+ Element data = createTestData(
+ xsiType("java:" + CompoundBean.class.getName()),
+ element("simple",
+ xsiType("java:" + SimpleBean.class.getName()),
+ element("sval", text("foo"), xsiType("xsd:string")),
+ element("ival", text("123"), xsiType("xsd:int")),
+ element("dval", text("456"), xsiType("xsd:decimal")),
+ element("bval", text("true"), xsiType("xsd:boolean"))),
+ element("primArray",
+ xsiType("java:" + int[].class.getName()),
+ element("idx1", text("1"), xsiType("xsd:int")),
+ element("idx2", text("2"), xsiType("xsd:int")),
+ element("idx3", text("3"), xsiType("xsd:int"))),
+ element("stringList",
+ xsiType("java:" + List.class.getName()),
+ element("idx1", text("foo"), xsiType("xsd:string")),
+ element("idx2", text("bar"), xsiType("xsd:string")),
+ element("idx3", text("baz"), xsiType("xsd:string"))));
+
+ CompoundBean result = driver.convert(data, CompoundBean.class);
+
+ assertEquals("foo", result.getSimple().getSval());
+ assertEquals(123, result.getSimple().getIval());
+ assertEquals(456, result.getSimple().getDval().intValue());
+ assertEquals(true, result.getSimple().isBval());
+ assertEquals(1, result.getPrimArray()[0]);
+ assertEquals(2, result.getPrimArray()[1]);
+ assertEquals(3, result.getPrimArray()[2]);
+ assertEquals("foo", result.getStringList().get(0));
+ assertEquals("bar", result.getStringList().get(1));
+ assertEquals("baz", result.getStringList().get(2));
+ }
+
+
+ public void testReadOnlyBean() throws Exception
+ {
+ Xml2BeanDriver driver = new Xml2BeanDriver();
+ Element data = createTestData(
+ element("sval", text("foo")));
+
+ assertConversionError("converted bean without setter",
+ driver, data, ReadOnlyBean.class);
+ }
+}
Property changes on: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java
___________________________________________________________________
Added: svn:executable
+ *
Deleted: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java 2009-08-15 18:57:35 UTC (rev 108)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java 2009-08-17 17:13:36 UTC (rev 109)
@@ -1,409 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.xml.XMLConstants;
-import org.w3c.dom.Element;
-
-import net.sf.practicalxml.DomUtil;
-import net.sf.practicalxml.builder.XmlBuilder;
-import net.sf.practicalxml.converter.xml2bean.Xml2BeanHandler;
-import net.sf.practicalxml.converter.xml2bean.Xml2BeanOptions;
-
-
-public class TestXml2BeanHandler
-extends AbstractBeanConverterTestCase
-{
- public TestXml2BeanHandler(String name)
- {
- super(name);
- }
-
-
-//----------------------------------------------------------------------------
-// Support Code
-//----------------------------------------------------------------------------
-
- /**
- * Builds a DOM tree with a single element, containing the specified
- * text as a child of the root. We don't care about the element's name;
- * it's the text that's important.
- */
- private Element createElement(String data)
- {
- Element elem = XmlBuilder.element("data").toDOM().getDocumentElement();
- if (data != null)
- DomUtil.appendText(elem, data);
- return elem;
- }
-
-
- /**
- * Reflectively executes the named method, and asserts that it throws
- * a conversion exception. This method exists to keep clutter out of
- * the test methods.
- */
- private void assertConversionFailure(
- Xml2BeanHandler handler, String methodName,
- Element elem, String failureText)
- throws Exception
- {
- Method method = handler.getClass().getMethod(methodName, Element.class);
- try
- {
- method.invoke(handler, elem);
- fail(methodName + ": " + failureText);
- }
- catch (InvocationTargetException ee)
- {
- if (ee.getCause().getClass() != ConversionException.class)
- fail(methodName + "threw unexpected exception: " + ee.getCause());
- // otherwise, we're successful
- }
- }
-
-
-//----------------------------------------------------------------------------
-// Test Cases
-//----------------------------------------------------------------------------
-
- public void testConvertString() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("foo");
- assertEquals("foo", handler.convertString(data1));
-
- Element data2 = createElement("");
- assertEquals("", handler.convertString(data2));
- }
-
-
- public void testConvertCharacter() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("A");
- assertEquals(Character.valueOf('A'), handler.convertCharacter(data1));
-
- Element data2 = createElement("\uFB01");
- assertEquals(Character.valueOf('\uFB01'), handler.convertCharacter(data2));
-
- Element data3 = createElement("");
- assertEquals(Character.valueOf('\0'), handler.convertCharacter(data3));
-
- Element data4 = createElement("ix");
- assertConversionFailure(handler, "convertCharacter", data4, "converted invalid value");
- }
-
-
- public void testConvertBoolean() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("true");
- assertEquals(Boolean.TRUE, handler.convertBoolean(data1));
-
- Element data2 = createElement("1");
- assertEquals(Boolean.TRUE, handler.convertBoolean(data2));
-
- Element data3 = createElement("false");
- assertEquals(Boolean.FALSE, handler.convertBoolean(data3));
-
- Element data4 = createElement("0");
- assertEquals(Boolean.FALSE, handler.convertBoolean(data4));
-
- Element data5 = createElement("ix");
- assertConversionFailure(handler, "convertBoolean", data5, "converted invalid value");
-
- Element data6 = createElement("");
- assertConversionFailure(handler, "convertBoolean", data6, "converted empty value");
- }
-
-
- public void testConvertByte() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("123");
- assertEquals(Byte.valueOf((byte)123), handler.convertByte(data1));
-
- Element data2 = createElement("-123");
- assertEquals(Byte.valueOf((byte)-123), handler.convertByte(data2));
-
- Element data3 = createElement("ix");
- assertConversionFailure(handler, "convertByte", data3, "converted invalid value");
-
- Element data4 = createElement("1234567");
- assertConversionFailure(handler, "convertByte", data4, "converted too-large value");
-
- Element data5 = createElement("");
- assertConversionFailure(handler, "convertByte", data5, "converted empty value");
- }
-
-
- public void testConvertShort() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("12345");
- assertEquals(Short.valueOf((short)12345), handler.convertShort(data1));
-
- Element data2 = createElement("-12345");
- assertEquals(Short.valueOf((short)-12345), handler.convertShort(data2));
-
- Element data3 = createElement("ix");
- assertConversionFailure(handler, "convertShort", data3, "converted non-numeric value");
-
- Element data4 = createElement("1234567");
- assertConversionFailure(handler, "convertShort", data4, "converted too-large value");
-
- Element data5 = createElement("123.45");
- assertConversionFailure(handler, "convertShort", data5, "converted non-integer value");
-
- Element data6 = createElement("");
- assertConversionFailure(handler, "convertShort", data6, "converted empty value");
- }
-
-
- public void testConvertInteger() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("123456789");
- assertEquals(Integer.valueOf(123456789), handler.convertInteger(data1));
-
- Element data2 = createElement("-123456789");
- assertEquals(Integer.valueOf(-123456789), handler.convertInteger(data2));
-
- Element data3 = createElement("ix");
- assertConversionFailure(handler, "convertInteger", data3, "converted non-numeric value");
-
- Element data4 = createElement("123456789012345");
- assertConversionFailure(handler, "convertInteger", data4, "converted too-large value");
-
- Element data5 = createElement("123.45");
- assertConversionFailure(handler, "convertInteger", data5, "converted non-integer value");
-
- Element data6 = createElement("");
- assertConversionFailure(handler, "convertInteger", data6, "converted empty value");
- }
-
-
- public void testConvertLong() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data1 = createElement("1234567890123456");
- assertE...
[truncated message content] |
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-15 18:57:45
|
Revision: 108
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=108&view=rev
Author: kdgregory
Date: 2009-08-15 18:57:35 +0000 (Sat, 15 Aug 2009)
Log Message:
-----------
fixed bug caused by re-arranging code in ctor
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-15 18:13:24 UTC (rev 107)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-15 18:57:35 UTC (rev 108)
@@ -46,9 +46,9 @@
public Bean2XmlDriver(Bean2XmlOptions... options)
{
- _helper = new ConversionHelper(shouldUseXsdFormatting());
for (Bean2XmlOptions option : options)
_options.add(option);
+ _helper = new ConversionHelper(shouldUseXsdFormatting());
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-15 18:13:31
|
Revision: 107
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=107&view=rev
Author: kdgregory
Date: 2009-08-15 18:13:24 +0000 (Sat, 15 Aug 2009)
Log Message:
-----------
comment change, private var name change
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 20:20:09 UTC (rev 106)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-15 18:13:24 UTC (rev 107)
@@ -35,22 +35,20 @@
/**
- * Driver class for converting bean data to an XML representation. In normal
- * usage, an instance of this class is constructed with the desired conversion
- * options, then {@link #convert} is called with the compound object to be
- * converted. The driver may be reused for multiple conversions, and is
- * thread-safe.
+ * Driver class for converting a Java bean into an XML DOM. Normal usage is
+ * to create a single instance of this class with desired options, then use
+ * it for multiple conversions. This class is thread-safe.
*/
public class Bean2XmlDriver
{
+ private ConversionHelper _helper;
private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class);
- private ConversionHelper _primitiveHelper;
public Bean2XmlDriver(Bean2XmlOptions... options)
{
+ _helper = new ConversionHelper(shouldUseXsdFormatting());
for (Bean2XmlOptions option : options)
_options.add(option);
- _primitiveHelper = new ConversionHelper(shouldUseXsdFormatting());
}
@@ -158,10 +156,10 @@
if (obj != null)
klass = obj.getClass();
- String objType = _primitiveHelper.getXsdType(klass);
+ String objType = _helper.getXsdType(klass);
if ((obj == null) || (objType != null))
{
- appender.appendValue(name, objType, _primitiveHelper.stringify(obj));
+ appender.appendValue(name, objType, _helper.stringify(obj));
return true;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 20:20:14
|
Revision: 106
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=106&view=rev
Author: kdgregory
Date: 2009-08-14 20:20:09 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
attach dummy xsi:nil to root element to prevent repetitive namespace defs by serializer
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 20:05:39 UTC (rev 105)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 20:20:09 UTC (rev 106)
@@ -24,6 +24,8 @@
import java.util.EnumSet;
import java.util.Map;
+import javax.xml.XMLConstants;
+
import org.w3c.dom.Element;
import net.sf.practicalxml.DomUtil;
@@ -76,6 +78,7 @@
public Element convert(Object obj, String nsUri, String rootName)
{
Element root = DomUtil.newDocument(nsUri, rootName);
+ doXsiNamespaceHack(root);
convert(obj, "", new DirectAppender(root, _options));
return root;
}
@@ -123,6 +126,32 @@
}
+ /**
+ * Introduces the XML Schema Instance namespace into the DOM tree using a
+ * meaningless attribute. The Xerces serializer does not attempt to promote
+ * namespace definitions above the subtree in which they first appear, which
+ * means that the XSI definition could be repeated many times throughout the
+ * serialized tree, adding bulk to the serialized representation.
+ * <p>
+ * By putting "nil=false" at the root element, we will keep the serializer
+ * from inserting all these definitions. This has to happen <em>before</em>
+ * any actual conversion, in case some bozo passes <code>null</code> to
+ * the top-level conversion routine.
+ * <p>
+ * Note that we only do this if <code>xsi:nil</code> is enabled by itself.
+ * If <code>xsi:type</code> is enabled, the converter will attach that
+ * attribute to the root instead, thereby establishing the namespace context.
+ */
+ private void doXsiNamespaceHack(Element root)
+ {
+ if (_options.contains(Bean2XmlOptions.XSI_NIL)
+ && !_options.contains(Bean2XmlOptions.XSI_TYPE))
+ {
+ root.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "false");
+ }
+ }
+
+
private boolean tryToConvertAsPrimitiveOrNull(
Object obj, Class<?> klass, String name, Appender appender)
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 20:05:46
|
Revision: 105
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=105&view=rev
Author: kdgregory
Date: 2009-08-14 20:05:39 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
rename PrimitiveConversionHelper to ConversionHelper
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java
Removed Paths:
-------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java (from rev 99, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -0,0 +1,446 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.practicalxml.XmlUtil;
+
+
+/**
+ * Responsible for converting "primitive" types -- those with unambiguous
+ * string representations -- to/from such a representation.
+ */
+public class ConversionHelper
+{
+ // this is not static because the helpers are inner classes
+ private Map<Class<?>,ConversionHandler<?>> _helpers
+ = new HashMap<Class<?>,ConversionHandler<?>>();
+ {
+ _helpers.put(String.class, new StringConversionHandler());
+ _helpers.put(Character.class, new CharacterConversionHandler());
+ _helpers.put(Boolean.class, new BooleanConversionHandler());
+ _helpers.put(Byte.class, new ByteConversionHandler());
+ _helpers.put(Short.class, new ShortConversionHandler());
+ _helpers.put(Integer.class, new IntegerConversionHandler());
+ _helpers.put(Long.class, new LongConversionHandler());
+ _helpers.put(Float.class, new FloatConversionHandler());
+ _helpers.put(Double.class, new DoubleConversionHandler());
+ _helpers.put(BigInteger.class, new BigIntegerConversionHandler());
+ _helpers.put(BigDecimal.class, new BigDecimalConversionHandler());
+ _helpers.put(Date.class, new DateConversionHandler());
+ }
+
+ private boolean _useXsdFormatting;
+
+
+ /**
+ * Default constructor, which uses Java formatting.
+ */
+ public ConversionHelper()
+ {
+ // nothing to see here
+ }
+
+
+ /**
+ * Constructor that allows selection of Java or XSD formatting.
+ */
+ public ConversionHelper(boolean useXsdFormatting)
+ {
+ _useXsdFormatting = useXsdFormatting;
+ }
+
+
+//----------------------------------------------------------------------------
+// Public Methods
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the XSD type name to use for stringified objects of the
+ * specified class, <code>null</code> if this converter can't convert
+ * instances of the class.
+ */
+ public String getXsdType(Class<?> klass)
+ {
+ ConversionHandler<?> helper = _helpers.get(klass);
+ return (helper == null) ? null : helper.getXsiType();
+ }
+
+
+ /**
+ * Converts the passed object into its string representation, according
+ * to the options currently in effect. Passing <code>null</code> will
+ * return <code>null</code>. Throws {@link ConversionException} if
+ * unable to convert the passed object.
+ */
+ public String stringify(Object obj)
+ {
+ if (obj == null)
+ return null;
+
+ try
+ {
+ return getHelper(obj.getClass()).stringify(obj);
+ }
+ catch (Exception ee)
+ {
+ if (ee instanceof ConversionException)
+ throw (ConversionException)ee;
+ throw new ConversionException("unable to convert: " + obj, ee);
+ }
+ }
+
+
+ /**
+ * Parses the passed string into an object of the desired class. Passing
+ * <code>null</code> will return <code>null</code>, passing an empty
+ * string will typically throw a {@link ConversionException}.
+ */
+ public Object parse(String str, Class<?> klass)
+ {
+ if (str == null)
+ return null;
+
+ try
+ {
+ return getHelper(klass).parse(str);
+ }
+ catch (Exception ee)
+ {
+ if (ee instanceof ConversionException)
+ throw (ConversionException)ee;
+ throw new ConversionException("unable to parse: " + str, ee);
+ }
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the appropriate conversion helper or throws.
+ */
+ @SuppressWarnings(value="unchecked")
+ private ConversionHandler getHelper(Class<?> klass)
+ {
+ ConversionHandler<?> helper = _helpers.get(klass);
+ if (helper == null)
+ throw new ConversionException("unable to get helper: " + klass.getName());
+ return helper;
+ }
+
+
+ /**
+ * Each primitive class has its own conversion handler that is responsible
+ * for converting to/from a string representation. Handlers are guaranteed
+ * to receive non-null objects/strings.
+ * <p>
+ * This interface is parameterized so that the compiler will generate
+ * bridge methods for implementation classes. Elsewhere, we don't care
+ * about parameterization, so wildcard or drop it (see {@link #getHelper}).
+ * <p>
+ * Implementation classes are expected to be inner classes, so that they
+ * have access to configuration information (such as formatting rules).
+ * <p>
+ * Implementation classes are permitted to throw any exception; caller is
+ * expected to catch them and translate to a {@link ConversionException}.
+ */
+ private static interface ConversionHandler<T>
+ {
+ public String getXsiType();
+ public String stringify(T obj) throws Exception;
+ public T parse(String str) throws Exception;
+ }
+
+
+ private class StringConversionHandler
+ implements ConversionHandler<String>
+ {
+ public String getXsiType()
+ {
+ return "xsd:string";
+ }
+
+ public String stringify(String obj)
+ {
+ return String.valueOf(obj);
+ }
+
+ public String parse(String str)
+ {
+ return str;
+ }
+ }
+
+
+ private class CharacterConversionHandler
+ implements ConversionHandler<Character>
+ {
+ private final Character NUL = Character.valueOf('\0');
+
+ public String getXsiType()
+ {
+ return "xsd:string";
+ }
+
+ public String stringify(Character obj)
+ {
+ if (obj.equals(NUL))
+ return "";
+ return obj.toString();
+ }
+
+ public Character parse(String str)
+ {
+ if (str.length() == 0)
+ return NUL;
+ if (str.length() > 1)
+ throw new ConversionException(
+ "attempted to convert multi-character string: \"" + str + "\"");
+ return Character.valueOf(str.charAt(0));
+ }
+ }
+
+
+ private class BooleanConversionHandler
+ implements ConversionHandler<Boolean>
+ {
+ public String getXsiType()
+ {
+ return "xsd:boolean";
+ }
+
+ public String stringify(Boolean obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdBoolean(obj.booleanValue())
+ : obj.toString();
+ }
+
+ public Boolean parse(String str)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.parseXsdBoolean(str)
+ : Boolean.parseBoolean(str);
+ }
+ }
+
+
+ private class ByteConversionHandler
+ implements ConversionHandler<Byte>
+ {
+ public String getXsiType()
+ {
+ return "xsd:byte";
+ }
+
+ public String stringify(Byte obj)
+ {
+ return obj.toString();
+ }
+
+ public Byte parse(String str)
+ {
+ return Byte.valueOf(str.trim());
+ }
+ }
+
+
+ private class ShortConversionHandler
+ implements ConversionHandler<Short>
+ {
+ public String getXsiType()
+ {
+ return "xsd:short";
+ }
+
+ public String stringify(Short obj)
+ {
+ return obj.toString();
+ }
+
+ public Short parse(String str)
+ {
+ return Short.valueOf(str.trim());
+ }
+ }
+
+
+ private class IntegerConversionHandler
+ implements ConversionHandler<Integer>
+ {
+ public String getXsiType()
+ {
+ return "xsd:int";
+ }
+
+ public String stringify(Integer obj)
+ {
+ return obj.toString();
+ }
+
+ public Integer parse(String str)
+ {
+ return Integer.valueOf(str.trim());
+ }
+ }
+
+
+ private class LongConversionHandler
+ implements ConversionHandler<Long>
+ {
+ public String getXsiType()
+ {
+ return "xsd:long";
+ }
+
+ public String stringify(Long obj)
+ {
+ return obj.toString();
+ }
+
+ public Long parse(String str)
+ {
+ return Long.valueOf(str.trim());
+ }
+ }
+
+
+ private class FloatConversionHandler
+ implements ConversionHandler<Float>
+ {
+ public String getXsiType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(Float obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDecimal(obj)
+ : obj.toString();
+ }
+
+ public Float parse(String str)
+ {
+ return Float.valueOf(str.trim());
+ }
+ }
+
+
+ private class DoubleConversionHandler
+ implements ConversionHandler<Double>
+ {
+ public String getXsiType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(Double obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDecimal(obj)
+ : obj.toString();
+ }
+
+ public Double parse(String str)
+ {
+ return Double.valueOf(str.trim());
+ }
+ }
+
+
+ private class BigIntegerConversionHandler
+ implements ConversionHandler<BigInteger>
+ {
+ public String getXsiType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(BigInteger obj)
+ {
+ return obj.toString();
+ }
+
+ public BigInteger parse(String str)
+ {
+ return new BigInteger(str.trim());
+ }
+ }
+
+
+ private class BigDecimalConversionHandler
+ implements ConversionHandler<BigDecimal>
+ {
+ public String getXsiType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(BigDecimal obj)
+ {
+ return obj.toString();
+ }
+
+ public BigDecimal parse(String str)
+ {
+ return new BigDecimal(str.trim());
+ }
+ }
+
+
+ private class DateConversionHandler
+ implements ConversionHandler<Date>
+ {
+ // format as specified by Date.toString() JavaDoc
+ private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
+
+ public String getXsiType()
+ {
+ return "xsd:dateTime";
+ }
+
+ public String stringify(Date obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDatetime(obj)
+ : obj.toString();
+ }
+
+ public Date parse(String str)
+ throws ParseException
+ {
+ if (_useXsdFormatting)
+ return XmlUtil.parseXsdDatetime(str);
+ else
+ {
+ synchronized (_defaultFormat)
+ {
+ return _defaultFormat.parse(str);
+ }
+ }
+ }
+ }
+}
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java 2009-08-14 19:00:11 UTC (rev 104)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -1,446 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import net.sf.practicalxml.XmlUtil;
-
-
-/**
- * Responsible for converting "primitive" types -- those with unambiguous
- * string representations -- to/from such a representation.
- */
-public class PrimitiveConversionHelper
-{
- // this is not static because the helpers are inner classes
- private Map<Class<?>,ConversionHandler<?>> _helpers
- = new HashMap<Class<?>,ConversionHandler<?>>();
- {
- _helpers.put(String.class, new StringConversionHandler());
- _helpers.put(Character.class, new CharacterConversionHandler());
- _helpers.put(Boolean.class, new BooleanConversionHandler());
- _helpers.put(Byte.class, new ByteConversionHandler());
- _helpers.put(Short.class, new ShortConversionHandler());
- _helpers.put(Integer.class, new IntegerConversionHandler());
- _helpers.put(Long.class, new LongConversionHandler());
- _helpers.put(Float.class, new FloatConversionHandler());
- _helpers.put(Double.class, new DoubleConversionHandler());
- _helpers.put(BigInteger.class, new BigIntegerConversionHandler());
- _helpers.put(BigDecimal.class, new BigDecimalConversionHandler());
- _helpers.put(Date.class, new DateConversionHandler());
- }
-
- private boolean _useXsdFormatting;
-
-
- /**
- * Default constructor, which uses Java formatting.
- */
- public PrimitiveConversionHelper()
- {
- // nothing to see here
- }
-
-
- /**
- * Constructor that allows selection of Java or XSD formatting.
- */
- public PrimitiveConversionHelper(boolean useXsdFormatting)
- {
- _useXsdFormatting = useXsdFormatting;
- }
-
-
-//----------------------------------------------------------------------------
-// Public Methods
-//----------------------------------------------------------------------------
-
- /**
- * Returns the XSD type name to use for stringified objects of the
- * specified class, <code>null</code> if this converter can't convert
- * instances of the class.
- */
- public String getXsdType(Class<?> klass)
- {
- ConversionHandler<?> helper = _helpers.get(klass);
- return (helper == null) ? null : helper.getXsiType();
- }
-
-
- /**
- * Converts the passed object into its string representation, according
- * to the options currently in effect. Passing <code>null</code> will
- * return <code>null</code>. Throws {@link ConversionException} if
- * unable to convert the passed object.
- */
- public String stringify(Object obj)
- {
- if (obj == null)
- return null;
-
- try
- {
- return getHelper(obj.getClass()).stringify(obj);
- }
- catch (Exception ee)
- {
- if (ee instanceof ConversionException)
- throw (ConversionException)ee;
- throw new ConversionException("unable to convert: " + obj, ee);
- }
- }
-
-
- /**
- * Parses the passed string into an object of the desired class. Passing
- * <code>null</code> will return <code>null</code>, passing an empty
- * string will typically throw a {@link ConversionException}.
- */
- public Object parse(String str, Class<?> klass)
- {
- if (str == null)
- return null;
-
- try
- {
- return getHelper(klass).parse(str);
- }
- catch (Exception ee)
- {
- if (ee instanceof ConversionException)
- throw (ConversionException)ee;
- throw new ConversionException("unable to parse: " + str, ee);
- }
- }
-
-
-//----------------------------------------------------------------------------
-// Internals
-//----------------------------------------------------------------------------
-
- /**
- * Returns the appropriate conversion helper or throws.
- */
- @SuppressWarnings(value="unchecked")
- private ConversionHandler getHelper(Class<?> klass)
- {
- ConversionHandler<?> helper = _helpers.get(klass);
- if (helper == null)
- throw new ConversionException("unable to get helper: " + klass.getName());
- return helper;
- }
-
-
- /**
- * Each primitive class has its own conversion handler that is responsible
- * for converting to/from a string representation. Handlers are guaranteed
- * to receive non-null objects/strings.
- * <p>
- * This interface is parameterized so that the compiler will generate
- * bridge methods for implementation classes. Elsewhere, we don't care
- * about parameterization, so wildcard or drop it (see {@link #getHelper}).
- * <p>
- * Implementation classes are expected to be inner classes, so that they
- * have access to configuration information (such as formatting rules).
- * <p>
- * Implementation classes are permitted to throw any exception; caller is
- * expected to catch them and translate to a {@link ConversionException}.
- */
- private static interface ConversionHandler<T>
- {
- public String getXsiType();
- public String stringify(T obj) throws Exception;
- public T parse(String str) throws Exception;
- }
-
-
- private class StringConversionHandler
- implements ConversionHandler<String>
- {
- public String getXsiType()
- {
- return "xsd:string";
- }
-
- public String stringify(String obj)
- {
- return String.valueOf(obj);
- }
-
- public String parse(String str)
- {
- return str;
- }
- }
-
-
- private class CharacterConversionHandler
- implements ConversionHandler<Character>
- {
- private final Character NUL = Character.valueOf('\0');
-
- public String getXsiType()
- {
- return "xsd:string";
- }
-
- public String stringify(Character obj)
- {
- if (obj.equals(NUL))
- return "";
- return obj.toString();
- }
-
- public Character parse(String str)
- {
- if (str.length() == 0)
- return NUL;
- if (str.length() > 1)
- throw new ConversionException(
- "attempted to convert multi-character string: \"" + str + "\"");
- return Character.valueOf(str.charAt(0));
- }
- }
-
-
- private class BooleanConversionHandler
- implements ConversionHandler<Boolean>
- {
- public String getXsiType()
- {
- return "xsd:boolean";
- }
-
- public String stringify(Boolean obj)
- {
- return _useXsdFormatting
- ? XmlUtil.formatXsdBoolean(obj.booleanValue())
- : obj.toString();
- }
-
- public Boolean parse(String str)
- {
- return _useXsdFormatting
- ? XmlUtil.parseXsdBoolean(str)
- : Boolean.parseBoolean(str);
- }
- }
-
-
- private class ByteConversionHandler
- implements ConversionHandler<Byte>
- {
- public String getXsiType()
- {
- return "xsd:byte";
- }
-
- public String stringify(Byte obj)
- {
- return obj.toString();
- }
-
- public Byte parse(String str)
- {
- return Byte.valueOf(str.trim());
- }
- }
-
-
- private class ShortConversionHandler
- implements ConversionHandler<Short>
- {
- public String getXsiType()
- {
- return "xsd:short";
- }
-
- public String stringify(Short obj)
- {
- return obj.toString();
- }
-
- public Short parse(String str)
- {
- return Short.valueOf(str.trim());
- }
- }
-
-
- private class IntegerConversionHandler
- implements ConversionHandler<Integer>
- {
- public String getXsiType()
- {
- return "xsd:int";
- }
-
- public String stringify(Integer obj)
- {
- return obj.toString();
- }
-
- public Integer parse(String str)
- {
- return Integer.valueOf(str.trim());
- }
- }
-
-
- private class LongConversionHandler
- implements ConversionHandler<Long>
- {
- public String getXsiType()
- {
- return "xsd:long";
- }
-
- public String stringify(Long obj)
- {
- return obj.toString();
- }
-
- public Long parse(String str)
- {
- return Long.valueOf(str.trim());
- }
- }
-
-
- private class FloatConversionHandler
- implements ConversionHandler<Float>
- {
- public String getXsiType()
- {
- return "xsd:decimal";
- }
-
- public String stringify(Float obj)
- {
- return _useXsdFormatting
- ? XmlUtil.formatXsdDecimal(obj)
- : obj.toString();
- }
-
- public Float parse(String str)
- {
- return Float.valueOf(str.trim());
- }
- }
-
-
- private class DoubleConversionHandler
- implements ConversionHandler<Double>
- {
- public String getXsiType()
- {
- return "xsd:decimal";
- }
-
- public String stringify(Double obj)
- {
- return _useXsdFormatting
- ? XmlUtil.formatXsdDecimal(obj)
- : obj.toString();
- }
-
- public Double parse(String str)
- {
- return Double.valueOf(str.trim());
- }
- }
-
-
- private class BigIntegerConversionHandler
- implements ConversionHandler<BigInteger>
- {
- public String getXsiType()
- {
- return "xsd:decimal";
- }
-
- public String stringify(BigInteger obj)
- {
- return obj.toString();
- }
-
- public BigInteger parse(String str)
- {
- return new BigInteger(str.trim());
- }
- }
-
-
- private class BigDecimalConversionHandler
- implements ConversionHandler<BigDecimal>
- {
- public String getXsiType()
- {
- return "xsd:decimal";
- }
-
- public String stringify(BigDecimal obj)
- {
- return obj.toString();
- }
-
- public BigDecimal parse(String str)
- {
- return new BigDecimal(str.trim());
- }
- }
-
-
- private class DateConversionHandler
- implements ConversionHandler<Date>
- {
- // format as specified by Date.toString() JavaDoc
- private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
-
- public String getXsiType()
- {
- return "xsd:dateTime";
- }
-
- public String stringify(Date obj)
- {
- return _useXsdFormatting
- ? XmlUtil.formatXsdDatetime(obj)
- : obj.toString();
- }
-
- public Date parse(String str)
- throws ParseException
- {
- if (_useXsdFormatting)
- return XmlUtil.parseXsdDatetime(str);
- else
- {
- synchronized (_defaultFormat)
- {
- return _defaultFormat.parse(str);
- }
- }
- }
- }
-}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 19:00:11 UTC (rev 104)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -28,7 +28,7 @@
import net.sf.practicalxml.DomUtil;
import net.sf.practicalxml.converter.ConversionException;
-import net.sf.practicalxml.converter.PrimitiveConversionHelper;
+import net.sf.practicalxml.converter.ConversionHelper;
import net.sf.practicalxml.converter.bean2xml.Bean2XmlAppenders.*;
@@ -42,13 +42,13 @@
public class Bean2XmlDriver
{
private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class);
- private PrimitiveConversionHelper _primitiveHelper;
+ private ConversionHelper _primitiveHelper;
public Bean2XmlDriver(Bean2XmlOptions... options)
{
for (Bean2XmlOptions option : options)
_options.add(option);
- _primitiveHelper = new PrimitiveConversionHelper(shouldUseXsdFormatting());
+ _primitiveHelper = new ConversionHelper(shouldUseXsdFormatting());
}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java 2009-08-14 19:00:11 UTC (rev 104)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -18,7 +18,7 @@
import net.sf.practicalxml.XmlException;
import net.sf.practicalxml.XmlUtil;
import net.sf.practicalxml.converter.ConversionException;
-import net.sf.practicalxml.converter.PrimitiveConversionHelper;
+import net.sf.practicalxml.converter.ConversionHelper;
import net.sf.practicalxml.internal.StringUtils;
import java.util.Arrays;
@@ -42,7 +42,7 @@
public class Xml2BeanHandler
{
private EnumSet<Xml2BeanOptions> _options;
- private PrimitiveConversionHelper _primitiveHelper;
+ private ConversionHelper _primitiveHelper;
/**
@@ -54,7 +54,7 @@
for (Xml2BeanOptions option : options)
_options.add(option);
- _primitiveHelper = new PrimitiveConversionHelper(true);
+ _primitiveHelper = new ConversionHelper(true);
}
Copied: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java (from rev 99, branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java)
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -0,0 +1,529 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+
+public class TestConversionHelper
+extends AbstractBeanConverterTestCase
+{
+ public TestConversionHelper(String name)
+ {
+ super(name);
+ }
+
+
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ private void assertFailsConversionToObject(
+ String message,
+ ConversionHelper helper,
+ String str,
+ Class<?> klass)
+ {
+ try
+ {
+ helper.parse(str, klass);
+ fail(message);
+ }
+ catch (ConversionException ee)
+ {
+ // success!
+ }
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ public void testUnknownClass() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertNull(helper.getXsdType(Class.class));
+ }
+
+
+ public void testConvertNull() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertNull(helper.stringify(null));
+ assertNull(helper.parse(null, Object.class));
+ }
+
+
+ public void testConvertString() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:string", helper.getXsdType(String.class));
+
+ assertEquals("foo", helper.stringify("foo"));
+ assertEquals("foo", helper.parse("foo", String.class));
+
+ assertEquals("", helper.stringify(""));
+ assertEquals("", helper.parse("", String.class));
+ }
+
+
+ public void testConvertCharacter() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:string", helper.getXsdType(Character.class));
+
+ Character simple = Character.valueOf('A');
+ assertEquals("A", helper.stringify(simple));
+ assertEquals(simple, helper.parse("A", Character.class));
+
+ Character nul = Character.valueOf('\0');
+ assertEquals("", helper.stringify(nul));
+ assertEquals(nul, helper.parse("", Character.class));
+
+ assertFailsConversionToObject(
+ "converted multi-character string",
+ helper, "ix", Character.class);
+ }
+
+
+ public void testConvertBooleanDefault() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ // default boolean conversion is compatible with XSD type def
+ assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
+
+ String sTrue = Boolean.TRUE.toString();
+ assertEquals(sTrue, helper.stringify(Boolean.TRUE));
+ assertEquals(Boolean.TRUE, helper.parse(sTrue, Boolean.class));
+
+ String sFalse = Boolean.FALSE.toString();
+ assertEquals(sFalse, helper.stringify(Boolean.FALSE));
+ assertEquals(Boolean.FALSE, helper.parse(sFalse, Boolean.class));
+
+ assertEquals(Boolean.FALSE, helper.parse("ix", Boolean.class));
+ assertEquals(Boolean.FALSE, helper.parse("", Boolean.class));
+ }
+
+
+ public void testConvertBooleanXsd() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper(true);
+
+ assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
+
+ assertEquals("true", helper.stringify(Boolean.TRUE));
+ assertEquals(Boolean.TRUE, helper.parse("true", Boolean.class));
+ assertEquals(Boolean.TRUE, helper.parse("1", Boolean.class));
+
+ assertEquals("false", helper.stringify(Boolean.FALSE));
+ assertEquals(Boolean.FALSE, helper.parse("false", Boolean.class));
+ assertEquals(Boolean.FALSE, helper.parse("0", Boolean.class));
+
+ assertFailsConversionToObject(
+ "converted multi-character string",
+ helper, "ix", Boolean.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Boolean.class);
+ }
+
+
+ public void testConvertByte() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:byte", helper.getXsdType(Byte.class));
+
+ String str1 = "123";
+ Byte val1 = Byte.valueOf((byte)123);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Byte.class));
+
+ String str2 = "-123";
+ Byte val2 = Byte.valueOf((byte)-123);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Byte.class));
+
+ String str3 = " -123 ";
+ Byte val3 = Byte.valueOf((byte)-123);
+ assertEquals(val3, helper.parse(str3, Byte.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "1234567", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "1.23", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Byte.class);
+ }
+
+
+ public void testConvertShort() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:short", helper.getXsdType(Short.class));
+
+ String str1 = "12345";
+ Short val1 = Short.valueOf((short)12345);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Short.class));
+
+ String str2 = "-12345";
+ Short val2 = Short.valueOf((short)-12345);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Short.class));
+
+ String str3 = " -12345 ";
+ Short val3 = Short.valueOf((short)-12345);
+ assertEquals(val3, helper.parse(str3, Short.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "1234567", Short.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Short.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Short.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Short.class);
+ }
+
+
+ public void testConvertInteger() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:int", helper.getXsdType(Integer.class));
+
+ String str1 = "1234567";
+ Integer val1 = Integer.valueOf(1234567);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Integer.class));
+
+ String str2 = "-1234567";
+ Integer val2 = Integer.valueOf(-1234567);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Integer.class));
+
+ String str3 = " -1234567 ";
+ Integer val3 = Integer.valueOf(-1234567);
+ assertEquals(val3, helper.parse(str3, Integer.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "123456789012345", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Integer.class);
+ }
+
+
+ public void testConvertLong() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:long", helper.getXsdType(Long.class));
+
+ String str1 = "1234567890";
+ Long val1 = Long.valueOf(1234567890L);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Long.class));
+
+ String str2 = "-1234567890";
+ Long val2 = Long.valueOf(-1234567890L);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Long.class));
+
+ String str3 = " -1234567890 ";
+ Long val3 = Long.valueOf(-1234567890L);
+ assertEquals(val3, helper.parse(str3, Long.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "123456789012345678901234567890", Long.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Long.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Long.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Long.class);
+ }
+
+
+ public void testConvertFloatDefault() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ // default float conversion is compatible with XSD type def
+ assertEquals("xsd:decimal", helper.getXsdType(Float.class));
+
+ // note: for default-format tests, strings are generated from values
+ Float val1 = Float.valueOf(1234f);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Float.class));
+
+ Float val2 = Float.valueOf(-1234f);
+ String str2 = val2.toString();
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Float.class));
+
+ String str3 = " -1234.5 ";
+ Float val3 = Float.valueOf(-1234.5f);
+ assertEquals(val3, helper.parse(str3, Float.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Float.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Float.class);
+ }
+
+
+ public void testConvertFloatXsd() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper(true);
+
+ assertEquals("xsd:decimal", helper.getXsdType(Float.class));
+
+ String str1 = "1234.0";
+ Float val1 = Float.valueOf(1234f);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Float.class));
+
+ String str2 = "-1234.0";
+ Float val2 = Float.valueOf(-1234f);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Float.class));
+
+ String str3 = " -1234.5 ";
+ Float val3 = Float.valueOf(-1234.5f);
+ assertEquals(val3, helper.parse(str3, Float.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Float.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Float.class);
+ }
+
+
+ public void testConvertDoubleDefault() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ // default double conversion is compatible with XSD type def
+ assertEquals("xsd:decimal", helper.getXsdType(Double.class));
+
+ // note: for default-format tests, strings are generated from values
+ Double val1 = Double.valueOf(1234567890.5);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Double.class));
+
+ Double val2 = Double.valueOf(-1234567890.1);
+ String str2 = val2.toString();
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Double.class));
+
+ String str3 = " -1234.5 ";
+ Double val3 = Double.valueOf(-1234.5);
+ assertEquals(val3, helper.parse(str3, Double.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Double.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Double.class);
+ }
+
+
+ public void testConvertDoubleXsd() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper(true);
+
+ assertEquals("xsd:decimal", helper.getXsdType(Double.class));
+
+ // while for XSD-format tests, we want to verify the strings
+ String str1 = "1234567890.5";
+ Double val1 = Double.valueOf(1234567890.5);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Double.class));
+
+ String str2 = "-1234567890.1";
+ Double val2 = Double.valueOf(-1234567890.1);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Double.class));
+
+ String str3 = " -1234.5 ";
+ Double val3 = Double.valueOf(-1234.5);
+ assertEquals(val3, helper.parse(str3, Double.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Double.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Double.class);
+ }
+
+
+ public void testConvertBigInteger() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:decimal", helper.getXsdType(BigInteger.class));
+
+ String str1 = "123456789012345678901234567890";
+ BigInteger val1 = new BigInteger(str1);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, BigInteger.class));
+
+ String str2 = "-123456789012345678901234567890";
+ BigInteger val2 = new BigInteger(str2);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, BigInteger.class));
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", BigInteger.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", BigInteger.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", BigInteger.class);
+ }
+
+
+ public void testConvertBigDecimal() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ assertEquals("xsd:decimal", helper.getXsdType(BigDecimal.class));
+
+ String str1 = "12345678901234567890.123456789";
+ BigDecimal val1 = new BigDecimal(str1);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, BigDecimal.class));
+
+ String str2 = "-12345678901234567890.123456789";
+ BigDecimal val2 = new BigDecimal(str2);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, BigDecimal.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", BigDecimal.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", BigDecimal.class);
+ }
+
+
+ public void testConvertDateDefault() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper();
+
+ // default date conversion is NOT compatible with XSD type def,
+ // so this is misleading
+ assertEquals("xsd:dateTime", helper.getXsdType(Date.class));
+
+ // for default conversion, we create string from value
+ Date val1 = new Date(1247551703000L);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Date.class));
+
+
+ assertFailsConversionToObject(
+ "converted non-date value",
+ helper, "ix", Date.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Date.class);
+ }
+
+
+ public void testConvertDateXsd() throws Exception
+ {
+ ConversionHelper helper = new ConversionHelper(true);
+
+ assertEquals("xsd:dateTime", helper.getXsdType(Date.class));
+
+ Date val1 = new Date(1247551703000L);
+ String str1 = "2009-07-14T06:08:23";
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Date.class));
+
+ assertFailsConversionToObject(
+ "converted non-date value",
+ helper, "ix", Date.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Date.class);
+ }
+}
Deleted: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java 2009-08-14 19:00:11 UTC (rev 104)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java 2009-08-14 20:05:39 UTC (rev 105)
@@ -1,529 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-
-
-public class TestPrimitiveConversionHelper
-extends AbstractBeanConverterTestCase
-{
- public TestPrimitiveConversionHelper(String name)
- {
- super(name);
- }
-
-
-//----------------------------------------------------------------------------
-// Support Code
-//----------------------------------------------------------------------------
-
- private void assertFailsConversionToObject(
- String message,
- PrimitiveConversionHelper helper,
- String str,
- Class<?> klass)
- {
- try
- {
- helper.parse(str, klass);
- fail(message);
- }
- catch (ConversionException ee)
- {
- // success!
- }
- }
-
-
-//----------------------------------------------------------------------------
-// Test Cases
-//----------------------------------------------------------------------------
-
- public void testUnknownClass() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertNull(helper.getXsdType(Class.class));
- }
-
-
- public void testConvertNull() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertNull(helper.stringify(null));
- assertNull(helper.parse(null, Object.class));
- }
-
-
- public void testConvertString() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:string", helper.getXsdType(String.class));
-
- assertEquals("foo", helper.stringify("foo"));
- assertEquals("foo", helper.parse("foo", String.class));
-
- assertEquals("", helper.stringify(""));
- assertEquals("", helper.parse("", String.class));
- }
-
-
- public void testConvertCharacter() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:string", helper.getXsdType(Character.class));
-
- Character simple = Character.valueOf('A');
- assertEquals("A", helper.stringify(simple));
- assertEquals(simple, helper.parse("A", Character.class));
-
- Character nul = Character.valueOf('\0');
- assertEquals("", helper.stringify(nul));
- assertEquals(nul, helper.parse("", Character.class));
-
- assertFailsConversionToObject(
- "converted multi-character string",
- helper, "ix", Character.class);
- }
-
-
- public void testConvertBooleanDefault() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- // default boolean conversion is compatible with XSD type def
- assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
-
- String sTrue = Boolean.TRUE.toString();
- assertEquals(sTrue, helper.stringify(Boolean.TRUE));
- assertEquals(Boolean.TRUE, helper.parse(sTrue, Boolean.class));
-
- String sFalse = Boolean.FALSE.toString();
- assertEquals(sFalse, helper.stringify(Boolean.FALSE));
- assertEquals(Boolean.FALSE, helper.parse(sFalse, Boolean.class));
-
- assertEquals(Boolean.FALSE, helper.parse("ix", Boolean.class));
- assertEquals(Boolean.FALSE, helper.parse("", Boolean.class));
- }
-
-
- public void testConvertBooleanXsd() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
-
- assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
-
- assertEquals("true", helper.stringify(Boolean.TRUE));
- assertEquals(Boolean.TRUE, helper.parse("true", Boolean.class));
- assertEquals(Boolean.TRUE, helper.parse("1", Boolean.class));
-
- assertEquals("false", helper.stringify(Boolean.FALSE));
- assertEquals(Boolean.FALSE, helper.parse("false", Boolean.class));
- assertEquals(Boolean.FALSE, helper.parse("0", Boolean.class));
-
- assertFailsConversionToObject(
- "converted multi-character string",
- helper, "ix", Boolean.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Boolean.class);
- }
-
-
- public void testConvertByte() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:byte", helper.getXsdType(Byte.class));
-
- String str1 = "123";
- Byte val1 = Byte.valueOf((byte)123);
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Byte.class));
-
- String str2 = "-123";
- Byte val2 = Byte.valueOf((byte)-123);
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Byte.class));
-
- String str3 = " -123 ";
- Byte val3 = Byte.valueOf((byte)-123);
- assertEquals(val3, helper.parse(str3, Byte.class));
-
- assertFailsConversionToObject(
- "converted too-large value",
- helper, "1234567", Byte.class);
-
- assertFailsConversionToObject(
- "converted non-integer value",
- helper, "1.23", Byte.class);
-
- assertFailsConversionToObject(
- "converted non-numeric value",
- helper, "ix", Byte.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Byte.class);
- }
-
-
- public void testConvertShort() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:short", helper.getXsdType(Short.class));
-
- String str1 = "12345";
- Short val1 = Short.valueOf((short)12345);
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Short.class));
-
- String str2 = "-12345";
- Short val2 = Short.valueOf((short)-12345);
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Short.class));
-
- String str3 = " -12345 ";
- Short val3 = Short.valueOf((short)-12345);
- assertEquals(val3, helper.parse(str3, Short.class));
-
- assertFailsConversionToObject(
- "converted too-large value",
- helper, "1234567", Short.class);
-
- assertFailsConversionToObject(
- "converted non-integer value",
- helper, "123.45", Short.class);
-
- assertFailsConversionToObject(
- "converted non-numeric value",
- helper, "ix", Short.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Short.class);
- }
-
-
- public void testConvertInteger() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:int", helper.getXsdType(Integer.class));
-
- String str1 = "1234567";
- Integer val1 = Integer.valueOf(1234567);
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Integer.class));
-
- String str2 = "-1234567";
- Integer val2 = Integer.valueOf(-1234567);
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Integer.class));
-
- String str3 = " -1234567 ";
- Integer val3 = Integer.valueOf(-1234567);
- assertEquals(val3, helper.parse(str3, Integer.class));
-
- assertFailsConversionToObject(
- "converted too-large value",
- helper, "123456789012345", Integer.class);
-
- assertFailsConversionToObject(
- "converted non-integer value",
- helper, "123.45", Integer.class);
-
- assertFailsConversionToObject(
- "converted non-numeric value",
- helper, "ix", Integer.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Integer.class);
- }
-
-
- public void testConvertLong() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- assertEquals("xsd:long", helper.getXsdType(Long.class));
-
- String str1 = "1234567890";
- Long val1 = Long.valueOf(1234567890L);
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Long.class));
-
- String str2 = "-1234567890";
- Long val2 = Long.valueOf(-1234567890L);
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Long.class));
-
- String str3 = " -1234567890 ";
- Long val3 = Long.valueOf(-1234567890L);
- assertEquals(val3, helper.parse(str3, Long.class));
-
- assertFailsConversionToObject(
- "converted too-large value",
- helper, "123456789012345678901234567890", Long.class);
-
- assertFailsConversionToObject(
- "converted non-integer value",
- helper, "123.45", Long.class);
-
- assertFailsConversionToObject(
- "converted non-numeric value",
- helper, "ix", Long.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Long.class);
- }
-
-
- public void testConvertFloatDefault() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
-
- // default float conversion is compatible with XSD type def
- assertEquals("xsd:decimal", helper.getXsdType(Float.class));
-
- // note: for default-format tests, strings are generated from values
- Float val1 = Float.valueOf(1234f);
- String str1 = val1.toString();
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Float.class));
-
- Float val2 = Float.valueOf(-1234f);
- String str2 = val2.toString();
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Float.class));
-
- String str3 = " -1234.5 ";
- Float val3 = Float.valueOf(-1234.5f);
- assertEquals(val3, helper.parse(str3, Float.class));
-
- assertFailsConversionToObject(
- "converted non-numeric value",
- helper, "ix", Float.class);
-
- assertFailsConversionToObject(
- "converted empty string",
- helper, "", Float.class);
- }
-
-
- public void testConvertFloatXsd() throws Exception
- {
- PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
-
- assertEquals("xsd:decimal", helper.getXsdType(Float.class));
-
- String str1 = "1234.0";
- Float val1 = Float.valueOf(1234f);
- assertEquals(str1, helper.stringify(val1));
- assertEquals(val1, helper.parse(str1, Float.class));
-
- String str2 = "-1234.0";
- Float val2 = Float.valueOf(-1234f);
- assertEquals(str2, helper.stringify(val2));
- assertEquals(val2, helper.parse(str2, Float.class));
-
- String str3 = " -1234.5 ";
- Float val3 = Float.valueOf(-1234.5f);
- assertEquals(val3, helper.parse(str3, Float.class));
-
- assertFailsConversionToObject(
- ...
[truncated message content] |
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 19:41:28
|
The package and class structure has changed pretty extensively; Sourceforge held up the original commit notification because it was too large. If you're playing with this, I suggest blowing away your working copy and checking out the latest from the branch. -kdg |
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 19:00:17
|
Revision: 104
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=104&view=rev
Author: kdgregory
Date: 2009-08-14 19:00:11 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
historical release tag
Added Paths:
-----------
tags/rel-1.0.3/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 18:59:19
|
Revision: 103
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=103&view=rev
Author: kdgregory
Date: 2009-08-14 18:59:10 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
historical release tag
Added Paths:
-----------
tags/rel-1.0.2/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 18:57:05
|
Revision: 102
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=102&view=rev
Author: kdgregory
Date: 2009-08-14 18:56:56 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
historical release tag
Added Paths:
-----------
tags/rel-1.0.1/trunk/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 18:54:10
|
Revision: 101
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=101&view=rev
Author: kdgregory
Date: 2009-08-14 18:54:03 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
historical release tag
Added Paths:
-----------
tags/rel-1.0.1/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 18:41:56
|
Revision: 100
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=100&view=rev
Author: kdgregory
Date: 2009-08-14 18:41:47 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
repackage
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java
Removed Paths:
-------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,235 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.util.EnumSet;
-
-import javax.xml.XMLConstants;
-
-import org.w3c.dom.Element;
-
-import net.sf.practicalxml.DomUtil;
-
-
-/**
- * Packaging class used for XML output appenders. This class is a temporary
- * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained
- * classes will end up in a new package, once I figure out what the package
- * structure should be.
- */
-public abstract class Bean2XmlAppenders
-{
- /**
- * An <code>Appender</code> appends children to a single node of the
- * output tree. The driver is responsible for creating new appenders
- * for each compound element, including the root, and providing those
- * appenders with options to control output generation.
- */
- public interface Appender
- {
- /**
- * Appends a value element to the current element. Value elements have
- * associated text, but no other children.
- *
- * @param name Name to be associated with the node.
- * @param type Type to be associated with the node; may or may
- * not be written to the output, depending on the
- * appender's options.
- * @param value The node's value. May be <code>null</code>, in
- * which case the appender decides whether or not
- * to actually append the node.
- *
- * @return The appended element. This is a convenience for subclasses,
- * which may want to set additional attributes after their
- * super has done the work of appending the element.
- * @throws ConversionException if unable to append the node.
- */
- public Element appendValue(String name, String type, String value);
-
-
- /**
- * Appends a container element to the current element. Container
- * elements have other elements as children, and may have a type,
- * but do not have an associated value.
- */
- public Element appendContainer(String name, String type);
- }
-
-
- /**
- * Base class for XML appenders, providing helper methods for subclasses.
- */
- private static abstract class AbstractAppender
- implements Appender
- {
- private EnumSet<Bean2XmlOptions> _options;
-
- public AbstractAppender(EnumSet<Bean2XmlOptions> options)
- {
- _options = options;
- }
-
- protected boolean isOptionSet(Bean2XmlOptions option)
- {
- return _options.contains(option);
- }
-
- protected boolean shouldSkip(Object value)
- {
- return (value == null) && !_options.contains(Bean2XmlOptions.XSI_NIL);
- }
-
- protected void setType(Element elem, String type)
- {
- if (isOptionSet(Bean2XmlOptions.XSI_TYPE))
- elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type);
- }
-
- protected void setValue(Element elem, String value)
- {
- if (value != null)
- DomUtil.setText(elem, value);
- else if (isOptionSet(Bean2XmlOptions.XSI_NIL))
- elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true");
- }
- }
-
-
- /**
- * Basic appender, which appends new elements to a parent.
- */
- public static class BasicAppender
- extends AbstractAppender
- {
- private Element _parent;
-
- public BasicAppender(Element parent, EnumSet<Bean2XmlOptions> options)
- {
- super(options);
- _parent = parent;
- }
-
- public Element appendValue(String name, String type, String value)
- {
- if (shouldSkip(value))
- return null;
-
- Element child = DomUtil.appendChildInheritNamespace(_parent, name);
- setType(child, type);
- setValue(child, value);
- return child;
- }
-
- public Element appendContainer(String name, String type)
- {
- Element child = DomUtil.appendChildInheritNamespace(_parent, name);
- setType(child, type);
- return child;
- }
- }
-
-
- /**
- * Appender for children of an indexed/iterated item (array, list, or set).
- * Each element will have an incremented <code>index</code> attribute that
- * indicates the position of the element within the iteration.
- */
- public static class IndexedAppender
- extends BasicAppender
- {
- int _index = 0;
-
- public IndexedAppender(Element parent, EnumSet<Bean2XmlOptions> options)
- {
- super(parent, options);
- }
-
-
- @Override
- public Element appendValue(String name, String type, String value)
- {
- Element child = super.appendValue(name, type, value);
- if (child != null)
- child.setAttribute("index", String.valueOf(_index++));
- return child;
- }
- }
-
-
- /**
- * Appender for children of a <code>Map</code>. Depending on options,
- * will either create children named after the key, or a generic "data"
- * child with the key as an attribute.
- */
- public static class MapAppender
- extends BasicAppender
- {
- public MapAppender(Element parent, EnumSet<Bean2XmlOptions> options)
- {
- super(parent, options);
- }
-
-
- @Override
- public Element appendValue(String name, String type, String value)
- {
- Element child = null;
- if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS))
- {
- child = super.appendValue(name, type, value);
- }
- else
- {
- child = super.appendValue("data", type, value);
- if (child != null)
- child.setAttribute("key", name);
- }
- return child;
- }
- }
-
-
- /**
- * An appender that sets values directly on the "parent" element. Used for
- * the conversion root element.
- */
- public static class DirectAppender
- extends AbstractAppender
- {
- private Element _elem;
-
- public DirectAppender(Element elem, EnumSet<Bean2XmlOptions> options)
- {
- super(options);
- _elem = elem;
- }
-
- public Element appendValue(String name, String type, String value)
- {
- if (!shouldSkip(value))
- {
- setType(_elem, type);
- setValue(_elem, value);
- }
- return _elem;
- }
-
- public Element appendContainer(String name, String type)
- {
- setType(_elem, type);
- return _elem;
- }
- }
-}
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,234 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Map;
-
-import org.w3c.dom.Element;
-
-import net.sf.practicalxml.DomUtil;
-import net.sf.practicalxml.converter.Bean2XmlAppenders.Appender;
-import net.sf.practicalxml.converter.Bean2XmlAppenders.BasicAppender;
-import net.sf.practicalxml.converter.Bean2XmlAppenders.DirectAppender;
-import net.sf.practicalxml.converter.Bean2XmlAppenders.IndexedAppender;
-import net.sf.practicalxml.converter.Bean2XmlAppenders.MapAppender;
-
-
-/**
- * Driver class for converting bean data to an XML representation. In normal
- * usage, an instance of this class is constructed with the desired conversion
- * options, then {@link #convert} is called with the compound object to be
- * converted. The driver may be reused for multiple conversions, and is
- * thread-safe.
- */
-public class Bean2XmlDriver
-{
- private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class);
- private PrimitiveConversionHelper _primitiveHelper;
-
- public Bean2XmlDriver(Bean2XmlOptions... options)
- {
- for (Bean2XmlOptions option : options)
- _options.add(option);
- _primitiveHelper = new PrimitiveConversionHelper(shouldUseXsdFormatting());
- }
-
-
-//----------------------------------------------------------------------------
-// Public methods
-//----------------------------------------------------------------------------
-
- /**
- * Creates an XML DOM with the specified root element name, and fills it
- * by introspecting the passed object (see {@link #introspect} for
- * treatment of simple objects).
- */
- public Element convert(Object obj, String rootName)
- {
- return convert(obj, null, rootName);
- }
-
-
- /**
- * Creates an XML DOM with the specified root element name and namespace
- * URI, and fills it by introspecting the passed object (see {@link
- * #introspect} for treatment of simple objects). The namespace URI (and
- * prefix, if provided) will be used for all child elements.
- */
- public Element convert(Object obj, String nsUri, String rootName)
- {
- Element root = DomUtil.newDocument(nsUri, rootName);
- convert(obj, "", new DirectAppender(root, _options));
- return root;
- }
-
-
- /**
- * Introspects the passed object, and appends its contents to the output.
- * This method is public to allow non-standard conversions, such as
- * appending into an existing tree, or (in the future, if we introduce an
- * appender factory) producing non-XML output.
- */
- public void convert(Object obj, String name, Appender appender)
- {
- // these methods have side effects!
- // empty blocks and comments are there to keep Eclipse happy
- if (tryToConvertAsPrimitiveOrNull(obj, null, name, appender))
- { /* it was converted */ }
- else if (tryToConvertAsArray(obj, name, appender))
- { /* it was converted */ }
- else if (tryToConvertAsMap(obj, name, appender))
- { /* it was converted */ }
- else if (tryToConvertAsCollection(obj, name, appender))
- { /* it was converted */ }
- else if (tryToConvertAsBean(obj, name, appender))
- { /* it was converted */ }
- else
- throw new ConversionException("unable to convert: " + obj.getClass().getName());
- }
-
-
-//----------------------------------------------------------------------------
-// Internals
-//----------------------------------------------------------------------------
-
- private boolean shouldUseXsdFormatting()
- {
- return _options.contains(Bean2XmlOptions.XSD_FORMAT)
- || _options.contains(Bean2XmlOptions.XSI_TYPE);
- }
-
-
- private String getJavaXsiType(Object obj)
- {
- return "java:" + obj.getClass().getName();
- }
-
-
- private boolean tryToConvertAsPrimitiveOrNull(
- Object obj, Class<?> klass, String name, Appender appender)
- {
- if (obj != null)
- klass = obj.getClass();
-
- String objType = _primitiveHelper.getXsdType(klass);
- if ((obj == null) || (objType != null))
- {
- appender.appendValue(name, objType, _primitiveHelper.stringify(obj));
- return true;
- }
-
- return false;
- }
-
-
- private boolean tryToConvertAsArray(Object array, String name, Appender appender)
- {
- if (!array.getClass().isArray())
- return false;
-
- Element parent = appender.appendContainer(name, getJavaXsiType(array));
- Appender childAppender = new IndexedAppender(parent, _options);
- int length = Array.getLength(array);
- for (int idx = 0 ; idx < length ; idx++)
- {
- Object value = Array.get(array, idx);
- convert(value, "data", childAppender);
- }
- return true;
- }
-
-
- private boolean tryToConvertAsMap(Object obj, String name, Appender appender)
- {
- if (!(obj instanceof Map))
- return false;
-
- Element parent = appender.appendContainer(name, getJavaXsiType(obj));
- Appender childAppender = new MapAppender(parent, _options);
- for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet())
- {
- convert(entry.getValue(), String.valueOf(entry.getKey()), childAppender);
- }
- return true;
- }
-
-
- private boolean tryToConvertAsCollection(Object obj, String name, Appender appender)
- {
- if (!(obj instanceof Collection))
- return false;
-
- Element parent = appender.appendContainer(name, getJavaXsiType(obj));
- Appender childAppender = new IndexedAppender(parent, _options);
- for (Object value : (Collection<?>)obj)
- {
- convert(value, "data", childAppender);
- }
- return true;
- }
-
-
- private boolean tryToConvertAsBean(Object bean, String name, Appender appender)
- {
- Element parent = appender.appendContainer(name, getJavaXsiType(bean));
- Appender childAppender = new BasicAppender(parent, _options);
- try
- {
- BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class);
- PropertyDescriptor[] props = info.getPropertyDescriptors();
- for (int ii = 0 ; ii < props.length ; ii++)
- convertBeanProperty(bean, props[ii], childAppender);
- }
- catch (IntrospectionException ee)
- {
- throw new ConversionException("introspection failure", ee);
- }
- return true;
- }
-
-
- private void convertBeanProperty(
- Object bean, PropertyDescriptor propDesc, Appender appender)
- {
- String name = propDesc.getName();
- Class<?> type = propDesc.getPropertyType();
- Object value;
- try
- {
- Method getter = propDesc.getReadMethod();
- if (getter == null)
- return;
- value = getter.invoke(bean);
- }
- catch (Exception ee)
- {
- throw new ConversionException("unable to retrieve bean value", ee);
- }
-
- if (value == null)
- tryToConvertAsPrimitiveOrNull(value, type, name, appender);
- else
- convert(value, name, appender);
- }
-}
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,55 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-
-/**
- * Options used by {@link Bean2XmlHandler} to control the structure of the
- * DOM tree.
- */
-public enum Bean2XmlOptions
-{
- /**
- * Outputs values using formats defined by XML Schema, rather than Java's
- * <code>String.valueOf()</code> method. Note that these formats are not
- * flagged in the element, so sender and receiver will have to agree on
- * the format.
- */
- XSD_FORMAT,
-
- /**
- * Will add an <code>xsi:type</code> attribute to each element. For values
- * covered by the XML Schema simple types, this attribute's value will be
- * "<code>xsd:XXX</code>", where XXX is the XSD type name. For complex
- * types, this attribute's value will be "<code>java:XXX</code>", where
- * XXX is the fully-qualified classname.
- * <p>
- * <em>This option implies {@link #XSD_FORMAT} for simple types</em>.
- */
- XSI_TYPE,
-
- /**
- * Report null values using the <code>xsi:nil="true"</code> attribute. If
- * not present, null values are ignored, and not added to DOM tree.
- */
- XSI_NIL,
-
- /**
- * Output maps in an "introspected" format, where the name of each item
- * is the map key (rather than "data"), and the "key" attribute is omitted.
- * If any key is not a valid XML identifier, the converter will throw.
- */
- INTROSPECT_MAPS
-}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -16,7 +16,10 @@
import org.w3c.dom.Document;
+import net.sf.practicalxml.converter.bean2xml.Bean2XmlDriver;
+import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions;
+
/**
* Converts Java objects (not just beans) to and from an XML representation.
* This was originally developed to support RESTful web services, without the
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,35 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import org.w3c.dom.Element;
-
-
-/**
- * Driver class for converting an XML DOM into a Java bean, using a {@link
- * Xml2BeanHandler} to manage data conversion.
- */
-public class Xml2BeanDriver
-{
- /**
- * Fills a bean-style object from an XML element. For each child of the
- * passed element, tries to find a property with the same name, invokes
- * the appropriate conversion handler method, and sets the property from
- * the result.
- */
- public void dispatch(Element elem, Object bean)
- {
- }
-}
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,192 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import net.sf.practicalxml.DomUtil;
-import net.sf.practicalxml.XmlException;
-import net.sf.practicalxml.XmlUtil;
-import net.sf.practicalxml.internal.StringUtils;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.xml.XMLConstants;
-
-import org.w3c.dom.Element;
-
-
-/**
- * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code>
- * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there
- * will only be one instance of this object created during conversion; all
- * intermediate data can be held on the stack.
- */
-public class Xml2BeanHandler
-{
- private EnumSet<Xml2BeanOptions> _options;
- private PrimitiveConversionHelper _primitiveHelper;
-
-
- /**
- * Public constructor, allowing various options specifications.
- */
- public Xml2BeanHandler(Xml2BeanOptions... options)
- {
- _options = EnumSet.noneOf(Xml2BeanOptions.class);
- for (Xml2BeanOptions option : options)
- _options.add(option);
-
- _primitiveHelper = new PrimitiveConversionHelper(true);
- }
-
-
-//----------------------------------------------------------------------------
-// Public Methods
-//----------------------------------------------------------------------------
-
- public Boolean convertBoolean(Element elem)
- {
- return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class);
- }
-
-
- public Byte convertByte(Element elem)
- {
- return (Byte)_primitiveHelper.parse(getText(elem), Byte.class);
- }
-
-
- public Character convertCharacter(Element elem)
- {
- return (Character)_primitiveHelper.parse(getText(elem), Character.class);
- }
-
-
- public Date convertDate(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Double convertDouble(Element elem)
- {
- return (Double)_primitiveHelper.parse(getText(elem), Double.class);
- }
-
-
- public Float convertFloat(Element elem)
- {
- return (Float)_primitiveHelper.parse(getText(elem), Float.class);
- }
-
-
- public Integer convertInteger(Element elem)
- {
- return (Integer)_primitiveHelper.parse(getText(elem), Integer.class);
- }
-
-
- public Long convertLong(Element elem)
- {
- return (Long)_primitiveHelper.parse(getText(elem), Long.class);
- }
-
-
- public Number convertNumber(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Short convertShort(Element elem)
- {
- return (Short)_primitiveHelper.parse(getText(elem), Short.class);
- }
-
-
- public String convertString(Element elem)
- {
- return (String)_primitiveHelper.parse(getText(elem), String.class);
- }
-
-
- public List<?> convertList(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Set<?> convertSet(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Map<?,?> convertMap(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Object convertObject(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
- public Object[] convertObjectArray(Element elem)
- {
- throw new UnsupportedOperationException("not implemented yet");
- }
-
-
-//----------------------------------------------------------------------------
-// Internals
-//----------------------------------------------------------------------------
-
- /**
- * Returns the text from a passed element, applying any low-level options
- * along the way.
- */
- private String getText(Element elem)
- {
- String text = DomUtil.getText(elem);
- if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text))
- text = null;
- validateXsiNil(elem, text);
- return text;
- }
-
-
- /**
- * Checks for elements that require <code>xsi:nil</code>, and throws if missing.
- */
- private void validateXsiNil(Element elem, String text)
- {
- if (text != null)
- return;
- if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL))
- return;
-
- String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
- if ((attr == null) || !attr.equals("true"))
- throw new ConversionException("empty element without required xsi:nil");
- }
-
-}
Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-14 18:27:36 UTC (rev 99)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -1,71 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-
-/**
- * Options used by {@link Xml2BeanHandler} to control the way that DOM trees
- * are translated to Java beans.
- */
-public enum Xml2BeanOptions
-{
- /**
- * If present, the converter will treat all elements with empty text nodes
- * as if they were empty elements -- in other words, <code>null</code>.
- * Note that this flag will interact with <code>REQUIRE_XSI_NIL</code>.
- */
- CONVERT_BLANK_AS_NULL,
-
-
- /**
- * If present, the converter ignores elements that don't correspond to
- * settable properties of the bean.
- */
- IGNORE_MISSING_PROPERTIES,
-
-
- /**
- * If present, the converter will ignore any objects that cannot be
- * converted (many of the JDK-provided classes fall into this category,
- * because they're not bean-structured).
- */
- IGNORE_UNCONVERTIBLE_OBJECTS,
-
-
- /**
- * If present, the converter will use a setter method taking a String, in
- * preference to any other type. Default behavior is to pick the method
- * with the most restrictive type (and considering numeric types as more
- * restrictive than <code>String</code>).
- */
- PREFER_STRING_SETTER,
-
-
- /**
- * If present, the converter requires an <code>xsi:nil</code> attribute
- * on any empty nodes, and will throw if it's not present. Default is to
- * treat empty nodes as <code>null</code>.
- */
- REQUIRE_XSI_NIL,
-
-
- /**
- * If present, the converter requires an <code>xsi:type</code> attribute
- * on each element, and will throw if it's not present. Default behavior
- * uses the <code>xsi:type</code> value to choose between different setter
- * methods, but otherwise ignores it.
- */
- REQUIRE_XSI_TYPE
-}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java (from rev 99, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,235 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter.bean2xml;
+
+import java.util.EnumSet;
+
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+import net.sf.practicalxml.DomUtil;
+
+
+/**
+ * Packaging class used for XML output appenders. This class is a temporary
+ * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained
+ * classes will end up in a new package, once I figure out what the package
+ * structure should be.
+ */
+public abstract class Bean2XmlAppenders
+{
+ /**
+ * An <code>Appender</code> appends children to a single node of the
+ * output tree. The driver is responsible for creating new appenders
+ * for each compound element, including the root, and providing those
+ * appenders with options to control output generation.
+ */
+ public interface Appender
+ {
+ /**
+ * Appends a value element to the current element. Value elements have
+ * associated text, but no other children.
+ *
+ * @param name Name to be associated with the node.
+ * @param type Type to be associated with the node; may or may
+ * not be written to the output, depending on the
+ * appender's options.
+ * @param value The node's value. May be <code>null</code>, in
+ * which case the appender decides whether or not
+ * to actually append the node.
+ *
+ * @return The appended element. This is a convenience for subclasses,
+ * which may want to set additional attributes after their
+ * super has done the work of appending the element.
+ * @throws ConversionException if unable to append the node.
+ */
+ public Element appendValue(String name, String type, String value);
+
+
+ /**
+ * Appends a container element to the current element. Container
+ * elements have other elements as children, and may have a type,
+ * but do not have an associated value.
+ */
+ public Element appendContainer(String name, String type);
+ }
+
+
+ /**
+ * Base class for XML appenders, providing helper methods for subclasses.
+ */
+ private static abstract class AbstractAppender
+ implements Appender
+ {
+ private EnumSet<Bean2XmlOptions> _options;
+
+ public AbstractAppender(EnumSet<Bean2XmlOptions> options)
+ {
+ _options = options;
+ }
+
+ protected boolean isOptionSet(Bean2XmlOptions option)
+ {
+ return _options.contains(option);
+ }
+
+ protected boolean shouldSkip(Object value)
+ {
+ return (value == null) && !_options.contains(Bean2XmlOptions.XSI_NIL);
+ }
+
+ protected void setType(Element elem, String type)
+ {
+ if (isOptionSet(Bean2XmlOptions.XSI_TYPE))
+ elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type);
+ }
+
+ protected void setValue(Element elem, String value)
+ {
+ if (value != null)
+ DomUtil.setText(elem, value);
+ else if (isOptionSet(Bean2XmlOptions.XSI_NIL))
+ elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true");
+ }
+ }
+
+
+ /**
+ * Basic appender, which appends new elements to a parent.
+ */
+ public static class BasicAppender
+ extends AbstractAppender
+ {
+ private Element _parent;
+
+ public BasicAppender(Element parent, EnumSet<Bean2XmlOptions> options)
+ {
+ super(options);
+ _parent = parent;
+ }
+
+ public Element appendValue(String name, String type, String value)
+ {
+ if (shouldSkip(value))
+ return null;
+
+ Element child = DomUtil.appendChildInheritNamespace(_parent, name);
+ setType(child, type);
+ setValue(child, value);
+ return child;
+ }
+
+ public Element appendContainer(String name, String type)
+ {
+ Element child = DomUtil.appendChildInheritNamespace(_parent, name);
+ setType(child, type);
+ return child;
+ }
+ }
+
+
+ /**
+ * Appender for children of an indexed/iterated item (array, list, or set).
+ * Each element will have an incremented <code>index</code> attribute that
+ * indicates the position of the element within the iteration.
+ */
+ public static class IndexedAppender
+ extends BasicAppender
+ {
+ int _index = 0;
+
+ public IndexedAppender(Element parent, EnumSet<Bean2XmlOptions> options)
+ {
+ super(parent, options);
+ }
+
+
+ @Override
+ public Element appendValue(String name, String type, String value)
+ {
+ Element child = super.appendValue(name, type, value);
+ if (child != null)
+ child.setAttribute("index", String.valueOf(_index++));
+ return child;
+ }
+ }
+
+
+ /**
+ * Appender for children of a <code>Map</code>. Depending on options,
+ * will either create children named after the key, or a generic "data"
+ * child with the key as an attribute.
+ */
+ public static class MapAppender
+ extends BasicAppender
+ {
+ public MapAppender(Element parent, EnumSet<Bean2XmlOptions> options)
+ {
+ super(parent, options);
+ }
+
+
+ @Override
+ public Element appendValue(String name, String type, String value)
+ {
+ Element child = null;
+ if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS))
+ {
+ child = super.appendValue(name, type, value);
+ }
+ else
+ {
+ child = super.appendValue("data", type, value);
+ if (child != null)
+ child.setAttribute("key", name);
+ }
+ return child;
+ }
+ }
+
+
+ /**
+ * An appender that sets values directly on the "parent" element. Used for
+ * the conversion root element.
+ */
+ public static class DirectAppender
+ extends AbstractAppender
+ {
+ private Element _elem;
+
+ public DirectAppender(Element elem, EnumSet<Bean2XmlOptions> options)
+ {
+ super(options);
+ _elem = elem;
+ }
+
+ public Element appendValue(String name, String type, String value)
+ {
+ if (!shouldSkip(value))
+ {
+ setType(_elem, type);
+ setValue(_elem, value);
+ }
+ return _elem;
+ }
+
+ public Element appendContainer(String name, String type)
+ {
+ setType(_elem, type);
+ return _elem;
+ }
+ }
+}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java (from rev 99, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,232 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter.bean2xml;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+
+import org.w3c.dom.Element;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.converter.ConversionException;
+import net.sf.practicalxml.converter.PrimitiveConversionHelper;
+import net.sf.practicalxml.converter.bean2xml.Bean2XmlAppenders.*;
+
+
+/**
+ * Driver class for converting bean data to an XML representation. In normal
+ * usage, an instance of this class is constructed with the desired conversion
+ * options, then {@link #convert} is called with the compound object to be
+ * converted. The driver may be reused for multiple conversions, and is
+ * thread-safe.
+ */
+public class Bean2XmlDriver
+{
+ private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class);
+ private PrimitiveConversionHelper _primitiveHelper;
+
+ public Bean2XmlDriver(Bean2XmlOptions... options)
+ {
+ for (Bean2XmlOptions option : options)
+ _options.add(option);
+ _primitiveHelper = new PrimitiveConversionHelper(shouldUseXsdFormatting());
+ }
+
+
+//----------------------------------------------------------------------------
+// Public methods
+//----------------------------------------------------------------------------
+
+ /**
+ * Creates an XML DOM with the specified root element name, and fills it
+ * by introspecting the passed object (see {@link #introspect} for
+ * treatment of simple objects).
+ */
+ public Element convert(Object obj, String rootName)
+ {
+ return convert(obj, null, rootName);
+ }
+
+
+ /**
+ * Creates an XML DOM with the specified root element name and namespace
+ * URI, and fills it by introspecting the passed object (see {@link
+ * #introspect} for treatment of simple objects). The namespace URI (and
+ * prefix, if provided) will be used for all child elements.
+ */
+ public Element convert(Object obj, String nsUri, String rootName)
+ {
+ Element root = DomUtil.newDocument(nsUri, rootName);
+ convert(obj, "", new DirectAppender(root, _options));
+ return root;
+ }
+
+
+ /**
+ * Introspects the passed object, and appends its contents to the output.
+ * This method is public to allow non-standard conversions, such as
+ * appending into an existing tree, or (in the future, if we introduce an
+ * appender factory) producing non-XML output.
+ */
+ public void convert(Object obj, String name, Appender appender)
+ {
+ // these methods have side effects!
+ // empty blocks and comments are there to keep Eclipse happy
+ if (tryToConvertAsPrimitiveOrNull(obj, null, name, appender))
+ { /* it was converted */ }
+ else if (tryToConvertAsArray(obj, name, appender))
+ { /* it was converted */ }
+ else if (tryToConvertAsMap(obj, name, appender))
+ { /* it was converted */ }
+ else if (tryToConvertAsCollection(obj, name, appender))
+ { /* it was converted */ }
+ else if (tryToConvertAsBean(obj, name, appender))
+ { /* it was converted */ }
+ else
+ throw new ConversionException("unable to convert: " + obj.getClass().getName());
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ private boolean shouldUseXsdFormatting()
+ {
+ return _options.contains(Bean2XmlOptions.XSD_FORMAT)
+ || _options.contains(Bean2XmlOptions.XSI_TYPE);
+ }
+
+
+ private String getJavaXsiType(Object obj)
+ {
+ return "java:" + obj.getClass().getName();
+ }
+
+
+ private boolean tryToConvertAsPrimitiveOrNull(
+ Object obj, Class<?> klass, String name, Appender appender)
+ {
+ if (obj != null)
+ klass = obj.getClass();
+
+ String objType = _primitiveHelper.getXsdType(klass);
+ if ((obj == null) || (objType != null))
+ {
+ appender.appendValue(name, objType, _primitiveHelper.stringify(obj));
+ return true;
+ }
+
+ return false;
+ }
+
+
+ private boolean tryToConvertAsArray(Object array, String name, Appender appender)
+ {
+ if (!array.getClass().isArray())
+ return false;
+
+ Element parent = appender.appendContainer(name, getJavaXsiType(array));
+ Appender childAppender = new IndexedAppender(parent, _options);
+ int length = Array.getLength(array);
+ for (int idx = 0 ; idx < length ; idx++)
+ {
+ Object value = Array.get(array, idx);
+ convert(value, "data", childAppender);
+ }
+ return true;
+ }
+
+
+ private boolean tryToConvertAsMap(Object obj, String name, Appender appender)
+ {
+ if (!(obj instanceof Map))
+ return false;
+
+ Element parent = appender.appendContainer(name, getJavaXsiType(obj));
+ Appender childAppender = new MapAppender(parent, _options);
+ for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet())
+ {
+ convert(entry.getValue(), String.valueOf(entry.getKey()), childAppender);
+ }
+ return true;
+ }
+
+
+ private boolean tryToConvertAsCollection(Object obj, String name, Appender appender)
+ {
+ if (!(obj instanceof Collection))
+ return false;
+
+ Element parent = appender.appendContainer(name, getJavaXsiType(obj));
+ Appender childAppender = new IndexedAppender(parent, _options);
+ for (Object value : (Collection<?>)obj)
+ {
+ convert(value, "data", childAppender);
+ }
+ return true;
+ }
+
+
+ private boolean tryToConvertAsBean(Object bean, String name, Appender appender)
+ {
+ Element parent = appender.appendContainer(name, getJavaXsiType(bean));
+ Appender childAppender = new BasicAppender(parent, _options);
+ try
+ {
+ BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class);
+ PropertyDescriptor[] props = info.getPropertyDescriptors();
+ for (int ii = 0 ; ii < props.length ; ii++)
+ convertBeanProperty(bean, props[ii], childAppender);
+ }
+ catch (IntrospectionException ee)
+ {
+ throw new ConversionException("introspection failure", ee);
+ }
+ return true;
+ }
+
+
+ private void convertBeanProperty(
+ Object bean, PropertyDescriptor propDesc, Appender appender)
+ {
+ String name = propDesc.getName();
+ Class<?> type = propDesc.getPropertyType();
+ Object value;
+ try
+ {
+ Method getter = propDesc.getReadMethod();
+ if (getter == null)
+ return;
+ value = getter.invoke(bean);
+ }
+ catch (Exception ee)
+ {
+ throw new ConversionException("unable to retrieve bean value", ee);
+ }
+
+ if (value == null)
+ tryToConvertAsPrimitiveOrNull(value, type, name, appender);
+ else
+ convert(value, name, appender);
+ }
+}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java (from rev 93, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,55 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter.bean2xml;
+
+
+/**
+ * Options used by {@link Bean2XmlHandler} to control the structure of the
+ * DOM tree.
+ */
+public enum Bean2XmlOptions
+{
+ /**
+ * Outputs values using formats defined by XML Schema, rather than Java's
+ * <code>String.valueOf()</code> method. Note that these formats are not
+ * flagged in the element, so sender and receiver will have to agree on
+ * the format.
+ */
+ XSD_FORMAT,
+
+ /**
+ * Will add an <code>xsi:type</code> attribute to each element. For values
+ * covered by the XML Schema simple types, this attribute's value will be
+ * "<code>xsd:XXX</code>", where XXX is the XSD type name. For complex
+ * types, this attribute's value will be "<code>java:XXX</code>", where
+ * XXX is the fully-qualified classname.
+ * <p>
+ * <em>This option implies {@link #XSD_FORMAT} for simple types</em>.
+ */
+ XSI_TYPE,
+
+ /**
+ * Report null values using the <code>xsi:nil="true"</code> attribute. If
+ * not present, null values are ignored, and not added to DOM tree.
+ */
+ XSI_NIL,
+
+ /**
+ * Output maps in an "introspected" format, where the name of each item
+ * is the map key (rather than "data"), and the "key" attribute is omitted.
+ * If any key is not a valid XML identifier, the converter will throw.
+ */
+ INTROSPECT_MAPS
+}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java (from rev 96, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,35 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter.xml2bean;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Driver class for converting an XML DOM into a Java bean, using a {@link
+ * Xml2BeanHandler} to manage data conversion.
+ */
+public class Xml2BeanDriver
+{
+ /**
+ * Fills a bean-style object from an XML element. For each child of the
+ * passed element, tries to find a property with the same name, invokes
+ * the appropriate conversion handler method, and sets the property from
+ * the result.
+ */
+ public void dispatch(Element elem, Object bean)
+ {
+ }
+}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java (from rev 98, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,194 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter.xml2bean;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.XmlException;
+import net.sf.practicalxml.XmlUtil;
+import net.sf.practicalxml.converter.ConversionException;
+import net.sf.practicalxml.converter.PrimitiveConversionHelper;
+import net.sf.practicalxml.internal.StringUtils;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code>
+ * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there
+ * will only be one instance of this object created during conversion; all
+ * intermediate data can be held on the stack.
+ */
+public class Xml2BeanHandler
+{
+ private EnumSet<Xml2BeanOptions> _options;
+ private PrimitiveConversionHelper _primitiveHelper;
+
+
+ /**
+ * Public constructor, allowing various options specifications.
+ */
+ public Xml2BeanHandler(Xml2BeanOptions... options)
+ {
+ _options = EnumSet.noneOf(Xml2BeanOptions.class);
+ for (Xml2BeanOptions option : options)
+ _options.add(option);
+
+ _primitiveHelper = new PrimitiveConversionHelper(true);
+ }
+
+
+//----------------------------------------------------------------------------
+// Public Methods
+//----------------------------------------------------------------------------
+
+ public Boolean convertBoolean(Element elem)
+ {
+ return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class);
+ }
+
+
+ public Byte convertByte(Element elem)
+ {
+ return (Byte)_primitiveHelper.parse(getText(elem), Byte.class);
+ }
+
+
+ public Character convertCharacter(Element elem)
+ {
+ return (Character)_primitiveHelper.parse(getText(elem), Character.class);
+ }
+
+
+ public Date convertDate(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Double convertDouble(Element elem)
+ {
+ return (Double)_primitiveHelper.parse(getText(elem), Double.class);
+ }
+
+
+ public Float convertFloat(Element elem)
+ {
+ return (Float)_primitiveHelper.parse(getText(elem), Float.class);
+ }
+
+
+ public Integer convertInteger(Element elem)
+ {
+ return (Integer)_primitiveHelper.parse(getText(elem), Integer.class);
+ }
+
+
+ public Long convertLong(Element elem)
+ {
+ return (Long)_primitiveHelper.parse(getText(elem), Long.class);
+ }
+
+
+ public Number convertNumber(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Short convertShort(Element elem)
+ {
+ return (Short)_primitiveHelper.parse(getText(elem), Short.class);
+ }
+
+
+ public String convertString(Element elem)
+ {
+ return (String)_primitiveHelper.parse(getText(elem), String.class);
+ }
+
+
+ public List<?> convertList(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Set<?> convertSet(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Map<?,?> convertMap(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Object convertObject(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Object[] convertObjectArray(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the text from a passed element, applying any low-level options
+ * along the way.
+ */
+ private String getText(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text))
+ text = null;
+ validateXsiNil(elem, text);
+ return text;
+ }
+
+
+ /**
+ * Checks for elements that require <code>xsi:nil</code>, and throws if missing.
+ */
+ private void validateXsiNil(Element elem, String text)
+ {
+ if (text != null)
+ return;
+ if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL))
+ return;
+
+ String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
+ if ((attr == null) || !attr.equals("true"))
+ throw new ConversionException("empty element without required xsi:nil");
+ }
+
+}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java (from rev 98, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java 2009-08-14 18:41:47 UTC (rev 100)
@@ -0,0 +1,71 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 CONDITI...
[truncated message content] |
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-12 20:35:45
|
Revision: 98
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=98&view=rev
Author: kdgregory
Date: 2009-08-12 20:35:22 +0000 (Wed, 12 Aug 2009)
Log Message:
-----------
checkpoint - flesh out parsing options, move primitive conversion to own class
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlHandler.java 2009-08-10 22:30:50 UTC (rev 97)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlHandler.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -17,6 +17,7 @@
import net.sf.practicalxml.DomUtil;
import net.sf.practicalxml.XmlUtil;
+import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.EnumSet;
@@ -46,6 +47,7 @@
{
private EnumSet<Bean2XmlOptions> _options;
private Appender _appender;
+ private PrimitiveConversionHelper _primitiveHelper;
/**
@@ -54,10 +56,13 @@
*/
public Bean2XmlHandler(Element appendTo, Bean2XmlOptions... options)
{
- _appender = new Appender(appendTo);
_options = EnumSet.noneOf(Bean2XmlOptions.class);
for (Bean2XmlOptions option : options)
_options.add(option);
+
+ _appender = new Appender(appendTo);
+
+ _primitiveHelper = new PrimitiveConversionHelper(shouldFormatAsXsd());
}
@@ -68,6 +73,7 @@
{
_appender = appender;
_options = parent._options;
+ _primitiveHelper = parent._primitiveHelper;
}
@@ -77,83 +83,69 @@
public void convert(String name, Boolean value)
{
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = value.booleanValue() ? "true" : "false";
-
- _appender.append(name, "xsd:boolean", formatted);
+ appendPrimitive(name, Boolean.class, value);
}
public void convert(String name, Byte value)
{
- _appender.append(name, "xsd:byte", value);
+ appendPrimitive(name, Byte.class, value);
}
public void convert(String name, Character value)
{
- _appender.append(name, "xsd:string", value);
+ appendPrimitive(name, Character.class, value);
}
public void convert(String name, Date value)
{
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDatetime(value);
-
- _appender.append(name, "xsd:dateTime", formatted);
+ appendPrimitive(name, Date.class, value);
}
public void convert(String name, Double value)
{
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDecimal(value);
-
- _appender.append(name, "xsd:decimal", formatted);
+ appendPrimitive(name, Double.class, value);
}
public void convert(String name, Float value)
{
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDecimal(value);
-
- _appender.append(name, "xsd:decimal", formatted);
+ appendPrimitive(name, Float.class, value);
}
public void convert(String name, Integer value)
{
- _appender.append(name, "xsd:int", value);
+ appendPrimitive(name, Integer.class, value);
}
public void convert(String name, Long value)
{
- _appender.append(name, "xsd:long", value);
+ appendPrimitive(name, Long.class, value);
}
+ // FIXME - passes tests but not pretty ...
+ // the multitude of convert methods will go away, however
public void convert(String name, Number value)
{
- _appender.append(name, "xsd:decimal", value);
+ appendPrimitive(name, BigDecimal.class, value);
}
public void convert(String name, Short value)
{
- _appender.append(name, "xsd:short", value);
+ appendPrimitive(name, Short.class, value);
}
public void convert(String name, String value)
{
- _appender.append(name, "xsd:string", value);
+ appendPrimitive(name, String.class, value);
}
@@ -229,6 +221,19 @@
/**
+ * Common code for primitive objects.
+ */
+ public void appendPrimitive(String name, Class<?> klass, Object value)
+ {
+ String xsdType = _primitiveHelper.getXsdType(klass);
+ if (xsdType == null)
+ throw new ConversionException("internal error: " + klass.getName()
+ + " passed as primitive");
+ _appender.append(name, xsdType, _primitiveHelper.stringify(value));
+ }
+
+
+ /**
* Common code for sequenced objects -- arrays, lists, and sets.
*/
private void appendSequence(Element parent, Iterator<?> itx, boolean isIndexed)
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/PrimitiveConversionHelper.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -0,0 +1,446 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.practicalxml.XmlUtil;
+
+
+/**
+ * Responsible for converting "primitive" types -- those with unambiguous
+ * string representations -- to/from such a representation.
+ */
+public class PrimitiveConversionHelper
+{
+ // this is not static because the helpers are inner classes
+ private Map<Class<?>,ConversionHandler<?>> _helpers
+ = new HashMap<Class<?>,ConversionHandler<?>>();
+ {
+ _helpers.put(String.class, new StringConversionHandler());
+ _helpers.put(Character.class, new CharacterConversionHandler());
+ _helpers.put(Boolean.class, new BooleanConversionHandler());
+ _helpers.put(Byte.class, new ByteConversionHandler());
+ _helpers.put(Short.class, new ShortConversionHandler());
+ _helpers.put(Integer.class, new IntegerConversionHandler());
+ _helpers.put(Long.class, new LongConversionHandler());
+ _helpers.put(Float.class, new FloatConversionHandler());
+ _helpers.put(Double.class, new DoubleConversionHandler());
+ _helpers.put(BigInteger.class, new BigIntegerConversionHandler());
+ _helpers.put(BigDecimal.class, new BigDecimalConversionHandler());
+ _helpers.put(Date.class, new DateConversionHandler());
+ }
+
+ private boolean _useXsdFormatting;
+
+
+ /**
+ * Default constructor, which uses Java formatting.
+ */
+ public PrimitiveConversionHelper()
+ {
+ // nothing to see here
+ }
+
+
+ /**
+ * Constructor that allows selection of Java or XSD formatting.
+ */
+ public PrimitiveConversionHelper(boolean useXsdFormatting)
+ {
+ _useXsdFormatting = useXsdFormatting;
+ }
+
+
+//----------------------------------------------------------------------------
+// Public Methods
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the XSD type name to use for stringified objects of the
+ * specified class, <code>null</code> if this converter can't convert
+ * instances of the class.
+ */
+ public String getXsdType(Class<?> klass)
+ {
+ ConversionHandler<?> helper = _helpers.get(klass);
+ return (helper == null) ? null : helper.getXsdType();
+ }
+
+
+ /**
+ * Converts the passed object into its string representation, according
+ * to the options currently in effect. Passing <code>null</code> will
+ * return <code>null</code>. Throws {@link ConversionException} if
+ * unable to convert the passed object.
+ */
+ public String stringify(Object obj)
+ {
+ if (obj == null)
+ return null;
+
+ try
+ {
+ return getHelper(obj.getClass()).stringify(obj);
+ }
+ catch (Exception ee)
+ {
+ if (ee instanceof ConversionException)
+ throw (ConversionException)ee;
+ throw new ConversionException("unable to convert: " + obj, ee);
+ }
+ }
+
+
+ /**
+ * Parses the passed string into an object of the desired class. Passing
+ * <code>null</code> will return <code>null</code>, passing an empty
+ * string will typically throw a {@link ConversionException}.
+ */
+ public Object parse(String str, Class<?> klass)
+ {
+ if (str == null)
+ return null;
+
+ try
+ {
+ return getHelper(klass).parse(str);
+ }
+ catch (Exception ee)
+ {
+ if (ee instanceof ConversionException)
+ throw (ConversionException)ee;
+ throw new ConversionException("unable to parse: " + str, ee);
+ }
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ /**
+ * Returns the appropriate conversion helper or throws.
+ */
+ @SuppressWarnings(value="unchecked")
+ private ConversionHandler getHelper(Class<?> klass)
+ {
+ ConversionHandler<?> helper = _helpers.get(klass);
+ if (helper == null)
+ throw new ConversionException("unable to get helper: " + klass.getName());
+ return helper;
+ }
+
+
+ /**
+ * Each primitive class has its own conversion handler that is responsible
+ * for converting to/from a string representation. Handlers are guaranteed
+ * to receive non-null objects/strings.
+ * <p>
+ * This interface is parameterized so that the compiler will generate
+ * bridge methods for implementation classes. Elsewhere, we don't care
+ * about parameterization, so wildcard or drop it (see {@link #getHelper}).
+ * <p>
+ * Implementation classes are expected to be inner classes, so that they
+ * have access to configuration information (such as formatting rules).
+ * <p>
+ * Implementation classes are permitted to throw any exception; caller is
+ * expected to catch them and translate to a {@link ConversionException}.
+ */
+ private static interface ConversionHandler<T>
+ {
+ public String getXsdType();
+ public String stringify(T obj) throws Exception;
+ public T parse(String str) throws Exception;
+ }
+
+
+ private class StringConversionHandler
+ implements ConversionHandler<String>
+ {
+ public String getXsdType()
+ {
+ return "xsd:string";
+ }
+
+ public String stringify(String obj)
+ {
+ return String.valueOf(obj);
+ }
+
+ public String parse(String str)
+ {
+ return str;
+ }
+ }
+
+
+ private class CharacterConversionHandler
+ implements ConversionHandler<Character>
+ {
+ private final Character NUL = Character.valueOf('\0');
+
+ public String getXsdType()
+ {
+ return "xsd:string";
+ }
+
+ public String stringify(Character obj)
+ {
+ if (obj.equals(NUL))
+ return "";
+ return obj.toString();
+ }
+
+ public Character parse(String str)
+ {
+ if (str.length() == 0)
+ return NUL;
+ if (str.length() > 1)
+ throw new ConversionException(
+ "attempted to convert multi-character string: \"" + str + "\"");
+ return Character.valueOf(str.charAt(0));
+ }
+ }
+
+
+ private class BooleanConversionHandler
+ implements ConversionHandler<Boolean>
+ {
+ public String getXsdType()
+ {
+ return "xsd:boolean";
+ }
+
+ public String stringify(Boolean obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdBoolean(obj.booleanValue())
+ : obj.toString();
+ }
+
+ public Boolean parse(String str)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.parseXsdBoolean(str)
+ : Boolean.parseBoolean(str);
+ }
+ }
+
+
+ private class ByteConversionHandler
+ implements ConversionHandler<Byte>
+ {
+ public String getXsdType()
+ {
+ return "xsd:byte";
+ }
+
+ public String stringify(Byte obj)
+ {
+ return obj.toString();
+ }
+
+ public Byte parse(String str)
+ {
+ return Byte.valueOf(str.trim());
+ }
+ }
+
+
+ private class ShortConversionHandler
+ implements ConversionHandler<Short>
+ {
+ public String getXsdType()
+ {
+ return "xsd:short";
+ }
+
+ public String stringify(Short obj)
+ {
+ return obj.toString();
+ }
+
+ public Short parse(String str)
+ {
+ return Short.valueOf(str.trim());
+ }
+ }
+
+
+ private class IntegerConversionHandler
+ implements ConversionHandler<Integer>
+ {
+ public String getXsdType()
+ {
+ return "xsd:int";
+ }
+
+ public String stringify(Integer obj)
+ {
+ return obj.toString();
+ }
+
+ public Integer parse(String str)
+ {
+ return Integer.valueOf(str.trim());
+ }
+ }
+
+
+ private class LongConversionHandler
+ implements ConversionHandler<Long>
+ {
+ public String getXsdType()
+ {
+ return "xsd:long";
+ }
+
+ public String stringify(Long obj)
+ {
+ return obj.toString();
+ }
+
+ public Long parse(String str)
+ {
+ return Long.valueOf(str.trim());
+ }
+ }
+
+
+ private class FloatConversionHandler
+ implements ConversionHandler<Float>
+ {
+ public String getXsdType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(Float obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDecimal(obj)
+ : obj.toString();
+ }
+
+ public Float parse(String str)
+ {
+ return Float.valueOf(str.trim());
+ }
+ }
+
+
+ private class DoubleConversionHandler
+ implements ConversionHandler<Double>
+ {
+ public String getXsdType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(Double obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDecimal(obj)
+ : obj.toString();
+ }
+
+ public Double parse(String str)
+ {
+ return Double.valueOf(str.trim());
+ }
+ }
+
+
+ private class BigIntegerConversionHandler
+ implements ConversionHandler<BigInteger>
+ {
+ public String getXsdType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(BigInteger obj)
+ {
+ return obj.toString();
+ }
+
+ public BigInteger parse(String str)
+ {
+ return new BigInteger(str.trim());
+ }
+ }
+
+
+ private class BigDecimalConversionHandler
+ implements ConversionHandler<BigDecimal>
+ {
+ public String getXsdType()
+ {
+ return "xsd:decimal";
+ }
+
+ public String stringify(BigDecimal obj)
+ {
+ return obj.toString();
+ }
+
+ public BigDecimal parse(String str)
+ {
+ return new BigDecimal(str.trim());
+ }
+ }
+
+
+ private class DateConversionHandler
+ implements ConversionHandler<Date>
+ {
+ // format as specified by Date.toString() JavaDoc
+ private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
+
+ public String getXsdType()
+ {
+ return "xsd:dateTime";
+ }
+
+ public String stringify(Date obj)
+ {
+ return _useXsdFormatting
+ ? XmlUtil.formatXsdDatetime(obj)
+ : obj.toString();
+ }
+
+ public Date parse(String str)
+ throws ParseException
+ {
+ if (_useXsdFormatting)
+ return XmlUtil.parseXsdDatetime(str);
+ else
+ {
+ synchronized (_defaultFormat)
+ {
+ return _defaultFormat.parse(str);
+ }
+ }
+ }
+ }
+}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-10 22:30:50 UTC (rev 97)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -15,7 +15,9 @@
package net.sf.practicalxml.converter;
import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.XmlException;
import net.sf.practicalxml.XmlUtil;
+import net.sf.practicalxml.internal.StringUtils;
import java.util.Arrays;
import java.util.Date;
@@ -38,6 +40,7 @@
public class Xml2BeanHandler
{
private EnumSet<Xml2BeanOptions> _options;
+ private PrimitiveConversionHelper _primitiveHelper;
/**
@@ -48,6 +51,8 @@
_options = EnumSet.noneOf(Xml2BeanOptions.class);
for (Xml2BeanOptions option : options)
_options.add(option);
+
+ _primitiveHelper = new PrimitiveConversionHelper(true);
}
@@ -55,27 +60,21 @@
// Public Methods
//----------------------------------------------------------------------------
-
public Boolean convertBoolean(Element elem)
{
- String text = DomUtil.getText(elem);
- return Boolean.valueOf(XmlUtil.parseXsdBoolean(text));
+ return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class);
}
public Byte convertByte(Element elem)
{
- String text = DomUtil.getText(elem);
- return Byte.valueOf(text);
+ return (Byte)_primitiveHelper.parse(getText(elem), Byte.class);
}
public Character convertCharacter(Element elem)
{
- String text = DomUtil.getText(elem);
- if (text.length() == 0)
- return '\0';
- return Character.valueOf(text.charAt(0));
+ return (Character)_primitiveHelper.parse(getText(elem), Character.class);
}
@@ -87,29 +86,25 @@
public Double convertDouble(Element elem)
{
- String text = DomUtil.getText(elem);
- return Double.valueOf(text);
+ return (Double)_primitiveHelper.parse(getText(elem), Double.class);
}
public Float convertFloat(Element elem)
{
- String text = DomUtil.getText(elem);
- return Float.valueOf(text);
+ return (Float)_primitiveHelper.parse(getText(elem), Float.class);
}
public Integer convertInteger(Element elem)
{
- String text = DomUtil.getText(elem);
- return Integer.valueOf(text);
+ return (Integer)_primitiveHelper.parse(getText(elem), Integer.class);
}
public Long convertLong(Element elem)
{
- String text = DomUtil.getText(elem);
- return Long.valueOf(text);
+ return (Long)_primitiveHelper.parse(getText(elem), Long.class);
}
@@ -121,15 +116,13 @@
public Short convertShort(Element elem)
{
- String text = DomUtil.getText(elem);
- return Short.valueOf(text);
+ return (Short)_primitiveHelper.parse(getText(elem), Short.class);
}
public String convertString(Element elem)
{
- String text = DomUtil.getText(elem);
- return text;
+ return (String)_primitiveHelper.parse(getText(elem), String.class);
}
@@ -167,5 +160,33 @@
// Internals
//----------------------------------------------------------------------------
+ /**
+ * Returns the text from a passed element, applying any low-level options
+ * along the way.
+ */
+ private String getText(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text))
+ text = null;
+ validateXsiNil(elem, text);
+ return text;
+ }
+
+ /**
+ * Checks for elements that require <code>xsi:nil</code>, and throws if missing.
+ */
+ private void validateXsiNil(Element elem, String text)
+ {
+ if (text != null)
+ return;
+ if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL))
+ return;
+
+ String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
+ if ((attr == null) || !attr.equals("true"))
+ throw new ConversionException("empty element without required xsi:nil");
+ }
+
}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-10 22:30:50 UTC (rev 97)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -22,6 +22,14 @@
public enum Xml2BeanOptions
{
/**
+ * If present, the converter will treat all elements with empty text nodes
+ * as if they were empty elements -- in other words, <code>null</code>.
+ * Note that this flag will interact with <code>REQUIRE_XSI_NIL</code>.
+ */
+ CONVERT_BLANK_AS_NULL,
+
+
+ /**
* If present, the converter ignores elements that don't correspond to
* settable properties of the bean.
*/
@@ -37,19 +45,27 @@
/**
+ * If present, the converter will use a setter method taking a String, in
+ * preference to any other type. Default behavior is to pick the method
+ * with the most restrictive type (and considering numeric types as more
+ * restrictive than <code>String</code>).
+ */
+ PREFER_STRING_SETTER,
+
+
+ /**
+ * If present, the converter requires an <code>xsi:nil</code> attribute
+ * on any empty nodes, and will throw if it's not present. Default is to
+ * treat empty nodes as <code>null</code>.
+ */
+ REQUIRE_XSI_NIL,
+
+
+ /**
* If present, the converter requires an <code>xsi:type</code> attribute
* on each element, and will throw if it's not present. Default behavior
* uses the <code>xsi:type</code> value to choose between different setter
* methods, but otherwise ignores it.
*/
- REQUIRE_XSI_TYPE,
-
-
- /**
- * If present, the converter will use a setter method taking a String, in
- * preference to any other type. Default behavior is to pick the method
- * with the most restrictive type (and considering numeric types as more
- * restrictive than <code>String</code>).
- */
- PREFER_STRING_SETTER
+ REQUIRE_XSI_TYPE
}
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestPrimitiveConversionHelper.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -0,0 +1,510 @@
+// Copyright (c) Keith D Gregory, all rights reserved
+package net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+public class TestPrimitiveConversionHelper extends TestCase
+{
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ private void assertFailsConversionToObject(
+ String message,
+ PrimitiveConversionHelper helper,
+ String str,
+ Class<?> klass)
+ {
+ try
+ {
+ helper.parse(str, klass);
+ fail(message);
+ }
+ catch (ConversionException ee)
+ {
+ // success!
+ }
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ public void testUnknownClass() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertNull(helper.getXsdType(Class.class));
+ }
+
+
+ public void testConvertNull() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertNull(helper.stringify(null));
+ assertNull(helper.parse(null, Object.class));
+ }
+
+
+ public void testConvertString() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:string", helper.getXsdType(String.class));
+
+ assertEquals("foo", helper.stringify("foo"));
+ assertEquals("foo", helper.parse("foo", String.class));
+
+ assertEquals("", helper.stringify(""));
+ assertEquals("", helper.parse("", String.class));
+ }
+
+
+ public void testConvertCharacter() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:string", helper.getXsdType(Character.class));
+
+ Character simple = Character.valueOf('A');
+ assertEquals("A", helper.stringify(simple));
+ assertEquals(simple, helper.parse("A", Character.class));
+
+ Character nul = Character.valueOf('\0');
+ assertEquals("", helper.stringify(nul));
+ assertEquals(nul, helper.parse("", Character.class));
+
+ assertFailsConversionToObject(
+ "converted multi-character string",
+ helper, "ix", Character.class);
+ }
+
+
+ public void testConvertBooleanDefault() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ // default boolean conversion is compatible with XSD type def
+ assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
+
+ String sTrue = Boolean.TRUE.toString();
+ assertEquals(sTrue, helper.stringify(Boolean.TRUE));
+ assertEquals(Boolean.TRUE, helper.parse(sTrue, Boolean.class));
+
+ String sFalse = Boolean.FALSE.toString();
+ assertEquals(sFalse, helper.stringify(Boolean.FALSE));
+ assertEquals(Boolean.FALSE, helper.parse(sFalse, Boolean.class));
+
+ assertEquals(Boolean.FALSE, helper.parse("ix", Boolean.class));
+ assertEquals(Boolean.FALSE, helper.parse("", Boolean.class));
+ }
+
+
+ public void testConvertBooleanXsd() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
+
+ assertEquals("xsd:boolean", helper.getXsdType(Boolean.class));
+
+ assertEquals("true", helper.stringify(Boolean.TRUE));
+ assertEquals(Boolean.TRUE, helper.parse("true", Boolean.class));
+ assertEquals(Boolean.TRUE, helper.parse("1", Boolean.class));
+
+ assertEquals("false", helper.stringify(Boolean.FALSE));
+ assertEquals(Boolean.FALSE, helper.parse("false", Boolean.class));
+ assertEquals(Boolean.FALSE, helper.parse("0", Boolean.class));
+
+ assertFailsConversionToObject(
+ "converted multi-character string",
+ helper, "ix", Boolean.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Boolean.class);
+ }
+
+
+ public void testConvertByte() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:byte", helper.getXsdType(Byte.class));
+
+ String str1 = "123";
+ Byte val1 = Byte.valueOf((byte)123);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Byte.class));
+
+ String str2 = "-123";
+ Byte val2 = Byte.valueOf((byte)-123);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Byte.class));
+
+ String str3 = " -123 ";
+ Byte val3 = Byte.valueOf((byte)-123);
+ assertEquals(val3, helper.parse(str3, Byte.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "1234567", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "1.23", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Byte.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Byte.class);
+ }
+
+
+ public void testConvertShort() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:short", helper.getXsdType(Short.class));
+
+ String str1 = "12345";
+ Short val1 = Short.valueOf((short)12345);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Short.class));
+
+ String str2 = "-12345";
+ Short val2 = Short.valueOf((short)-12345);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Short.class));
+
+ String str3 = " -12345 ";
+ Short val3 = Short.valueOf((short)-12345);
+ assertEquals(val3, helper.parse(str3, Short.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "1234567", Short.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Short.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Short.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Short.class);
+ }
+
+
+ public void testConvertInteger() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:int", helper.getXsdType(Integer.class));
+
+ String str1 = "1234567";
+ Integer val1 = Integer.valueOf(1234567);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Integer.class));
+
+ String str2 = "-1234567";
+ Integer val2 = Integer.valueOf(-1234567);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Integer.class));
+
+ String str3 = " -1234567 ";
+ Integer val3 = Integer.valueOf(-1234567);
+ assertEquals(val3, helper.parse(str3, Integer.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "123456789012345", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Integer.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Integer.class);
+ }
+
+
+ public void testConvertLong() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:long", helper.getXsdType(Long.class));
+
+ String str1 = "1234567890";
+ Long val1 = Long.valueOf(1234567890L);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Long.class));
+
+ String str2 = "-1234567890";
+ Long val2 = Long.valueOf(-1234567890L);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Long.class));
+
+ String str3 = " -1234567890 ";
+ Long val3 = Long.valueOf(-1234567890L);
+ assertEquals(val3, helper.parse(str3, Long.class));
+
+ assertFailsConversionToObject(
+ "converted too-large value",
+ helper, "123456789012345678901234567890", Long.class);
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", Long.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Long.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Long.class);
+ }
+
+
+ public void testConvertFloatDefault() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ // default float conversion is compatible with XSD type def
+ assertEquals("xsd:decimal", helper.getXsdType(Float.class));
+
+ // note: for default-format tests, strings are generated from values
+ Float val1 = Float.valueOf(1234f);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Float.class));
+
+ Float val2 = Float.valueOf(-1234f);
+ String str2 = val2.toString();
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Float.class));
+
+ String str3 = " -1234.5 ";
+ Float val3 = Float.valueOf(-1234.5f);
+ assertEquals(val3, helper.parse(str3, Float.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Float.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Float.class);
+ }
+
+
+ public void testConvertFloatXsd() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
+
+ assertEquals("xsd:decimal", helper.getXsdType(Float.class));
+
+ String str1 = "1234.0";
+ Float val1 = Float.valueOf(1234f);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Float.class));
+
+ String str2 = "-1234.0";
+ Float val2 = Float.valueOf(-1234f);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Float.class));
+
+ String str3 = " -1234.5 ";
+ Float val3 = Float.valueOf(-1234.5f);
+ assertEquals(val3, helper.parse(str3, Float.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Float.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Float.class);
+ }
+
+
+ public void testConvertDoubleDefault() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ // default double conversion is compatible with XSD type def
+ assertEquals("xsd:decimal", helper.getXsdType(Double.class));
+
+ // note: for default-format tests, strings are generated from values
+ Double val1 = Double.valueOf(1234567890.5);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Double.class));
+
+ Double val2 = Double.valueOf(-1234567890.1);
+ String str2 = val2.toString();
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Double.class));
+
+ String str3 = " -1234.5 ";
+ Double val3 = Double.valueOf(-1234.5);
+ assertEquals(val3, helper.parse(str3, Double.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Double.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Double.class);
+ }
+
+
+ public void testConvertDoubleXsd() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
+
+ assertEquals("xsd:decimal", helper.getXsdType(Double.class));
+
+ // while for XSD-format tests, we want to verify the strings
+ String str1 = "1234567890.5";
+ Double val1 = Double.valueOf(1234567890.5);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Double.class));
+
+ String str2 = "-1234567890.1";
+ Double val2 = Double.valueOf(-1234567890.1);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, Double.class));
+
+ String str3 = " -1234.5 ";
+ Double val3 = Double.valueOf(-1234.5);
+ assertEquals(val3, helper.parse(str3, Double.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", Double.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Double.class);
+ }
+
+
+ public void testConvertBigInteger() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:decimal", helper.getXsdType(BigInteger.class));
+
+ String str1 = "123456789012345678901234567890";
+ BigInteger val1 = new BigInteger(str1);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, BigInteger.class));
+
+ String str2 = "-123456789012345678901234567890";
+ BigInteger val2 = new BigInteger(str2);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, BigInteger.class));
+
+ assertFailsConversionToObject(
+ "converted non-integer value",
+ helper, "123.45", BigInteger.class);
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", BigInteger.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", BigInteger.class);
+ }
+
+
+ public void testConvertBigDecimal() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ assertEquals("xsd:decimal", helper.getXsdType(BigDecimal.class));
+
+ String str1 = "12345678901234567890.123456789";
+ BigDecimal val1 = new BigDecimal(str1);
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, BigDecimal.class));
+
+ String str2 = "-12345678901234567890.123456789";
+ BigDecimal val2 = new BigDecimal(str2);
+ assertEquals(str2, helper.stringify(val2));
+ assertEquals(val2, helper.parse(str2, BigDecimal.class));
+
+ assertFailsConversionToObject(
+ "converted non-numeric value",
+ helper, "ix", BigDecimal.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", BigDecimal.class);
+ }
+
+
+ public void testConvertDateDefault() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper();
+
+ // default date conversion is NOT compatible with XSD type def,
+ // so this is misleading
+ assertEquals("xsd:dateTime", helper.getXsdType(Date.class));
+
+ // for default conversion, we create string from value
+ Date val1 = new Date(1247551703000L);
+ String str1 = val1.toString();
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Date.class));
+
+
+ assertFailsConversionToObject(
+ "converted non-date value",
+ helper, "ix", Date.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Date.class);
+ }
+
+
+ public void testConvertDateXsd() throws Exception
+ {
+ PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true);
+
+ assertEquals("xsd:dateTime", helper.getXsdType(Date.class));
+
+ Date val1 = new Date(1247551703000L);
+ String str1 = "2009-07-14T06:08:23";
+ assertEquals(str1, helper.stringify(val1));
+ assertEquals(val1, helper.parse(str1, Date.class));
+
+ assertFailsConversionToObject(
+ "converted non-date value",
+ helper, "ix", Date.class);
+
+ assertFailsConversionToObject(
+ "converted empty string",
+ helper, "", Date.class);
+ }
+}
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java 2009-08-10 22:30:50 UTC (rev 97)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java 2009-08-12 20:35:22 UTC (rev 98)
@@ -14,9 +14,13 @@
package net.sf.practicalxml.converter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.xml.XMLConstants;
import org.w3c.dom.Element;
-
+import net.sf.practicalxml.DomUtil;
import net.sf.practicalxml.builder.XmlBuilder;
@@ -40,16 +44,72 @@
*/
private Element createElement(String data)
{
- return XmlBuilder.element("data", XmlBuilder.text(data))
- .toDOM().getDocumentElement();
+ Element elem = XmlBuilder.element("data").toDOM().getDocumentElement();
+ if (data != null)
+ DomUtil.appendText(elem, data);
+ return elem;
}
+ /**
+ * Reflectively executes the named method, and asserts that it throws
+ * a conversion exception. This method exists to keep clutter out of
+ * the test methods.
+ */
+ private void assertConversionFailure(
+ Xml2BeanHandler handler, String methodName,
+ Element elem, String failureText)
+ throws Exception
+ {
+ Method method = handler.getClass().getMethod(methodName, Element.class);
+ try
+ {
+ method.invoke(handler, elem);
+ fail(methodName + ": " + failureText);
+ }
+ catch (InvocationTargetException ee)
+ {
+ if (ee.getCause().getClass() != ConversionException.class)
+ fail(methodName + "threw unexpected exception: " + ee.getCause());
+ // otherwise, we're successful
+ }
+ }
+
+
//----------------------------------------------------------------------------
// Test Cases
//----------------------------------------------------------------------------
+ public void testConvertString() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+ Element data1 = createElement("foo");
+ assertEquals("foo", handler.convertString(data1));
+
+ Element data2 = createElement("");
+ assertEquals("", handler.convertString(data2));
+ }
+
+
+ public void testConvertCharacter() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data1 = createElement("A");
+ assertEquals(Character.valueOf('A'), handler.convertCharacter(data1));
+
+ Element data2 = createElement("\uFB01");
+ assertEquals(Character.valueOf('\uFB01'), handler.convertCharacter(data2));
+
+ Element data3 = createElement("");
+ assertEquals(Character.valueOf('\0'), handler.convertCharacter(data3));
+
+ Element data4 = createElement("ix");
+ assertConversionFailure(handler, "convertCharacter", data4, "converted invalid value");
+ }
+
+
public void testConvertBoolean() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
@@ -66,7 +126,11 @@
Element data4 = createElement("0");
assertEquals(Boolean.FALSE, handler.convertBoolean(data4));
- // FIXME - test failure
+ Element data5 = createElement("ix");
+ assertConversionFailure(handler, "convertBoolean", data5, "converted invalid value");
+
+ Element data6 = createElement("");
+ assertConversionFailure(handler, "convertBoolean", data6, "converted empty value");
}
@@ -80,73 +144,116 @@
Element data2 = createElement("-123");
assertEquals(Byte.valueOf((byte)-123), handler.convertByte(data2));
- // FIXME - test failure
+ Element data3 = createElement("ix");
+ assertConversionFailure(handler, "convertByte", data3, "converted invalid value");
+
+ Element data4 = createElement("1234567");
+ assertConversionFailure(handler, "convertByte", data4, "converted too-large value");
+
+ Element data5 = createElement("");
+ assertConversionFailure(handler, "convertByte", data5, "converted empty value");
}
- public void testConvertCharacter() throws Exception
+ public void testConvertShort() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
- Element data1 = createElement("A");
- assertEquals(Character.valueOf('A'), handler.convertCharacter(data1));
+ Element data1 = createElement("12345");
+ assertEquals(Short.valueOf((short)12345), handler.convertShort(data1));
- Element data2 = createElement("\uFB01");
- assertEquals(Character.valueOf('\uFB01'), handler.convertCharacter(data2));
+ Element data2 = createElement("-12345");
+ assertEquals(Short.valueOf((short)-12345), handler.convertShort(data2));
- Element data3 = createElement("");
- assertEquals(Character.valueOf('\0'), handler.convertCharacter(data3));
+ Element data3 = createElement("ix");
+ assertConversionFailure(handler, "convertShort", data3, "converted non-numeric value");
- // FIXME - test failure -- multi-character?
- }
+ Element data4 = createElement("1234567");
+ assertConversionFailure(handler, "convertShort", data4, "converted too-large value");
+ Element data5 = createElement("123.45");
+ assertConversionFailure(handler, "convertShort", data5, "converted non-integer value");
-// public void testConvertDate() throws Exception
-// {
-// }
+ Element data6 = createElement("");
+ assertConversionFailure(handler, "convertShort", data6, "converted empty value");
+ }
- public void testConvertDouble() throws Exception
+ public void testConvertInteger() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
- Element data = createElement("1234567890.125");
- assertEquals(Double.valueOf(1234567890.125), handler.convertDouble(data));
+ Element data1 = createElement("123456789");
+ assertEquals(Integer.valueOf(123456789), handler.convertInteger(data1));
- // FIXME - test failure
+ Element data2 = createElement("-123456789");
+ assertEquals(Integer.valueOf(-123456789), handler.convertInteger(data2));
+
+ Element data3 = createElement("ix");
+ assertConversionFailure(handler, "convertInteger", data3, "converted non-numeric value");
+
+ Element data4 = createElement("123456789012345");
+ assertConversionFailure(handler, "convertInteger", data4, "converted too-large value");
+
+ Element data5 = createElement("123.45");
+ assertConversionFailure(handler, "convertInteger", data5, "converted non-integer value");
+
+ Element data6 = createElement("");
+ assertConversionFailure(handler, "convertInteger", data6, "converted empty value");
}
- public void testConvertFloat() throws Exception
+ public void testConvertLong() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
- Element data = createElement("1234.5");
- assertEquals(Float.valueOf((float)1234.5), handler.convertFloat(data));
+ Element data1 = createElement("1234567890123456");
+ assertEquals(Long.valueOf(1234567890123456L), handler.convertLong(data1));
- // FIXME - test failure
+ Element data2 = createElement("-1234567890123456");
+ assertEquals(Long.valueOf(-1234567890123456L), handler.convertLong(data2));
+
+ Element data3 = createElement("ix");
+ assertConversionFailure(handler, "convertLong", data3, "converted non-numeric value");
+
+ Element data4 = createElement("123456789012345123456789012345");
+ assertConversionFailure(handler, "convertLong", data4, "converted too-large value");
+
+ Element data5 = createElement("123.45");
+ assertConversionFailure(handler, "convertLong", data5, "converted non-integer value");
+
+ Element data6 = createElement("");
+ assertConversionFailure(handler, "convertLong", data6, "converted empty value");
}
- public void testConvertInteger() throws Exception
+ public void testConvertFloat() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
- Element data = createElement("123456789");
- assertEquals(Integer.valueOf(123456789), handler.convertInteger(data));
+ Element data1 = createElement("1234.5");
+ assertEquals(Float.valueOf((float)1234.5), handler.convertFloat(data1));
- // FIXME - test failure
+ Element data2 = createElement("ix");
+ assertConversionFailure(handler, "convertFloat", data2, "converted non-numeric value");
+
+ Element data3 = createElement("");
+ assertConversionFailure(handler, "convertFloat", data3, "converted empty value");
}
- public void testConvertLong() throws Exception
+ public void testConvertDouble() throws Exception
{
Xml2BeanHandler handler = new Xml2BeanHandler();
- Element data = createElement("1234567890123456");
- assertEquals(Long.valueOf(1234567890123456L), handler.convertLong(data));
+ Element data1 = createElement("1234567890.125");
+ assertEquals(Double.valueOf(1234567890.125), handler.convertDouble(data1));
- // FIXME - test failure
+ Element data2 = createElement("ix");
+ assertConversionFailure(handler, "convertDouble", data2, "converted non-numeric value");
+
+ Element data3 = createElement("");
+ assertConversionFailure(handler, "convertDouble", data3, "converted empty value");
}
@@ -155,25 +262,11 @@
// }
- public void testConvertShort() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
+// public void testConvertDate() throws Exception
+// {
+// }
- Element data = createElement("12345");
- assertEquals(Short.valueOf((short)12345), handler.convertShort(data));
- // FIXME - test failure
- }
-
-
- public void testConvertString() throws Exception
- {
- Xml2BeanHandler handler = new Xml2BeanHandler();
-
- Element data = createElement("foo");
- assertEquals("foo", handler.convertString(data));
- }
-
// public void testConvertList() throws Exception
// {
// }
@@ -197,4 +290,118 @@
// public void testConvertObjectArray() throws Exception
// {
// }
+
+
+ public void testConvertNull() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element nullData = createElement(null);
+
+ assertNull(handler.convertString(nullData));
+ assertNull(handler.convertCharacter(nullData));
+ assertNull(handler.convertBoolean(nullData));
+ assertNull(handler.convertByte(nullData));
+ assertNull(handler.convertShort(nullData));
+ assertNull(handler.convertInteger(nullData));
+ assertNull(handler.convertLong(nullData));
+ assertNull(handler.convertFloat(nullData));
+ assertNull(handler.convertDouble(nullData));
+// assertNull(handler.convertNumber(nullData)); FIXME
+// assertNull(handler.convertDate(nullData)); FIXME
+// assertNull(handler.convertList(nullData)); FIXME
+// assertNull(handler.convertMap(nullData)); FIXME
+// assertNull(handler.convertSet(nullData)); FIXME
+// assertNull(handler.convertObject(nullData)); FIXME
+// assertNull(handler.convertObjectArray(nullData)); FIXME
+ }
+
+
+ public void testConvertEmptyAsNull() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler(Xml2BeanOptions.CONVERT_BLANK_AS_NULL);
+
+ Element empty = createElement(null);
+
+ assertNull(handler.convertString(empty));
+ assertNull(handler.convertCharacter(empty));
+ assertNull(handler.convertBoolean(empty));
+ assertNull(handler.convertByte(empty));
+ assertNull(handler.convertShort(empty));
+ assertNull(handler.convertInteger(empty));
+ assertNull(handler.convertLong(empty));
+ assertNull(handler.convertFloat(empty));
+ assertNull(handler.convertDouble(empty));
+// assertNull(handler.convertNumber(empty)); FIXME
+// assertNull(handler.convertDate(empty)); FIXME
+// assertNull(handler.convertList(empty)); FIXME
+// assertNull(handler.convertMap(empty)); FIXME
+// assertNull(handler.convertSet(empty)); FIXME
+// assertNull(handler.convertObject(empty)); FIXME
+// assertNull(handler.convertObjectArray(empty)); FIXME
+
+ Element blank = createElement(" \t\n ");
+
+ assertNull(handler.convertString(blank));
+ assertNull(handler.convertCharacter(blank));
+ assertNull(handler.convertBoolean(blank));
+ assertNull(handler.convertByte(blank));
+ assertNull(handler.convertShort(blank));
+ assertNull(handler.convertInteger(blank));
+ assertNull(handler.convertLong(blank));
+ assertNull(handler.convertFloat(blank));
+ assertNull(handler.convertDouble(blank));
+// assertNull(handler.convertNumber(blank)); FIXME
+// assertNull(handler.convertDate(blank)); FIXME
+// assertNull(handler.convertList(blank)); FIXME
+// assertNull(handler.convertMap(blank)); FIXME
+// assertNull(handler.convertSet(blank)); FIXME
+// assertNull(handler.convertObject(blank)); FIXME
+// assertNull(handler.convertObjectArray(blank)); FIXME
+ }
+
+
+ public void testRequireXsiNil() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler(Xml2BeanOptions.REQUIRE_XSI_NIL);
+
+ Element badData = createElement(null);
+
+ assertConversionFailure(handler, "convertString", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertCharacter", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertBoolean", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertByte", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertShort", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertInteger", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertLong", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertFloat", badData, "converted empty without xsi:nil");
+ assertConversionFailure(handler, "convertDouble", badData, "converted empty without xsi:nil");
+// assertConversionFailure(handler, "convertNumber", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertDate", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertList", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertMap", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertSet", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertObject", badData, "converted empty without xsi:nil"); FIXME
+// assertConversionFailure(handler, "convertObjectArray", badData, "converted empty without xsi:nil"); FIXME
+
+ Element goodData = createElement(null);
+ goodData.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true");
+
+ assertNull(handler.convertString(goodData));
+ assertNull(handler.convertCharacter(goodData));
+ assertNull(handler.convertBoolean(goodData));
+ assertNull(handler.convertByte(goodData));
+ assertNull(handler.convertShort(goodData));
+ assertNull(handler.convertInteger(goodData));
+ assertNull(handler.convertLong(goodData));
+ assertNull(handler.convertFloat(goodData));
+ assertNull(handler.convertDouble(goodData));
+// assertNull(handler.convertNumber(goodData)); FIXME
+// assertNull(handler.convertDate(goodData)); FIXME
+// assertNull(handler.convertList(goodData)); FIXME
+// assertNull(handler.convertMap(goodData)); FIXME
+// assertNull(handler.convertSet(goodData)); FIXME
+// assertNull(handler.convertObject(goodData)); FIXME
+// assertNull(handler.convertObjectArray(goodData)); FIXME
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-10 22:31:11
|
Revision: 97
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=97&view=rev
Author: kdgregory
Date: 2009-08-10 22:30:50 +0000 (Mon, 10 Aug 2009)
Log Message:
-----------
introduce ConversionException
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-07-23 23:28:30 UTC (rev 96)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-08-10 22:30:50 UTC (rev 97)
@@ -179,7 +179,7 @@
}
catch (IntrospectionException ee)
{
- throw new RuntimeException("introspection failure", ee);
+ throw new ConversionException("introspection failure", ee);
}
}
@@ -198,7 +198,7 @@
}
catch (Exception ee)
{
- throw new RuntimeException("unable to retrieve bean value", ee);
+ throw new ConversionException("unable to retrieve bean value", ee);
}
dispatch(propDesc.getName(), value, handler);
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java 2009-08-10 22:30:50 UTC (rev 97)
@@ -0,0 +1,36 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+
+/**
+ * A runtime exception thrown for any conversion error. Will always have a
+ * message, and typically contains a wrapped exception.
+ */
+public class ConversionException
+extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public ConversionException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public ConversionException(String message)
+ {
+ super(message);
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-23 23:28:39
|
Revision: 96
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=96&view=rev
Author: kdgregory
Date: 2009-07-23 23:28:30 +0000 (Thu, 23 Jul 2009)
Log Message:
-----------
checkpoint - XML to Bean conversion
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java 2009-07-23 23:28:30 UTC (rev 96)
@@ -0,0 +1,35 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Driver class for converting an XML DOM into a Java bean, using a {@link
+ * Xml2BeanHandler} to manage data conversion.
+ */
+public class Xml2BeanDriver
+{
+ /**
+ * Fills a bean-style object from an XML element. For each child of the
+ * passed element, tries to find a property with the same name, invokes
+ * the appropriate conversion handler method, and sets the property from
+ * the result.
+ */
+ public void dispatch(Element elem, Object bean)
+ {
+ }
+}
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-07-23 23:28:30 UTC (rev 96)
@@ -0,0 +1,171 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.XmlUtil;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code>
+ * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there
+ * will only be one instance of this object created during conversion; all
+ * intermediate data can be held on the stack.
+ */
+public class Xml2BeanHandler
+{
+ private EnumSet<Xml2BeanOptions> _options;
+
+
+ /**
+ * Public constructor, allowing various options specifications.
+ */
+ public Xml2BeanHandler(Xml2BeanOptions... options)
+ {
+ _options = EnumSet.noneOf(Xml2BeanOptions.class);
+ for (Xml2BeanOptions option : options)
+ _options.add(option);
+ }
+
+
+//----------------------------------------------------------------------------
+// Public Methods
+//----------------------------------------------------------------------------
+
+
+ public Boolean convertBoolean(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Boolean.valueOf(XmlUtil.parseXsdBoolean(text));
+ }
+
+
+ public Byte convertByte(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Byte.valueOf(text);
+ }
+
+
+ public Character convertCharacter(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ if (text.length() == 0)
+ return '\0';
+ return Character.valueOf(text.charAt(0));
+ }
+
+
+ public Date convertDate(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Double convertDouble(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Double.valueOf(text);
+ }
+
+
+ public Float convertFloat(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Float.valueOf(text);
+ }
+
+
+ public Integer convertInteger(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Integer.valueOf(text);
+ }
+
+
+ public Long convertLong(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Long.valueOf(text);
+ }
+
+
+ public Number convertNumber(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Short convertShort(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return Short.valueOf(text);
+ }
+
+
+ public String convertString(Element elem)
+ {
+ String text = DomUtil.getText(elem);
+ return text;
+ }
+
+
+ public List<?> convertList(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Set<?> convertSet(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Map<?,?> convertMap(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Object convertObject(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ public Object[] convertObjectArray(Element elem)
+ {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+
+}
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-07-23 23:28:30 UTC (rev 96)
@@ -0,0 +1,55 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+
+/**
+ * Options used by {@link Xml2BeanHandler} to control the way that DOM trees
+ * are translated to Java beans.
+ */
+public enum Xml2BeanOptions
+{
+ /**
+ * If present, the converter ignores elements that don't correspond to
+ * settable properties of the bean.
+ */
+ IGNORE_MISSING_PROPERTIES,
+
+
+ /**
+ * If present, the converter will ignore any objects that cannot be
+ * converted (many of the JDK-provided classes fall into this category,
+ * because they're not bean-structured).
+ */
+ IGNORE_UNCONVERTIBLE_OBJECTS,
+
+
+ /**
+ * If present, the converter requires an <code>xsi:type</code> attribute
+ * on each element, and will throw if it's not present. Default behavior
+ * uses the <code>xsi:type</code> value to choose between different setter
+ * methods, but otherwise ignores it.
+ */
+ REQUIRE_XSI_TYPE,
+
+
+ /**
+ * If present, the converter will use a setter method taking a String, in
+ * preference to any other type. Default behavior is to pick the method
+ * with the most restrictive type (and considering numeric types as more
+ * restrictive than <code>String</code>).
+ */
+ PREFER_STRING_SETTER
+}
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java 2009-07-23 23:28:30 UTC (rev 96)
@@ -0,0 +1,200 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import org.w3c.dom.Element;
+
+
+import net.sf.practicalxml.builder.XmlBuilder;
+
+
+public class TestXml2BeanHandler
+extends AbstractBeanConverterTestCase
+{
+ public TestXml2BeanHandler(String name)
+ {
+ super(name);
+ }
+
+
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ /**
+ * Builds a DOM tree with a single element, containing the specified
+ * text as a child of the root. We don't care about the element's name;
+ * it's the text that's important.
+ */
+ private Element createElement(String data)
+ {
+ return XmlBuilder.element("data", XmlBuilder.text(data))
+ .toDOM().getDocumentElement();
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+
+ public void testConvertBoolean() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data1 = createElement("true");
+ assertEquals(Boolean.TRUE, handler.convertBoolean(data1));
+
+ Element data2 = createElement("1");
+ assertEquals(Boolean.TRUE, handler.convertBoolean(data2));
+
+ Element data3 = createElement("false");
+ assertEquals(Boolean.FALSE, handler.convertBoolean(data3));
+
+ Element data4 = createElement("0");
+ assertEquals(Boolean.FALSE, handler.convertBoolean(data4));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertByte() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data1 = createElement("123");
+ assertEquals(Byte.valueOf((byte)123), handler.convertByte(data1));
+
+ Element data2 = createElement("-123");
+ assertEquals(Byte.valueOf((byte)-123), handler.convertByte(data2));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertCharacter() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data1 = createElement("A");
+ assertEquals(Character.valueOf('A'), handler.convertCharacter(data1));
+
+ Element data2 = createElement("\uFB01");
+ assertEquals(Character.valueOf('\uFB01'), handler.convertCharacter(data2));
+
+ Element data3 = createElement("");
+ assertEquals(Character.valueOf('\0'), handler.convertCharacter(data3));
+
+ // FIXME - test failure -- multi-character?
+ }
+
+
+// public void testConvertDate() throws Exception
+// {
+// }
+
+
+ public void testConvertDouble() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("1234567890.125");
+ assertEquals(Double.valueOf(1234567890.125), handler.convertDouble(data));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertFloat() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("1234.5");
+ assertEquals(Float.valueOf((float)1234.5), handler.convertFloat(data));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertInteger() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("123456789");
+ assertEquals(Integer.valueOf(123456789), handler.convertInteger(data));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertLong() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("1234567890123456");
+ assertEquals(Long.valueOf(1234567890123456L), handler.convertLong(data));
+
+ // FIXME - test failure
+ }
+
+
+// public void testConvertNumber() throws Exception
+// {
+// }
+
+
+ public void testConvertShort() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("12345");
+ assertEquals(Short.valueOf((short)12345), handler.convertShort(data));
+
+ // FIXME - test failure
+ }
+
+
+ public void testConvertString() throws Exception
+ {
+ Xml2BeanHandler handler = new Xml2BeanHandler();
+
+ Element data = createElement("foo");
+ assertEquals("foo", handler.convertString(data));
+ }
+
+// public void testConvertList() throws Exception
+// {
+// }
+//
+//
+// public void testConvertSet() throws Exception
+// {
+// }
+//
+//
+// public void testConvertMap() throws Exception
+// {
+// }
+//
+//
+// public void testConvertObject() throws Exception
+// {
+// }
+//
+//
+// public void testConvertObjectArray() throws Exception
+// {
+// }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-23 22:23:55
|
Revision: 95
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=95&view=rev
Author: kdgregory
Date: 2009-07-23 22:23:42 +0000 (Thu, 23 Jul 2009)
Log Message:
-----------
refactor common code from bean converter testcases into abstract super
Modified Paths:
--------------
branches/dev-1.1/src/test/java/net/sf/practicalxml/AbstractTestCase.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlHandler.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
Added Paths:
-----------
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/AbstractTestCase.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/AbstractTestCase.java 2009-07-23 22:06:24 UTC (rev 94)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/AbstractTestCase.java 2009-07-23 22:23:42 UTC (rev 95)
@@ -14,6 +14,10 @@
package net.sf.practicalxml;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
import junit.framework.TestCase;
/**
@@ -41,6 +45,10 @@
}
+//----------------------------------------------------------------------------
+// Assertions
+//----------------------------------------------------------------------------
+
/**
* Asserts a multi-line string, after stripping out any '\r' characters.
* Needed for a cross-platform build.
@@ -55,4 +63,16 @@
}
assertEquals(expected, buf.toString());
}
+
+
+ /**
+ * Asserts that an element has the expected number of element children
+ * (verifies that we didn't append to the wrong element).
+ */
+ protected void assertChildCount(String message, Element parent, int expected)
+ {
+ List<Element> children = DomUtil.getChildren(parent);
+ assertEquals(message + " child count:", expected, children.size());
+ }
+
}
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java 2009-07-23 22:23:42 UTC (rev 95)
@@ -0,0 +1,108 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import net.sf.practicalxml.AbstractTestCase;
+
+
+/**
+ * Provides common support code (primary test bean classes) for the converter
+ * testcases. Note that the bean classes are public, so that they can be
+ * instrospected.
+ */
+public abstract class AbstractBeanConverterTestCase
+extends AbstractTestCase
+{
+ protected AbstractBeanConverterTestCase(String name)
+ {
+ super(name);
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Bean Classes
+//----------------------------------------------------------------------------
+
+ public static class SimpleBean
+ {
+ private String _sval;
+ private int _ival;
+ private BigDecimal _dval;
+ private boolean _bval;
+
+ public SimpleBean()
+ {
+ // nothign to see here
+ }
+
+ public SimpleBean(String sval, int ival, BigDecimal dval, boolean bval)
+ {
+ _sval = sval;
+ _ival = ival;
+ _dval = dval;
+ _bval = bval;
+ }
+
+ public String getSval() { return _sval; }
+ public void setSval(String sval) { _sval = sval; }
+
+ public int getIval() { return _ival; }
+ public void setIval(int ival) { _ival = ival; }
+
+ public BigDecimal getDval() { return _dval; }
+ public void setDval(BigDecimal dval) { _dval = dval; }
+
+ public boolean isBval() { return _bval; }
+ public void setBval(boolean bval) { _bval = bval; }
+ }
+
+
+ public static class CompoundBean
+ {
+ private SimpleBean _simple;
+ private int[] _primArray;
+ private List<String> _stringList;
+
+ public CompoundBean()
+ {
+ // nothing here
+ }
+
+ public CompoundBean(SimpleBean simple, int[] primArray, List<String> stringList)
+ {
+ super();
+ _simple = simple;
+ _primArray = primArray;
+ _stringList = stringList;
+ }
+
+ public SimpleBean getSimple() { return _simple; }
+ public void setSimple(SimpleBean simple) { _simple = simple; }
+
+ public int[] getPrimArray() { return _primArray; }
+ public void setPrimArray(int[] primArray) { _primArray = primArray; }
+
+ public List<String> getStringList() { return _stringList; }
+ public void setStringList(List<String> list) { _stringList = list; }
+ }
+
+
+//----------------------------------------------------------------------------
+// Common Assertions
+//----------------------------------------------------------------------------
+}
Property changes on: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java
___________________________________________________________________
Added: svn:executable
+ *
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlHandler.java 2009-07-23 22:06:24 UTC (rev 94)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlHandler.java 2009-07-23 22:23:42 UTC (rev 95)
@@ -28,8 +28,6 @@
import org.w3c.dom.Element;
-import junit.framework.TestCase;
-
import net.sf.practicalxml.DomUtil;
import net.sf.practicalxml.OutputUtil;
import net.sf.practicalxml.junit.DomAsserts;
@@ -37,8 +35,14 @@
public class TestBean2XmlHandler
-extends TestCase
+extends AbstractBeanConverterTestCase
{
+ public TestBean2XmlHandler(String name)
+ {
+ super(name);
+ }
+
+
//----------------------------------------------------------------------------
// Test Data / Classes
//----------------------------------------------------------------------------
@@ -65,87 +69,7 @@
};
- // has to be public so that we can introspect it
- public static class SimpleBean
- {
- private String _sval;
- private int _ival;
- private BigDecimal _dval;
- private boolean _bval;
-
- public SimpleBean()
- {
- // nothign to see here
- }
-
- public SimpleBean(String sval, int ival, BigDecimal dval, boolean bval)
- {
- _sval = sval;
- _ival = ival;
- _dval = dval;
- _bval = bval;
- }
-
- public String getSval() { return _sval; }
- public void setSval(String sval) { _sval = sval; }
-
- public int getIval() { return _ival; }
- public void setIval(int ival) { _ival = ival; }
-
- public BigDecimal getDval() { return _dval; }
- public void setDval(BigDecimal dval) { _dval = dval; }
-
- public boolean isBval() { return _bval; }
- public void setBval(boolean bval) { _bval = bval; }
- }
-
-
- public static class CompoundBean
- {
- private SimpleBean _simple;
- private int[] _primArray;
- private List<String> _stringList;
-
- public CompoundBean()
- {
- // nothing here
- }
-
- public CompoundBean(SimpleBean simple, int[] primArray, List<String> stringList)
- {
- super();
- _simple = simple;
- _primArray = primArray;
- _stringList = stringList;
- }
-
- public SimpleBean getSimple() { return _simple; }
- public void setSimple(SimpleBean simple) { _simple = simple; }
-
- public int[] getPrimArray() { return _primArray; }
- public void setPrimArray(int[] primArray) { _primArray = primArray; }
-
- public List<String> getStringList() { return _stringList; }
- public void setStringList(List<String> list) { _stringList = list; }
- }
-
-
-//----------------------------------------------------------------------------
-// Support Code
-//----------------------------------------------------------------------------
-
/**
- * Asserts that an element has the expected number of children (verifies
- * that we didn't append to the wrong element).
- */
- private void assertChildCount(String message, Element parent, int expected)
- {
- List<Element> children = DomUtil.getChildren(parent);
- assertEquals(message + " child count:", expected, children.size());
- }
-
-
- /**
* Asserts the name, type, and value of an element. If any of the expected
* values are null, the associated test isn't performed.
*/
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-07-23 22:06:24 UTC (rev 94)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-07-23 22:23:42 UTC (rev 95)
@@ -21,7 +21,6 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import junit.framework.TestCase;
/**
* Tests for the top-level <code>BeanConverter</code> methods. These tend to
@@ -29,12 +28,19 @@
* and {@link TestBeanInputHandler}.
*/
public class TestBeanConverter
-extends TestCase
+extends AbstractBeanConverterTestCase
{
+ public TestBeanConverter(String name)
+ {
+ super(name);
+ }
+
+
//----------------------------------------------------------------------------
// Support Code
//----------------------------------------------------------------------------
+
//----------------------------------------------------------------------------
// Test Cases
//----------------------------------------------------------------------------
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-23 22:06:37
|
Revision: 94
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=94&view=rev
Author: kdgregory
Date: 2009-07-23 22:06:24 +0000 (Thu, 23 Jul 2009)
Log Message:
-----------
add XmlUtil.formatXsdBoolean(), XmlUtil.parseXsdBoolean()
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/XmlUtil.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/TestXmlUtil.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/XmlUtil.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-07-23 21:36:40 UTC (rev 93)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-07-23 22:06:24 UTC (rev 94)
@@ -100,6 +100,32 @@
/**
+ * Parses an XML Schema <code>dateTime</code> value, accepting any of
+ * the legal formats. Note that this method can also be used to parse
+ * a generic ISO-8601 date.
+ *
+ * @throws XmlException if unable to parse.
+ */
+ public static Date parseXsdDatetime(String value)
+ {
+ Calendar cal = GregorianCalendar.getInstance();
+ cal.setTimeInMillis(0);
+ int idx = parserHelper(value, cal, Calendar.YEAR, 0);
+ idx = parserHelper(value, cal, Calendar.MONTH, idx+1);
+ idx = parserHelper(value, cal, Calendar.DAY_OF_MONTH, idx+1);
+ idx = parserHelper(value, cal, Calendar.HOUR_OF_DAY, idx+1);
+ idx = parserHelper(value, cal, Calendar.MINUTE, idx+1);
+ idx = parserHelper(value, cal, Calendar.SECOND, idx+1);
+ if (idx < value.length() && (value.charAt(idx) == '.'))
+ {
+ idx = parserHelper(value, cal, Calendar.MILLISECOND, idx+1);
+ }
+ parseTimezone(value, cal, idx);
+ return cal.getTime();
+ }
+
+
+ /**
* Converts a Java <code>double</code> to a string, using the format
* specified by XML Schema for <code>decimal</code> elements. This
* method wraps the value and calls {@link #formatXsdDecimal(Number)},
@@ -125,28 +151,39 @@
/**
- * Parses an XML Schema <code>dateTime</code> object, accepting any of
- * the legal formats. Note that this method can also be used to parse
- * a generic ISO-8601 date.
+ * Converts a <code>boolean</code> value to the literal strings "true" or
+ * "false" (XML Schema <code>boolean</code> fields also allow "1" or "0").
+ */
+ public static String formatXsdBoolean(boolean value)
+ {
+ return value ? "true" : "false";
+ }
+
+
+ /**
+ * Parses an XML Schema <code>boolean</code> value, accepting any of
+ * the legal formats and trimming whitespace.
*
- * @throws XmlException if unable to parse.
+ * @throws XmlException the passed value, after trimming, is not one
+ * of the 4 legal representations of boolean data under XML
+ * Schema.
*/
- public static Date parseXsdDatetime(String value)
+ public static boolean parseXsdBoolean(String value)
{
- Calendar cal = GregorianCalendar.getInstance();
- cal.setTimeInMillis(0);
- int idx = parserHelper(value, cal, Calendar.YEAR, 0);
- idx = parserHelper(value, cal, Calendar.MONTH, idx+1);
- idx = parserHelper(value, cal, Calendar.DAY_OF_MONTH, idx+1);
- idx = parserHelper(value, cal, Calendar.HOUR_OF_DAY, idx+1);
- idx = parserHelper(value, cal, Calendar.MINUTE, idx+1);
- idx = parserHelper(value, cal, Calendar.SECOND, idx+1);
- if (idx < value.length() && (value.charAt(idx) == '.'))
+ try
{
- idx = parserHelper(value, cal, Calendar.MILLISECOND, idx+1);
+ value = value.trim();
+ if (value.equals("true") || value.equals("1"))
+ return true;
+ else if (value.equals("false") || value.equals("0"))
+ return false;
+ else
+ throw new XmlException("not an XSD boolean value: " + value);
}
- parseTimezone(value, cal, idx);
- return cal.getTime();
+ catch (NullPointerException e)
+ {
+ throw new XmlException("null values not allowed");
+ }
}
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/TestXmlUtil.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/TestXmlUtil.java 2009-07-23 21:36:40 UTC (rev 93)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/TestXmlUtil.java 2009-07-23 22:06:24 UTC (rev 94)
@@ -88,6 +88,52 @@
}
+ public void testFormatXsdBoolean() throws Exception
+ {
+ assertEquals("true", XmlUtil.formatXsdBoolean(true));
+ assertEquals("false", XmlUtil.formatXsdBoolean(false));
+ }
+
+
+ public void testParseXsdBoolean() throws Exception
+ {
+ assertEquals(true, XmlUtil.parseXsdBoolean("true"));
+ assertEquals(true, XmlUtil.parseXsdBoolean("1"));
+ assertEquals(false, XmlUtil.parseXsdBoolean("false"));
+ assertEquals(false, XmlUtil.parseXsdBoolean("0"));
+
+ try
+ {
+ XmlUtil.parseXsdBoolean("TRUE");
+ fail("uppercase \"TRUE\" not legal per XML schema");
+ }
+ catch (XmlException e)
+ {
+ // success
+ }
+
+ try
+ {
+ XmlUtil.parseXsdBoolean("");
+ fail("empty string not legal per XML schema");
+ }
+ catch (XmlException e)
+ {
+ // success
+ }
+
+ try
+ {
+ XmlUtil.parseXsdBoolean(null);
+ fail("null not legal");
+ }
+ catch (XmlException e)
+ {
+ // success
+ }
+ }
+
+
public void testEscape() throws Exception
{
assertEquals("", XmlUtil.escape(null));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-23 21:36:58
|
Revision: 93
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=93&view=rev
Author: kdgregory
Date: 2009-07-23 21:36:40 +0000 (Thu, 23 Jul 2009)
Log Message:
-----------
fix copyright/license comment
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-07-23 20:17:49 UTC (rev 92)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-07-23 21:36:40 UTC (rev 93)
@@ -1,6 +1,20 @@
-// Copyright (c) 2009 Keith D Gregory
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
/**
* Options used by {@link Bean2XmlHandler} to control the structure of the
* DOM tree.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-16 15:15:32
|
Revision: 90
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=90&view=rev
Author: kdgregory
Date: 2009-07-16 15:15:28 +0000 (Thu, 16 Jul 2009)
Log Message:
-----------
re-introduce OutputHandler interface
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandlerImpl.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandlerImpl.java
Removed Paths:
-------------
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-07-15 19:31:56 UTC (rev 89)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -62,7 +62,7 @@
BeanOutputOptions... options)
{
Element root = DomUtil.newDocument(nsUri, "temp");
- BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandler(root, options));
+ BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandlerImpl(root, options));
return replaceRoot(root);
}
@@ -81,7 +81,7 @@
BeanOutputOptions... options)
{
Element root = DomUtil.newDocument("temp");
- BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandler(root, options));
+ BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandlerImpl(root, options));
return replaceRoot(root);
}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java 2009-07-15 19:31:56 UTC (rev 89)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -14,335 +14,35 @@
package net.sf.practicalxml.converter;
-import net.sf.practicalxml.DomUtil;
-import net.sf.practicalxml.XmlUtil;
-
-import java.util.Arrays;
import java.util.Date;
-import java.util.EnumSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.xml.XMLConstants;
-import org.w3c.dom.Element;
-
/**
- * {@link OutputHandler} that builds a DOM tree. The structure of this
- * tree is customized by passing values from {@link BeanOutputOptions}.
- * <p>
- * Instances of this class are constructed around an <code>Element</code>,
- * which represents the object to be introspected by {@link BeanOutputDriver};
- * this simplifies recursive calls.
- * <p>
- * This class is not threadsafe (but then, neither are the JDK's DOM classes).
+ * {@link BeanOutputDriver} interacts with instances of this interface.
+ * There's only one such instance within the Practical XML library:
+ * {@link BeanOutputHandlerImpl}, but the existence of the interface
+ * lets you reuse the driver for other purposes.
*/
-public class BeanOutputHandler
+public interface BeanOutputHandler
{
- private EnumSet<BeanOutputOptions> _options;
- private Appender _appender;
-
-
- /**
- * Public constructor, which uses default appender and allows individual
- * options specifiers.
- */
- public BeanOutputHandler(Element appendTo, BeanOutputOptions... options)
- {
- _appender = new Appender(appendTo);
- _options = EnumSet.noneOf(BeanOutputOptions.class);
- for (BeanOutputOptions option : options)
- _options.add(option);
- }
-
-
- /**
- * Internal constructor, used by container classes for recursive calls.
- */
- protected BeanOutputHandler(BeanOutputHandler parent, Appender appender)
- {
- _appender = appender;
- _options = parent._options;
- }
-
-
-//----------------------------------------------------------------------------
-// OutputHandler implementation
-//----------------------------------------------------------------------------
-
- public void convert(String name, Boolean value)
- {
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = value.booleanValue() ? "true" : "false";
-
- _appender.append(name, "xsd:boolean", formatted);
- }
-
-
- public void convert(String name, Byte value)
- {
- _appender.append(name, "xsd:byte", value);
- }
-
-
- public void convert(String name, Character value)
- {
- _appender.append(name, "xsd:string", value);
- }
-
-
- public void convert(String name, Date value)
- {
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDatetime(value);
-
- _appender.append(name, "xsd:dateTime", formatted);
- }
-
-
- public void convert(String name, Double value)
- {
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDecimal(value);
-
- _appender.append(name, "xsd:decimal", formatted);
- }
-
-
- public void convert(String name, Float value)
- {
- Object formatted = value;
- if (shouldFormatAsXsd())
- formatted = XmlUtil.formatXsdDecimal(value);
-
- _appender.append(name, "xsd:decimal", formatted);
- }
-
-
- public void convert(String name, Integer value)
- {
- _appender.append(name, "xsd:int", value);
- }
-
-
- public void convert(String name, Long value)
- {
- _appender.append(name, "xsd:long", value);
- }
-
-
- public void convert(String name, Number value)
- {
- _appender.append(name, "xsd:decimal", value);
- }
-
-
- public void convert(String name, Short value)
- {
- _appender.append(name, "xsd:short", value);
- }
-
-
- public void convert(String name, String value)
- {
- _appender.append(name, "xsd:string", value);
- }
-
-
- public void convert(String name, List<?> value)
- {
- Element container = _appender.append(name, javaXsiType(value), null);
- appendSequence(container, value.iterator(), true);
- }
-
-
- public void convert(String name, Set<?> value)
- {
- Element container = _appender.append(name, javaXsiType(value), null);
- appendSequence(container, value.iterator(), false);
- }
-
-
- public void convert(String name, Map<?,?> map)
- {
- Element container = _appender.append(name, javaXsiType(map), null);
- BeanOutputHandler childHandler = new BeanOutputHandler(this, new MapAppender(container));
- BeanOutputDriver.introspect(map, childHandler);
- }
-
-
- public void convert(String name, Object value)
- {
- Element container = _appender.append(name, javaXsiType(value), null);
- Appender childAppender = value.getClass().isArray()
- ? new IndexedAppender(container)
- : new Appender(container);
- BeanOutputHandler childHandler = new BeanOutputHandler(this, childAppender);
- BeanOutputDriver.introspect(value, childHandler);
- }
-
-
- public void convert(String name, Object[] array)
- {
- Element container = _appender.append(name, javaXsiType(array), null);
- appendSequence(container, Arrays.asList(array).iterator(), true);
- }
-
-
- public void convertNull(String name)
- {
- if (!_options.contains(BeanOutputOptions.XSI_NIL))
- return;
-
- Element child = _appender.append(name, "", null);
- child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
- }
-
-
-//----------------------------------------------------------------------------
-// Internals
-//----------------------------------------------------------------------------
-
- protected boolean shouldFormatAsXsd()
- {
- return _options.contains(BeanOutputOptions.XSD_FORMAT)
- || _options.contains(BeanOutputOptions.XSI_TYPE);
- }
-
-
- /**
- * Returns the <code>xsi:type</code> value for a Java object (should not
- * be called for primitive wrappers, as these are covered by "xsd" types).
- */
- private String javaXsiType(Object obj)
- {
- return "java:" + obj.getClass().getName();
- }
-
-
- /**
- * Common code for sequenced objects -- arrays, lists, and sets.
- */
- private void appendSequence(Element parent, Iterator<?> itx, boolean isIndexed)
- {
- Appender childAppender = isIndexed ? new IndexedAppender(parent)
- : new Appender(parent);
- BeanOutputHandler childHandler = new BeanOutputHandler(this, childAppender);
- while (itx.hasNext())
- BeanOutputDriver.dispatch("data", itx.next(), childHandler);
- }
-
-
- /**
- * This class is responsible for adding nodes to the DOM tree. Each
- * instance of <code>XmlOutputHandler</code> is constructed around one
- * of these (or a subclass). Subclasses may override the {@link #append}
- * method to add additional information to the appended nodes.
- * <p>
- * A little bit of weirdness: as an inner class, this is constructed in
- * the context of an <code>XmlOutputHandler</code>, and has access to
- * members defined by that handler. However, in a recursive call, it is
- * actually held and used by a different handler. Since the second handler
- * copies members of the first, I don't see this as a problem ... until
- * some member doesn't get copied.
- */
- private class Appender
- {
- private Element _appendTo;
-
- public Appender(Element appendTo)
- {
- _appendTo = appendTo;
- }
-
- /**
- * Appends a child to the element we manage.
- *
- * @param name Local-name for the new element. As long as you're
- * dealing with Java, property names and element names
- * are interchangeable. If handling a <code>Map</code>,
- * you'll need to ensure that keys are appropriate XML
- * element names.
- * @param xsiType The value to insert in an <code>xsi:type</code>
- * attribute. This is required, even if the output-type
- * option isn't turned on.
- * @param value If not-null, will be stringified and attached to the
- * element as a text node. Apply any fancy formatting
- * before coming here. If null, will be ignored.
- */
- public Element append(String name, String xsiType, Object value)
- {
- if ((name == null) || (name.length() == 0))
- name = "data";
-
- Element child = DomUtil.appendChildInheritNamespace(_appendTo, name);
-
- if (_options.contains(BeanOutputOptions.XSI_TYPE))
- child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type", xsiType);
-
- if (value != null)
- child.setTextContent(String.valueOf(value));
-
- return child;
- }
- }
-
-
- /**
- * An appender for array/list processing, that attaches an index attribute
- * to the appended node.
- */
- private class IndexedAppender
- extends Appender
- {
- int _index = 0;
-
- public IndexedAppender(Element appendTo)
- {
- super(appendTo);
- }
-
- @Override
- public Element append(String name, String xsiType, Object value)
- {
- Element child = super.append(name, xsiType, value);
- child.setAttribute("index", String.valueOf(_index++));
- return child;
- }
- }
-
-
- /**
- * An appender for maps, which either uses the passed name as the
- * element name, or as the value of a "key" attribute.
- */
- private class MapAppender
- extends Appender
- {
- public MapAppender(Element appendTo)
- {
- super(appendTo);
- }
-
- @Override
- public Element append(String name, String xsiType, Object value)
- {
- Element child = null;
- if (_options.contains(BeanOutputOptions.INTROSPECT_MAPS))
- {
- child = super.append(name, xsiType, value);
- }
- else
- {
- child = super.append("data", xsiType, value);
- child.setAttribute("key", name);
- }
- return child;
- }
- }
+ public void convert(String name, Boolean value);
+ public void convert(String name, Byte value);
+ public void convert(String name, Character value);
+ public void convert(String name, Date value);
+ public void convert(String name, Double value);
+ public void convert(String name, Float value);
+ public void convert(String name, Integer value);
+ public void convert(String name, Long value);
+ public void convert(String name, Number value);
+ public void convert(String name, Short value);
+ public void convert(String name, String value);
+ public void convert(String name, List<?> value);
+ public void convert(String name, Set<?> value);
+ public void convert(String name, Map<?,?> map);
+ public void convert(String name, Object value);
+ public void convert(String name, Object[] array);
+ public void convertNull(String name);
}
Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandlerImpl.java (from rev 89, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java)
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandlerImpl.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandlerImpl.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -0,0 +1,351 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.XmlUtil;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Invoked by {@link BeanOutputDriver} to build a DOM tree from introspected
+ * Java objects.
+ * <p>
+ * Instances of this class are constructed around an <code>Element</code>,
+ * which represents the object to be introspected by {@link BeanOutputDriver}.
+ * This simplifies recursive calls, at the expense of not being able to attach
+ * type information at the top level. See {@link BeanConverter} for the rather
+ * ugly hack to work around this.
+ * <p>
+ * This class is not threadsafe (but then, neither are the JDK's DOM classes).
+ */
+public class BeanOutputHandlerImpl
+implements BeanOutputHandler
+{
+ private EnumSet<BeanOutputOptions> _options;
+ private Appender _appender;
+
+
+ /**
+ * Public constructor, which uses default appender and allows individual
+ * options specifiers.
+ */
+ public BeanOutputHandlerImpl(Element appendTo, BeanOutputOptions... options)
+ {
+ _appender = new Appender(appendTo);
+ _options = EnumSet.noneOf(BeanOutputOptions.class);
+ for (BeanOutputOptions option : options)
+ _options.add(option);
+ }
+
+
+ /**
+ * Internal constructor, used by container classes for recursive calls.
+ */
+ protected BeanOutputHandlerImpl(BeanOutputHandlerImpl parent, Appender appender)
+ {
+ _appender = appender;
+ _options = parent._options;
+ }
+
+
+//----------------------------------------------------------------------------
+// OutputHandler implementation
+//----------------------------------------------------------------------------
+
+ public void convert(String name, Boolean value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = value.booleanValue() ? "true" : "false";
+
+ _appender.append(name, "xsd:boolean", formatted);
+ }
+
+
+ public void convert(String name, Byte value)
+ {
+ _appender.append(name, "xsd:byte", value);
+ }
+
+
+ public void convert(String name, Character value)
+ {
+ _appender.append(name, "xsd:string", value);
+ }
+
+
+ public void convert(String name, Date value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDatetime(value);
+
+ _appender.append(name, "xsd:dateTime", formatted);
+ }
+
+
+ public void convert(String name, Double value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDecimal(value);
+
+ _appender.append(name, "xsd:decimal", formatted);
+ }
+
+
+ public void convert(String name, Float value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDecimal(value);
+
+ _appender.append(name, "xsd:decimal", formatted);
+ }
+
+
+ public void convert(String name, Integer value)
+ {
+ _appender.append(name, "xsd:int", value);
+ }
+
+
+ public void convert(String name, Long value)
+ {
+ _appender.append(name, "xsd:long", value);
+ }
+
+
+ public void convert(String name, Number value)
+ {
+ _appender.append(name, "xsd:decimal", value);
+ }
+
+
+ public void convert(String name, Short value)
+ {
+ _appender.append(name, "xsd:short", value);
+ }
+
+
+ public void convert(String name, String value)
+ {
+ _appender.append(name, "xsd:string", value);
+ }
+
+
+ public void convert(String name, List<?> value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ appendSequence(container, value.iterator(), true);
+ }
+
+
+ public void convert(String name, Set<?> value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ appendSequence(container, value.iterator(), false);
+ }
+
+
+ public void convert(String name, Map<?,?> map)
+ {
+ Element container = _appender.append(name, javaXsiType(map), null);
+ BeanOutputHandlerImpl childHandler = new BeanOutputHandlerImpl(this, new MapAppender(container));
+ BeanOutputDriver.introspect(map, childHandler);
+ }
+
+
+ public void convert(String name, Object value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ Appender childAppender = value.getClass().isArray()
+ ? new IndexedAppender(container)
+ : new Appender(container);
+ BeanOutputHandlerImpl childHandler = new BeanOutputHandlerImpl(this, childAppender);
+ BeanOutputDriver.introspect(value, childHandler);
+ }
+
+
+ public void convert(String name, Object[] array)
+ {
+ Element container = _appender.append(name, javaXsiType(array), null);
+ appendSequence(container, Arrays.asList(array).iterator(), true);
+ }
+
+
+ public void convertNull(String name)
+ {
+ if (!_options.contains(BeanOutputOptions.XSI_NIL))
+ return;
+
+ Element child = _appender.append(name, "", null);
+ child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ protected boolean shouldFormatAsXsd()
+ {
+ return _options.contains(BeanOutputOptions.XSD_FORMAT)
+ || _options.contains(BeanOutputOptions.XSI_TYPE);
+ }
+
+
+ /**
+ * Returns the <code>xsi:type</code> value for a Java object (should not
+ * be called for primitive wrappers, as these are covered by "xsd" types).
+ */
+ private String javaXsiType(Object obj)
+ {
+ return "java:" + obj.getClass().getName();
+ }
+
+
+ /**
+ * Common code for sequenced objects -- arrays, lists, and sets.
+ */
+ private void appendSequence(Element parent, Iterator<?> itx, boolean isIndexed)
+ {
+ Appender childAppender = isIndexed ? new IndexedAppender(parent)
+ : new Appender(parent);
+ BeanOutputHandlerImpl childHandler = new BeanOutputHandlerImpl(this, childAppender);
+ while (itx.hasNext())
+ BeanOutputDriver.dispatch("data", itx.next(), childHandler);
+ }
+
+
+ /**
+ * This class is responsible for adding nodes to the DOM tree. Each
+ * instance of <code>XmlOutputHandler</code> is constructed around one
+ * of these (or a subclass). Subclasses may override the {@link #append}
+ * method to add additional information to the appended nodes.
+ * <p>
+ * A little bit of weirdness: as an inner class, this is constructed in
+ * the context of an <code>XmlOutputHandler</code>, and has access to
+ * members defined by that handler. However, in a recursive call, it is
+ * actually held and used by a different handler. Since the second handler
+ * copies members of the first, I don't see this as a problem ... until
+ * some member doesn't get copied.
+ */
+ private class Appender
+ {
+ private Element _appendTo;
+
+ public Appender(Element appendTo)
+ {
+ _appendTo = appendTo;
+ }
+
+ /**
+ * Appends a child to the element we manage.
+ *
+ * @param name Local-name for the new element. As long as you're
+ * dealing with Java, property names and element names
+ * are interchangeable. If handling a <code>Map</code>,
+ * you'll need to ensure that keys are appropriate XML
+ * element names.
+ * @param xsiType The value to insert in an <code>xsi:type</code>
+ * attribute. This is required, even if the output-type
+ * option isn't turned on.
+ * @param value If not-null, will be stringified and attached to the
+ * element as a text node. Apply any fancy formatting
+ * before coming here. If null, will be ignored.
+ */
+ public Element append(String name, String xsiType, Object value)
+ {
+ if ((name == null) || (name.length() == 0))
+ name = "data";
+
+ Element child = DomUtil.appendChildInheritNamespace(_appendTo, name);
+
+ if (_options.contains(BeanOutputOptions.XSI_TYPE))
+ child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type", xsiType);
+
+ if (value != null)
+ child.setTextContent(String.valueOf(value));
+
+ return child;
+ }
+ }
+
+
+ /**
+ * An appender for array/list processing, that attaches an index attribute
+ * to the appended node.
+ */
+ private class IndexedAppender
+ extends Appender
+ {
+ int _index = 0;
+
+ public IndexedAppender(Element appendTo)
+ {
+ super(appendTo);
+ }
+
+ @Override
+ public Element append(String name, String xsiType, Object value)
+ {
+ Element child = super.append(name, xsiType, value);
+ child.setAttribute("index", String.valueOf(_index++));
+ return child;
+ }
+ }
+
+
+ /**
+ * An appender for maps, which either uses the passed name as the
+ * element name, or as the value of a "key" attribute.
+ */
+ private class MapAppender
+ extends Appender
+ {
+ public MapAppender(Element appendTo)
+ {
+ super(appendTo);
+ }
+
+ @Override
+ public Element append(String name, String xsiType, Object value)
+ {
+ Element child = null;
+ if (_options.contains(BeanOutputOptions.INTROSPECT_MAPS))
+ {
+ child = super.append(name, xsiType, value);
+ }
+ else
+ {
+ child = super.append("data", xsiType, value);
+ child.setAttribute("key", name);
+ }
+ return child;
+ }
+ }
+}
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java 2009-07-15 19:31:56 UTC (rev 89)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -2,7 +2,7 @@
package net.sf.practicalxml.converter;
/**
- * Options used by {@link BeanOutputHandler} to control the structure of the
+ * Options used by {@link BeanOutputHandlerImpl} to control the structure of the
* DOM tree.
*/
public enum BeanOutputOptions
Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-07-15 19:31:56 UTC (rev 89)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -25,7 +25,7 @@
/**
* Tests for the top-level <code>BeanConverter</code> methods. These tend to
- * be minimal; the detailed testing happens in {@link TestBeanOutputHandler}
+ * be minimal; the detailed testing happens in {@link TestBeanOutputHandlerImpl}
* and {@link TestBeanInputHandler}.
*/
public class TestBeanConverter
Deleted: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java 2009-07-15 19:31:56 UTC (rev 89)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -1,574 +0,0 @@
-// Copyright 2008-2009 severally by the contributors
-//
-// Licensed 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 net.sf.practicalxml.converter;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import javax.xml.XMLConstants;
-
-import org.w3c.dom.Element;
-
-import junit.framework.TestCase;
-
-import net.sf.practicalxml.DomUtil;
-import net.sf.practicalxml.OutputUtil;
-import net.sf.practicalxml.junit.DomAsserts;
-import net.sf.practicalxml.xpath.XPathWrapper;
-
-
-public class TestBeanOutputHandler
-extends TestCase
-{
-//----------------------------------------------------------------------------
-// Test Data / Classes
-//----------------------------------------------------------------------------
-
- /**
- * An array of simple value types, along with their XSD type name and
- * XSD-formatted value.
- */
- private final static Object[][] SIMPLE_VALUES = new Object[][]
- {
- new Object[] { Byte.valueOf((byte)123), "xsd:byte", "123" },
- new Object[] { Short.valueOf((short)4567), "xsd:short", "4567" },
- new Object[] { Integer.valueOf(12345678), "xsd:int", "12345678" },
- new Object[] { Long.valueOf(12345678901234L), "xsd:long", "12345678901234" },
- new Object[] { Float.valueOf((float)1234), "xsd:decimal", "1234.0" },
- new Object[] { Double.valueOf(1234567890.5), "xsd:decimal", "1234567890.5" },
- new Object[] { Boolean.TRUE, "xsd:boolean", "true" },
- new Object[] { Boolean.FALSE, "xsd:boolean", "false" },
- new Object[] { Character.valueOf('A'), "xsd:string", "A" },
- new Object[] { "this is a test", "xsd:string", "this is a test" },
- new Object[] { new Date(1247551703704L), "xsd:dateTime", "2009-07-14T06:08:23" },
- new Object[] { new BigInteger("123456789012345"), "xsd:decimal", "123456789012345" },
- new Object[] { new BigDecimal("123456789012345.123456789012345"), "xsd:decimal", "123456789012345.123456789012345" }
- };
-
-
- // has to be public so that we can introspect it
- public static class SimpleBean
- {
- private String _sval;
- private int _ival;
- private BigDecimal _dval;
- private boolean _bval;
-
- public SimpleBean()
- {
- // nothign to see here
- }
-
- public SimpleBean(String sval, int ival, BigDecimal dval, boolean bval)
- {
- _sval = sval;
- _ival = ival;
- _dval = dval;
- _bval = bval;
- }
-
- public String getSval() { return _sval; }
- public void setSval(String sval) { _sval = sval; }
-
- public int getIval() { return _ival; }
- public void setIval(int ival) { _ival = ival; }
-
- public BigDecimal getDval() { return _dval; }
- public void setDval(BigDecimal dval) { _dval = dval; }
-
- public boolean isBval() { return _bval; }
- public void setBval(boolean bval) { _bval = bval; }
- }
-
-
- public static class CompoundBean
- {
- private SimpleBean _simple;
- private int[] _primArray;
- private List<String> _stringList;
-
- public CompoundBean()
- {
- // nothing here
- }
-
- public CompoundBean(SimpleBean simple, int[] primArray, List<String> stringList)
- {
- super();
- _simple = simple;
- _primArray = primArray;
- _stringList = stringList;
- }
-
- public SimpleBean getSimple() { return _simple; }
- public void setSimple(SimpleBean simple) { _simple = simple; }
-
- public int[] getPrimArray() { return _primArray; }
- public void setPrimArray(int[] primArray) { _primArray = primArray; }
-
- public List<String> getStringList() { return _stringList; }
- public void setStringList(List<String> list) { _stringList = list; }
- }
-
-
-//----------------------------------------------------------------------------
-// Support Code
-//----------------------------------------------------------------------------
-
- /**
- * Asserts that an element has the expected number of children (verifies
- * that we didn't append to the wrong element).
- */
- private void assertChildCount(String message, Element parent, int expected)
- {
- List<Element> children = DomUtil.getChildren(parent);
- assertEquals(message + " child count:", expected, children.size());
- }
-
-
- /**
- * Asserts the name, type, and value of an element. If any of the expected
- * values are null, the associated test isn't performed.
- */
- private void assertNameTypeValue(
- String message, Element elem,
- String expectedName, String expectedType, String expectedValue)
- {
- if (expectedName != null)
- assertEquals(message + " name:", expectedName,
- elem.getNodeName());
- if (expectedType != null)
- assertEquals(message + " type:", expectedType,
- elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"));
- if (expectedValue != null)
- assertEquals(message + " value:", expectedValue,
- DomUtil.getText(elem));
- }
-
-
- /**
- * Asserts the name and type of a compound element, where the type is a Java classname.
- */
- private void assertContainerNameAndType(Element elem, String expectedName, Class<?> expectedType)
- {
- assertNameTypeValue("container", elem, expectedName, "java:" + expectedType.getName(), null);
- }
-
-
- /**
- * A variety of assertions about added children. Assumes that we'll add
- * a single child node per parent, and that we aren't using namespaces.
- */
- private void assertAppend(String message, Element parent,
- String expectedName,
- String expectedType,
- String expectedValue)
- {
- assertChildCount(message, parent, 1);
- assertNameTypeValue(message, DomUtil.getChildren(parent).get(0),
- expectedName, expectedType, expectedValue);
- }
-
-
-//----------------------------------------------------------------------------
-// Test Cases
-//----------------------------------------------------------------------------
-
- // this test is essentially repeated in the DispatchSimpleValues tests
- // it exists here as an initial verification of appended element structure
- public void testDispatch() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", "bar", new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- assertAppend("", root, "foo", "", "bar");
- }
-
-
- public void testDispachWithNullName() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch(null, "bar", new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- assertAppend("", root, "data", "", "bar");
- }
-
-
- public void testNamespaceInheritance() throws Exception
- {
- Element root = DomUtil.newDocument("urn:zippy", "argle:bargle");
- BeanOutputDriver.dispatch("foo", "bar", new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- List<Element> children = DomUtil.getChildren(root);
- assertEquals("child count", 1, children.size());
-
- Element child = children.get(0);
- assertEquals("urn:zippy", child.getNamespaceURI());
- assertEquals("argle", child.getPrefix());
- assertEquals("foo", child.getLocalName());
- }
-
-
- public void testDispatchNullValue() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", null, new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- List<Element> children1 = DomUtil.getChildren(root);
- assertEquals("null element added", 0, children1.size());
-
- BeanOutputDriver.dispatch("foo", null, new BeanOutputHandler(root, BeanOutputOptions.XSI_NIL));
- List<Element> children2 = DomUtil.getChildren(root);
- assertEquals("null element added", 1, children2.size());
- assertEquals("nil flag", "true",
- children2.get(0).getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
- }
-
-
-
- public void testDispatchSimpleValuesWithDefaults() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
- {
- Object value = SIMPLE_VALUES[ii][0];
- Element parent = DomUtil.appendChild(root, "value");
- BeanOutputDriver.dispatch("foo", value, new BeanOutputHandler(parent));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
- assertAppend("value " + ii, parent, "foo", "", String.valueOf(value));
- }
- }
-
-
- public void testDispatchSimpleValuesWithXSDFormatting() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
- {
- Element parent = DomUtil.appendChild(root, "value");
- BeanOutputDriver.dispatch("foo", SIMPLE_VALUES[ii][0],
- new BeanOutputHandler(parent, BeanOutputOptions.XSD_FORMAT));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
- assertAppend("value " + ii, parent, "foo", "", (String)SIMPLE_VALUES[ii][2]);
- }
- }
-
-
- public void testDispatchSimpleValuesWithXSIType() throws Exception
- {
- Element root = DomUtil.newDocument("test");
- for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
- {
- Element parent = DomUtil.appendChild(root, "value");
- BeanOutputDriver.dispatch("foo", SIMPLE_VALUES[ii][0],
- new BeanOutputHandler(parent, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
- assertAppend("value " + ii, parent, "foo", (String)SIMPLE_VALUES[ii][1], (String)SIMPLE_VALUES[ii][2]);
- }
- }
-
-
- public void testDispatchObjectArray() throws Exception
- {
- Object[] data = new String[] { "argle", "bargle" };
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data, new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- assertAppend("container", root, "foo", "", null);
-
- Element container = DomUtil.getChild(root, "foo");
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "data", "", "argle");
- assertNameTypeValue("child 1", children.get(1), "data", "", "bargle");
-
- DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
- DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
- }
-
-
- public void testDispatchObjectArrayWithType() throws Exception
- {
- Object[] data = new String[] { "argle", "bargle" };
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
- assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
-
- DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
- DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
- }
-
-
- public void testDispatchPrimitiveArrayWithType() throws Exception
- {
- int[] data = new int[] { 1, 2, 3 };
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 3, children.size());
- assertNameTypeValue("child 1", children.get(0), "data", "xsd:int", "1");
- assertNameTypeValue("child 2", children.get(1), "data", "xsd:int", "2");
- assertNameTypeValue("child 3", children.get(2), "data", "xsd:int", "3");
-
- DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
- DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
- DomAsserts.assertEquals("child 3 index", "2", root, "/test/foo/data[3]/@index");
- }
-
-
- public void testDispatchListWithType() throws Exception
- {
- List<String> data = new ArrayList<String>();
- data.add("argle");
- data.add("bargle");
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
- assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
-
- DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
- DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
- }
-
-
- public void testDispatchSetWithType() throws Exception
- {
- // use TreeSet so that order is guaranteed
- Set<String> data = new TreeSet<String>();
- data.add("bargle");
- data.add("argle");
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
- assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
-
- DomAsserts.assertEquals("child 1 index", "", root, "/test/foo/data[1]/@index");
- DomAsserts.assertEquals("child 2 index", "", root, "/test/foo/data[2]/@index");
- }
-
-
- public void testDispatchMapWithDefaultFormat() throws Exception
- {
- // use TreeMap so that order is guaranteed
- Map<String,Object> data = new TreeMap<String,Object>();
- data.put("foo", Integer.valueOf(123));
- data.put("argle", "bargle");
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "bargle");
- assertNameTypeValue("child 1", children.get(1), "data", "xsd:int", "123");
-
- DomAsserts.assertEquals("child 1 key", "argle", root, "/test/foo/data[1]/@key");
- DomAsserts.assertEquals("child 2 key", "foo", root, "/test/foo/data[2]/@key");
- }
-
-
- public void testDispatchMapWithIntrospectFormat() throws Exception
- {
- // use TreeMap so that order is guaranteed
- Map<String,Object> data = new TreeMap<String,Object>();
- data.put("foo", Integer.valueOf(123));
- data.put("argle", "bargle");
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", data,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE,
- BeanOutputOptions.INTROSPECT_MAPS));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", data.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
- assertNameTypeValue("child 0", children.get(0), "argle", "xsd:string", "bargle");
- assertNameTypeValue("child 1", children.get(1), "foo", "xsd:int", "123");
-
- DomAsserts.assertEquals("child 1 key", "", root, "/test/foo/argle/@key");
- DomAsserts.assertEquals("child 2 key", "", root, "/test/foo/foo/@key");
- }
-
-
- public void testDispatchSimpleBean() throws Exception
- {
- SimpleBean bean = new SimpleBean("zippy", 123, new BigDecimal("456.78"), true);
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", bean,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", bean.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 4, children.size());
-
- Element child1 = (Element)(new XPathWrapper("//sval").evaluate(root).get(0));
- assertNameTypeValue("sval", child1, "sval", "xsd:string", "zippy");
-
- Element child2 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
- assertNameTypeValue("ival", child2, "ival", "xsd:int", "123");
-
- Element child3 = (Element)(new XPathWrapper("//dval").evaluate(root).get(0));
- assertNameTypeValue("dval", child3, "dval", "xsd:decimal", "456.78");
-
- Element child4 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
- assertNameTypeValue("bval", child4, "bval", "xsd:boolean", "true");
- }
-
-
- public void testDispatchSimpleBeanIncludingNulls() throws Exception
- {
- SimpleBean bean = new SimpleBean();
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", bean,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE,
- BeanOutputOptions.XSI_NIL));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", bean.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 4, children.size());
-
- Element child1 = (Element)(new XPathWrapper("//sval").evaluate(root).get(0));
- assertEquals("sval nil", "true", child1.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
-
- Element child2 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
- assertNameTypeValue("ival", child2, "ival", "xsd:int", "0");
-
- Element child3 = (Element)(new XPathWrapper("//dval").evaluate(root).get(0));
- assertEquals("dval nil", "true", child3.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
-
- Element child4 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
- assertNameTypeValue("bval", child4, "bval", "xsd:boolean", "false");
- }
-
-
- public void testDispatchSimpleBeanIgnoringNulls() throws Exception
- {
- SimpleBean bean = new SimpleBean();
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", bean,
- new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- Element container = DomUtil.getChild(root, "foo");
- assertContainerNameAndType(container, "foo", bean.getClass());
-
- List<Element> children = DomUtil.getChildren(container);
- assertEquals("child count", 2, children.size());
-
- Element child1 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
- assertNameTypeValue("ival", child1, "ival", "xsd:int", "0");
-
- Element child2 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
- assertNameTypeValue("bval", child2, "bval", "xsd:boolean", "false");
- }
-
-
- public void testDispatchCompoundBean() throws Exception
- {
- CompoundBean bean = new CompoundBean(
- new SimpleBean("zippy", 123, new BigDecimal("456.78"), true),
- new int[] { 1, 2, 3 },
- Arrays.asList("foo", "bar", "baz"));
-
- // at this point, I'm convinced the type output works, so we'll do default
- // output and then use XPath for all assertions
-
- Element root = DomUtil.newDocument("test");
- BeanOutputDriver.dispatch("foo", bean, new BeanOutputHandler(root));
-// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
-
- DomAsserts.assertEquals("zippy", root, "/test/foo/simple/sval");
- DomAsserts.assertEquals("123", root, "/test/foo/simple/ival");
- DomAsserts.assertEquals("456.78", root, "/test/foo/simple/dval");
- DomAsserts.assertEquals("true", root, "/test/foo/simple/bval");
-
- DomAsserts.assertEquals("1", root, "/test/foo/primArray/data[1]");
- DomAsserts.assertEquals("2", root, "/test/foo/primArray/data[2]");
- DomAsserts.assertEquals("3", root, "/test/foo/primArray/data[3]");
-
- DomAsserts.assertEquals("0", root, "/test/foo/primArray/data[1]/@index");
- DomAsserts.assertEquals("1", root, "/test/foo/primArray/data[2]/@index");
- DomAsserts.assertEquals("2", root, "/test/foo/primArray/data[3]/@index");
-
- DomAsserts.assertEquals("foo", root, "/test/foo/stringList/data[1]");
- DomAsserts.assertEquals("bar", root, "/test/foo/stringList/data[2]");
- DomAsserts.assertEquals("baz", root, "/test/foo/stringList/data[3]");
- }
-}
Copied: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandlerImpl.java (from rev 89, branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java)
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandlerImpl.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandlerImpl.java 2009-07-16 15:15:28 UTC (rev 90)
@@ -0,0 +1,574 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+import junit.framework.TestCase;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.OutputUtil;
+import net.sf.practicalxml.junit.DomAsserts;
+import net.sf.practicalxml.xpath.XPathWrapper;
+
+
+public class TestBeanOutputHandlerImpl
+extends TestCase
+{
+//----------------------------------------------------------------------------
+// Test Data / Classes
+//----------------------------------------------------------------------------
+
+ /**
+ * An array of simple value types, along with their XSD type name and
+ * XSD-formatted value.
+ */
+ private final static Object[][] SIMPLE_VALUES = new Object[][]
+ {
+ new Object[] { Byte.valueOf((byte)123), "xsd:byte", "123" },
+ new Object[] { Short.valueOf((short)4567), "xsd:short", "4567" },
+ new Object[] { Integer.valueOf(12345678), "xsd:int", "12345678" },
+ new Object[] { Long.valueOf(12345678901234L), "xsd:long", "12345678901234" },
+ new Object[] { Float.valueOf((float)1234), "xsd:decimal", "1234.0" },
+ new Object[] { Double.valueOf(1234567890.5), "xsd:decimal", "1234567890.5" },
+ new Object[] { Boolean.TRUE, "xsd:boolean", "true" },
+ new Object[] { Boolean.FALSE, "xsd:boolean", "false" },
+ new Object[] { Character.valueOf('A'), "xsd:string", "A" },
+ new Object[] { "this is a test", "xsd:string", "this is a test" },
+ new Object[] { new Date(1247551703704L), "xsd:dateTime", "2009-07-14T06:08:23" },
+ new Object[] { new BigInteger("123456789012345"), "xsd:decimal", "123456789012345" },
+ new Object[] { new BigDecimal("123456789012345.123456789012345"), "xsd:decimal", "123456789012345.123456789012345" }
+ };
+
+
+ // has to be public so that we can introspect it
+ public static class SimpleBean
+ {
+ private String _sval;
+ private int _ival;
+ private BigDecimal _dval;
+ private boolean _bval;
+
+ public SimpleBean()
+ {
+ // nothign to see here
+ }
+
+ public SimpleBean(String sval, int ival, BigDecimal dval, boolean bval)
+ {
+ _sval = sval;
+ _ival = ival;
+ _dval = dval;
+ _bval = bval;
+ }
+
+ public String getSval() { return _sval; }
+ public void setSval(String sval) { _sval = sval; }
+
+ public int getIval() { return _ival; }
+ public void setIval(int ival) { _ival = ival; }
+
+ public BigDecimal getDval() { return _dval; }
+ public void setDval(BigDecimal dval) { _dval = dval; }
+
+ public boolean isBval() { return _bval; }
+ public void setBval(boolean bval) { _bval = bval; }
+ }
+
+
+ public static class CompoundBean
+ {
+ private SimpleBean _simple;
+ private int[] _primArray;
+ private List<String> _stringList;
+
+ public CompoundBean()
+ {
+ // nothing here
+ }
+
+ public CompoundBean(SimpleBean simple, int[] primArray, List<String> stringList)
+ {
+ super();
+ _simple = simple;
+ _primArray = primArray;
+ _stringList = stringList;
+ }
+
+ public SimpleBean getSimple() { return _simple; }
+ public void setSimple(SimpleBean simple) { _simple = simple; }
+
+ public int[] getPrimArray() { return _primArray; }
+ public void setPrimArray(int[] primArray) { _primArray = primArray; }
+
+ public List<String> getStringList() { return _stringList; }
+ public void setStringList(List<String> list) { _stringList = list; }
+ }
+
+
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ /**
+ * Asserts that an element has the expected number of children (verifies
+ * that we didn't append to the wrong element).
+ */
+ private void assertChildCount(String message, Element parent, int expected)
+ {
+ List<Element> children = DomUtil.getChildren(parent);
+ assertEquals(message + " child count:", expected, children.size());
+ }
+
+
+ /**
+ * Asserts the name, type, and value of an element. If any of the expected
+ * values are null, the associated test isn't performed.
+ */
+ private void assertNameTypeValue(
+ String message, Element elem,
+ String expectedName, String expectedType, String expectedValue)
+ {
+ if (expectedName != null)
+ assertEquals(message + " name:", expectedName,
+ elem.getNodeName());
+ if (expectedType != null)
+ assertEquals(message + " type:", expectedType,
+ elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"));
+ if (expectedValue != null)
+ assertEquals(message + " value:", expectedValue,
+ DomUtil.getText(elem));
+ }
+
+
+ /**
+ * Asserts the name and type of a compound element, where the type is a Java classname.
+ */
+ private void assertContainerNameAndType(Element elem, String expectedName, Class<?> expectedType)
+ {
+ assertNameTypeValue("container", elem, expectedName, "java:" + expectedType.getName(), null);
+ }
+
+
+ /**
+ * A variety of assertions about added children. Assumes that we'll add
+ * a single child node per parent, and that we aren't using namespaces.
+ */
+ private void assertAppend(String message, Element parent,
+ String expectedName,
+ String expectedType,
+ String expectedValue)
+ {
+ assertChildCount(message, parent, 1);
+ assertNameTypeValue(message, Do...
[truncated message content] |
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-15 19:31:59
|
Revision: 89
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=89&view=rev
Author: kdgregory
Date: 2009-07-15 19:31:56 +0000 (Wed, 15 Jul 2009)
Log Message:
-----------
remove unused methods
Modified Paths:
--------------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java 2009-07-15 19:28:12 UTC (rev 88)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java 2009-07-15 19:31:56 UTC (rev 89)
@@ -26,7 +26,6 @@
import java.util.Set;
import javax.xml.XMLConstants;
-import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -70,47 +69,6 @@
//----------------------------------------------------------------------------
-// Public methods
-//----------------------------------------------------------------------------
-
- /**
- * Convenience method to create a new document and invoke conversion.
- * This document will not namespace its elements.
- *
- * @param bean The object to be converted.
- * @param rootName The name of the root element of the new document.
- * @param options Options to control the output structure. Options
- * are additive, and are either on (passed here) or
- * off.
- */
- public static Document newDocument(Object bean, String rootName, BeanOutputOptions... options)
- {
- return newDocument(bean, null, rootName, options);
- }
-
-
- /**
- * Convenience method to create a new document and invoke conversion,
- * with all elements belonging to a specified namespace.
- *
- * @param bean The object to be converted.
- * @param nsUri Namespace for this document; all elements will
- * have the same namespace. If <code>null</code>,
- * the elements will not be namespaced.
- * @param rootName The name of the root element of the new document.
- * @param options Options to control the output structure. Options
- * are additive, and are either on (passed here) or
- * off.
- */
- public static Document newDocument(Object bean, String nsUri, String rootName,
- BeanOutputOptions... options)
- {
- Element root = DomUtil.newDocument(nsUri, rootName);
- return root.getOwnerDocument();
- }
-
-
-//----------------------------------------------------------------------------
// OutputHandler implementation
//----------------------------------------------------------------------------
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-15 19:28:14
|
Revision: 88
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=88&view=rev
Author: kdgregory
Date: 2009-07-15 19:28:12 +0000 (Wed, 15 Jul 2009)
Log Message:
-----------
DomAsserts - rename params for clarity
Modified Paths:
--------------
trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java
Modified: trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-07-15 19:23:56 UTC (rev 87)
+++ trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-07-15 19:28:12 UTC (rev 88)
@@ -62,7 +62,7 @@
/**
- * Asserts that an element has the given name and namespace URI.
+ * Asserts that an element has the given local name and namespace URI.
* <p>
* If assertion fails, will display message indicating whether name or
* namespace was invalid.
@@ -70,32 +70,32 @@
* @param expectedNSUri The expected namespace URI. May be <code>null
* </code> to assert that the element does not
* have a namespace.
- * @param expectedName The expected name.
+ * @param localName The expected name, sans prefix
* @param elem The element to assert.
*/
public static void assertNamespaceAndName(
- String expectedNSUri, String expectedName, Element elem)
+ String expectedNSUri, String localName, Element elem)
{
Assert.assertEquals("invalid namespace", expectedNSUri, elem.getNamespaceURI());
- Assert.assertEquals("invalid localname", expectedName, DomUtil.getLocalName(elem));
+ Assert.assertEquals("invalid localname", localName, DomUtil.getLocalName(elem));
}
/**
- * Asserts that an element has the given name and namespace URI.
+ * Asserts that an element has the given local name and namespace URI.
*
* @param message Message to display if assertion fails.
* @param expectedNSUri The expected namespace URI. May be <code>null
* </code> to assert that the element does not
* have a namespace.
- * @param expectedName The expected name.
+ * @param localName The expected name, sans prefix
* @param elem The element to assert.
*/
public static void assertNamespaceAndName(
- String message, String expectedNSUri, String expectedName, Element elem)
+ String message, String expectedNSUri, String localName, Element elem)
{
Assert.assertEquals(message, expectedNSUri, elem.getNamespaceURI());
- Assert.assertEquals(message, expectedName, DomUtil.getLocalName(elem));
+ Assert.assertEquals(message, localName, DomUtil.getLocalName(elem));
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-15 19:23:58
|
Revision: 87
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=87&view=rev
Author: kdgregory
Date: 2009-07-15 19:23:56 +0000 (Wed, 15 Jul 2009)
Log Message:
-----------
Initial Commit - BeanConverter (output only)
Added Paths:
-----------
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputDriver.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,112 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import net.sf.practicalxml.DomUtil;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * Converts Java objects (not just beans) to and from an XML representation.
+ * This was originally developed to support RESTful web services, without the
+ * class-generation hassle of JAXB.
+ * <p>
+ * The XML generated/consumed by this class obeys the following rules, with
+ * options controlled by {@link BeanOutputOptions}:
+ * <ul>
+ * <li> All elements inherit their parent's namespace and namespace prefix.
+ * <li> Elements of sets are output using the element name "data".
+ * <li> Elements of lists and arrays are output using the element name "data",
+ * with an attribute "index" that contains the numeric index.
+ * <li> Elements of maps are by default output using the name "data", with an
+ * attribute "name" containing the actual map key. The output option
+ * <code>INTROSPECT_MAPS</code> will change this behavior, but will throw
+ * if the map keys are not valid XML element names.
+ * <li> Values are output using <code>toString()</code>, except as overridden
+ * by options.
+ * <li> Null values do not generate output, unless the <code>XSI_NIL</code>
+ * option is in effect.
+ * </ul>
+ */
+public class BeanConverter
+{
+ /**
+ * Creates a new DOM document from the passed bean, in which all elements
+ * are members of the specified namespace.
+ *
+ * @param bean The source object. This can be any Java object:
+ * bean, collection, or simple type.
+ * @param nsUri The namespace of the root element. This will be
+ * inherited by all child elements.
+ * @param rootName The qualified name given to the root element of the
+ * generated document. If a qualified name, all child
+ * elements will inherit its prefix.
+ * @param options Options controlling output.
+.
+ */
+ public static Document generateXml(Object bean, String nsUri, String rootName,
+ BeanOutputOptions... options)
+ {
+ Element root = DomUtil.newDocument(nsUri, "temp");
+ BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandler(root, options));
+ return replaceRoot(root);
+ }
+
+
+ /**
+ * Creates a new DOM document from the passed bean, without namespace.
+ *
+ * @param bean The source object. This can be any Java object:
+ * bean, collection, or simple type.
+ * @param rootName The name given to the root element of the produced
+ * document.
+ * @param options Options controlling output.
+.
+ */
+ public static Document generateXml(Object bean, String rootName,
+ BeanOutputOptions... options)
+ {
+ Element root = DomUtil.newDocument("temp");
+ BeanOutputDriver.dispatch(rootName, bean, new BeanOutputHandler(root, options));
+ return replaceRoot(root);
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ /**
+ * Replaces the passed element as the root of the document by its first
+ * element child. This is a remarkably ugly hack, but it lets me avoid
+ * writing a worse hack into the output handler to determine whether or
+ * not it is handling the root element.
+ * <p>
+ * This works for the Sun (Xerces) DOM implementation. It might not work
+ * for other implementations (indeed, the <code>Node</code> JavaDoc
+ * indicates that it might not be allowed).
+ */
+ private static Document replaceRoot(Element oldRoot)
+ {
+ Element newRoot = DomUtil.getChildren(oldRoot).get(0);
+ oldRoot.removeChild(newRoot);
+
+ Document dom = oldRoot.getOwnerDocument();
+ dom.replaceChild(newRoot, oldRoot);
+ return dom;
+ }
+}
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputDriver.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputDriver.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputDriver.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,207 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Driver class for bean conversion. This class uses an {@link OutputHandler}
+ * to produce actual output, and provides two methods that interact with that
+ * handler:
+ *
+ * <ul>
+ * <li> {@link #dispatch} examines the type of the passed object, and calls
+ * the appropriate output handler method. Objects may be dispatched
+ * with or without a name associated.
+ * <li> {@link #introspect} examines compound objects that are either beans
+ * or Java collection objects, and calls <code>dispatch()</code> for
+ * each member. This method is meant to be called by the handler.
+ * </ul>
+ */
+public class BeanOutputDriver
+{
+ /**
+ * Dispatches a named object to the output handler.
+ */
+ public static void dispatch(String name, Object obj, BeanOutputHandler handler)
+ {
+ if (obj == null)
+ handler.convertNull(name);
+ else if (obj instanceof String)
+ handler.convert(name, (String)obj);
+ else if (obj instanceof Integer)
+ handler.convert(name, (Integer)obj);
+ else if (obj instanceof Long)
+ handler.convert(name, (Long)obj);
+ else if (obj instanceof Short)
+ handler.convert(name, (Short)obj);
+ else if (obj instanceof Byte)
+ handler.convert(name, (Byte)obj);
+ else if (obj instanceof Double)
+ handler.convert(name, (Double)obj);
+ else if (obj instanceof Float)
+ handler.convert(name, (Float)obj);
+ else if (obj instanceof Boolean)
+ handler.convert(name, (Boolean)obj);
+ else if (obj instanceof Character)
+ handler.convert(name, (Character)obj);
+ else if (obj instanceof Date)
+ handler.convert(name, (Date)obj);
+ else if (obj instanceof Number)
+ handler.convert(name, (Number)obj);
+ else if (obj instanceof List)
+ handler.convert(name, (List<?>)obj);
+ else if (obj instanceof Set)
+ handler.convert(name, (Set<?>)obj);
+ else if (obj instanceof Map)
+ handler.convert(name, (Map<?,?>)obj);
+ else if (obj instanceof Object[])
+ handler.convert(name, (Object[])obj);
+ else
+ handler.convert(name, obj);
+ }
+
+
+ /**
+ * Dispatches an unnamed object to the output handler (actually
+ * dispatches with a null name).
+ */
+ public static void dispatch(Object obj, BeanOutputHandler handler)
+ {
+ dispatch(null, obj, handler);
+ }
+
+
+ /**
+ * Introspects the passed compound object, and dispatches each of its
+ * components. If the object is not a compound object, will dispatch
+ * the object itself. If the object is <code>null</code>, does nothing.
+ */
+ public static void introspect(Object obj, BeanOutputHandler handler)
+ {
+ if (obj == null)
+ return;
+
+ if (isSimpleObject(obj))
+ dispatch(obj, handler);
+ else if (obj.getClass().isArray())
+ introspectPrimitiveArray(obj, handler);
+ else if (obj instanceof Object[])
+ introspectObjectArray((Object[])obj, handler);
+ else if (obj instanceof Collection<?>)
+ introspectCollection((Collection<?>)obj, handler);
+ else if (obj instanceof Map<?,?>)
+ introspectMap((Map<?,?>)obj, handler);
+ else
+ introspectBean(obj, handler);
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ private static boolean isSimpleObject(Object obj)
+ {
+ return (obj instanceof String)
+ || (obj instanceof Integer)
+ || (obj instanceof Long)
+ || (obj instanceof Byte)
+ || (obj instanceof Short)
+ || (obj instanceof Double)
+ || (obj instanceof Float)
+ || (obj instanceof Character)
+ || (obj instanceof Boolean)
+ || (obj instanceof Number)
+ || (obj instanceof Date);
+ }
+
+
+ private static void introspectPrimitiveArray(Object array, BeanOutputHandler handler)
+ {
+ int length = Array.getLength(array);
+ for (int ii = 0 ; ii < length ; ii++)
+ dispatch(Array.get(array, ii), handler);
+ }
+
+
+ private static void introspectObjectArray(Object[] array, BeanOutputHandler handler)
+ {
+ for (int ii = 0 ; ii < array.length ; ii++)
+ dispatch(array[ii], handler);
+ }
+
+
+ private static void introspectCollection(Collection<?> coll, BeanOutputHandler handler)
+ {
+ for (Object member : coll)
+ dispatch(member, handler);
+ }
+
+
+ private static void introspectMap(Map<?,?> map, BeanOutputHandler handler)
+ {
+ for (Map.Entry<?,?> entry : map.entrySet())
+ dispatch(String.valueOf(entry.getKey()), entry.getValue(), handler);
+ }
+
+
+ private static void introspectBean(Object bean, BeanOutputHandler handler)
+ {
+ try
+ {
+ BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class);
+ PropertyDescriptor[] props = info.getPropertyDescriptors();
+ for (int ii = 0 ; ii < props.length ; ii++)
+ beanIntrospectionHelper(bean, props[ii], handler);
+ }
+ catch (IntrospectionException ee)
+ {
+ throw new RuntimeException("introspection failure", ee);
+ }
+ }
+
+
+ private static void beanIntrospectionHelper(
+ Object bean, PropertyDescriptor propDesc, BeanOutputHandler handler)
+ {
+ Method getter = propDesc.getReadMethod();
+ if (getter == null)
+ return;
+
+ Object value = null;
+ try
+ {
+ value = getter.invoke(bean);
+ }
+ catch (Exception ee)
+ {
+ throw new RuntimeException("unable to retrieve bean value", ee);
+ }
+
+ dispatch(propDesc.getName(), value, handler);
+ }
+}
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputHandler.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,390 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.XmlUtil;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * {@link OutputHandler} that builds a DOM tree. The structure of this
+ * tree is customized by passing values from {@link BeanOutputOptions}.
+ * <p>
+ * Instances of this class are constructed around an <code>Element</code>,
+ * which represents the object to be introspected by {@link BeanOutputDriver};
+ * this simplifies recursive calls.
+ * <p>
+ * This class is not threadsafe (but then, neither are the JDK's DOM classes).
+ */
+public class BeanOutputHandler
+{
+ private EnumSet<BeanOutputOptions> _options;
+ private Appender _appender;
+
+
+ /**
+ * Public constructor, which uses default appender and allows individual
+ * options specifiers.
+ */
+ public BeanOutputHandler(Element appendTo, BeanOutputOptions... options)
+ {
+ _appender = new Appender(appendTo);
+ _options = EnumSet.noneOf(BeanOutputOptions.class);
+ for (BeanOutputOptions option : options)
+ _options.add(option);
+ }
+
+
+ /**
+ * Internal constructor, used by container classes for recursive calls.
+ */
+ protected BeanOutputHandler(BeanOutputHandler parent, Appender appender)
+ {
+ _appender = appender;
+ _options = parent._options;
+ }
+
+
+//----------------------------------------------------------------------------
+// Public methods
+//----------------------------------------------------------------------------
+
+ /**
+ * Convenience method to create a new document and invoke conversion.
+ * This document will not namespace its elements.
+ *
+ * @param bean The object to be converted.
+ * @param rootName The name of the root element of the new document.
+ * @param options Options to control the output structure. Options
+ * are additive, and are either on (passed here) or
+ * off.
+ */
+ public static Document newDocument(Object bean, String rootName, BeanOutputOptions... options)
+ {
+ return newDocument(bean, null, rootName, options);
+ }
+
+
+ /**
+ * Convenience method to create a new document and invoke conversion,
+ * with all elements belonging to a specified namespace.
+ *
+ * @param bean The object to be converted.
+ * @param nsUri Namespace for this document; all elements will
+ * have the same namespace. If <code>null</code>,
+ * the elements will not be namespaced.
+ * @param rootName The name of the root element of the new document.
+ * @param options Options to control the output structure. Options
+ * are additive, and are either on (passed here) or
+ * off.
+ */
+ public static Document newDocument(Object bean, String nsUri, String rootName,
+ BeanOutputOptions... options)
+ {
+ Element root = DomUtil.newDocument(nsUri, rootName);
+ return root.getOwnerDocument();
+ }
+
+
+//----------------------------------------------------------------------------
+// OutputHandler implementation
+//----------------------------------------------------------------------------
+
+ public void convert(String name, Boolean value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = value.booleanValue() ? "true" : "false";
+
+ _appender.append(name, "xsd:boolean", formatted);
+ }
+
+
+ public void convert(String name, Byte value)
+ {
+ _appender.append(name, "xsd:byte", value);
+ }
+
+
+ public void convert(String name, Character value)
+ {
+ _appender.append(name, "xsd:string", value);
+ }
+
+
+ public void convert(String name, Date value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDatetime(value);
+
+ _appender.append(name, "xsd:dateTime", formatted);
+ }
+
+
+ public void convert(String name, Double value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDecimal(value);
+
+ _appender.append(name, "xsd:decimal", formatted);
+ }
+
+
+ public void convert(String name, Float value)
+ {
+ Object formatted = value;
+ if (shouldFormatAsXsd())
+ formatted = XmlUtil.formatXsdDecimal(value);
+
+ _appender.append(name, "xsd:decimal", formatted);
+ }
+
+
+ public void convert(String name, Integer value)
+ {
+ _appender.append(name, "xsd:int", value);
+ }
+
+
+ public void convert(String name, Long value)
+ {
+ _appender.append(name, "xsd:long", value);
+ }
+
+
+ public void convert(String name, Number value)
+ {
+ _appender.append(name, "xsd:decimal", value);
+ }
+
+
+ public void convert(String name, Short value)
+ {
+ _appender.append(name, "xsd:short", value);
+ }
+
+
+ public void convert(String name, String value)
+ {
+ _appender.append(name, "xsd:string", value);
+ }
+
+
+ public void convert(String name, List<?> value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ appendSequence(container, value.iterator(), true);
+ }
+
+
+ public void convert(String name, Set<?> value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ appendSequence(container, value.iterator(), false);
+ }
+
+
+ public void convert(String name, Map<?,?> map)
+ {
+ Element container = _appender.append(name, javaXsiType(map), null);
+ BeanOutputHandler childHandler = new BeanOutputHandler(this, new MapAppender(container));
+ BeanOutputDriver.introspect(map, childHandler);
+ }
+
+
+ public void convert(String name, Object value)
+ {
+ Element container = _appender.append(name, javaXsiType(value), null);
+ Appender childAppender = value.getClass().isArray()
+ ? new IndexedAppender(container)
+ : new Appender(container);
+ BeanOutputHandler childHandler = new BeanOutputHandler(this, childAppender);
+ BeanOutputDriver.introspect(value, childHandler);
+ }
+
+
+ public void convert(String name, Object[] array)
+ {
+ Element container = _appender.append(name, javaXsiType(array), null);
+ appendSequence(container, Arrays.asList(array).iterator(), true);
+ }
+
+
+ public void convertNull(String name)
+ {
+ if (!_options.contains(BeanOutputOptions.XSI_NIL))
+ return;
+
+ Element child = _appender.append(name, "", null);
+ child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
+ }
+
+
+//----------------------------------------------------------------------------
+// Internals
+//----------------------------------------------------------------------------
+
+ protected boolean shouldFormatAsXsd()
+ {
+ return _options.contains(BeanOutputOptions.XSD_FORMAT)
+ || _options.contains(BeanOutputOptions.XSI_TYPE);
+ }
+
+
+ /**
+ * Returns the <code>xsi:type</code> value for a Java object (should not
+ * be called for primitive wrappers, as these are covered by "xsd" types).
+ */
+ private String javaXsiType(Object obj)
+ {
+ return "java:" + obj.getClass().getName();
+ }
+
+
+ /**
+ * Common code for sequenced objects -- arrays, lists, and sets.
+ */
+ private void appendSequence(Element parent, Iterator<?> itx, boolean isIndexed)
+ {
+ Appender childAppender = isIndexed ? new IndexedAppender(parent)
+ : new Appender(parent);
+ BeanOutputHandler childHandler = new BeanOutputHandler(this, childAppender);
+ while (itx.hasNext())
+ BeanOutputDriver.dispatch("data", itx.next(), childHandler);
+ }
+
+
+ /**
+ * This class is responsible for adding nodes to the DOM tree. Each
+ * instance of <code>XmlOutputHandler</code> is constructed around one
+ * of these (or a subclass). Subclasses may override the {@link #append}
+ * method to add additional information to the appended nodes.
+ * <p>
+ * A little bit of weirdness: as an inner class, this is constructed in
+ * the context of an <code>XmlOutputHandler</code>, and has access to
+ * members defined by that handler. However, in a recursive call, it is
+ * actually held and used by a different handler. Since the second handler
+ * copies members of the first, I don't see this as a problem ... until
+ * some member doesn't get copied.
+ */
+ private class Appender
+ {
+ private Element _appendTo;
+
+ public Appender(Element appendTo)
+ {
+ _appendTo = appendTo;
+ }
+
+ /**
+ * Appends a child to the element we manage.
+ *
+ * @param name Local-name for the new element. As long as you're
+ * dealing with Java, property names and element names
+ * are interchangeable. If handling a <code>Map</code>,
+ * you'll need to ensure that keys are appropriate XML
+ * element names.
+ * @param xsiType The value to insert in an <code>xsi:type</code>
+ * attribute. This is required, even if the output-type
+ * option isn't turned on.
+ * @param value If not-null, will be stringified and attached to the
+ * element as a text node. Apply any fancy formatting
+ * before coming here. If null, will be ignored.
+ */
+ public Element append(String name, String xsiType, Object value)
+ {
+ if ((name == null) || (name.length() == 0))
+ name = "data";
+
+ Element child = DomUtil.appendChildInheritNamespace(_appendTo, name);
+
+ if (_options.contains(BeanOutputOptions.XSI_TYPE))
+ child.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type", xsiType);
+
+ if (value != null)
+ child.setTextContent(String.valueOf(value));
+
+ return child;
+ }
+ }
+
+
+ /**
+ * An appender for array/list processing, that attaches an index attribute
+ * to the appended node.
+ */
+ private class IndexedAppender
+ extends Appender
+ {
+ int _index = 0;
+
+ public IndexedAppender(Element appendTo)
+ {
+ super(appendTo);
+ }
+
+ @Override
+ public Element append(String name, String xsiType, Object value)
+ {
+ Element child = super.append(name, xsiType, value);
+ child.setAttribute("index", String.valueOf(_index++));
+ return child;
+ }
+ }
+
+
+ /**
+ * An appender for maps, which either uses the passed name as the
+ * element name, or as the value of a "key" attribute.
+ */
+ private class MapAppender
+ extends Appender
+ {
+ public MapAppender(Element appendTo)
+ {
+ super(appendTo);
+ }
+
+ @Override
+ public Element append(String name, String xsiType, Object value)
+ {
+ Element child = null;
+ if (_options.contains(BeanOutputOptions.INTROSPECT_MAPS))
+ {
+ child = super.append(name, xsiType, value);
+ }
+ else
+ {
+ child = super.append("data", xsiType, value);
+ child.setAttribute("key", name);
+ }
+ return child;
+ }
+ }
+}
Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java
===================================================================
--- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java (rev 0)
+++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanOutputOptions.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,41 @@
+// Copyright (c) 2009 Keith D Gregory
+package net.sf.practicalxml.converter;
+
+/**
+ * Options used by {@link BeanOutputHandler} to control the structure of the
+ * DOM tree.
+ */
+public enum BeanOutputOptions
+{
+ /**
+ * Outputs values using formats defined by XML Schema, rather than Java's
+ * <code>String.valueOf()</code> method. Note that these formats are not
+ * flagged in the element, so sender and receiver will have to agree on
+ * the format.
+ */
+ XSD_FORMAT,
+
+ /**
+ * Will add an <code>xsi:type</code> attribute to each element. For values
+ * covered by the XML Schema simple types, this attribute's value will be
+ * "<code>xsd:XXX</code>", where XXX is the XSD type name. For complex
+ * types, this attribute's value will be "<code>java:XXX</code>", where
+ * XXX is the fully-qualified classname.
+ * <p>
+ * <em>This option implies {@link #XSD_FORMAT} for simple types</em>.
+ */
+ XSI_TYPE,
+
+ /**
+ * Report null values using the <code>xsi:nil="true"</code> attribute. If
+ * not present, null values are ignored, and not added to DOM tree.
+ */
+ XSI_NIL,
+
+ /**
+ * Output maps in an "introspected" format, where the name of each item
+ * is the map key (rather than "data"), and the "key" attribute is omitted.
+ * If any key is not a valid XML identifier, the converter will throw.
+ */
+ INTROSPECT_MAPS
+}
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,74 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.OutputUtil;
+
+import javax.xml.XMLConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the top-level <code>BeanConverter</code> methods. These tend to
+ * be minimal; the detailed testing happens in {@link TestBeanOutputHandler}
+ * and {@link TestBeanInputHandler}.
+ */
+public class TestBeanConverter
+extends TestCase
+{
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ public void testGenerateSimpleContentSansNamespace() throws Exception
+ {
+ String rootName = "argle";
+ String value = "foo";
+
+ Document dom = BeanConverter.generateXml(value, rootName, BeanOutputOptions.XSI_TYPE);
+// System.out.println(OutputUtil.compactString(dom));
+
+ Element root = dom.getDocumentElement();
+ assertEquals(rootName, root.getNodeName());
+ assertEquals(value, root.getTextContent());
+ assertEquals("xsd:string", root.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"));
+ assertEquals(0, DomUtil.getChildren(root).size());
+ }
+
+
+ public void testGenerateSimpleContentWithNamespace() throws Exception
+ {
+ String nsUri = "urn:fibble";
+ String rootName = "argle:bargle";
+ String value = "foo";
+
+ Document dom = BeanConverter.generateXml(value, nsUri, rootName, BeanOutputOptions.XSI_TYPE);
+// System.out.println(OutputUtil.compactString(dom));
+
+ Element root = dom.getDocumentElement();
+ assertEquals(nsUri, root.getNamespaceURI());
+ assertEquals(rootName, root.getNodeName());
+ assertEquals(value, root.getTextContent());
+ assertEquals("xsd:string", root.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"));
+ assertEquals(0, DomUtil.getChildren(root).size());
+ }
+}
\ No newline at end of file
Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java
===================================================================
--- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java (rev 0)
+++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanOutputHandler.java 2009-07-15 19:23:56 UTC (rev 87)
@@ -0,0 +1,574 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// Licensed 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 net.sf.practicalxml.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.xml.XMLConstants;
+
+import org.w3c.dom.Element;
+
+import junit.framework.TestCase;
+
+import net.sf.practicalxml.DomUtil;
+import net.sf.practicalxml.OutputUtil;
+import net.sf.practicalxml.junit.DomAsserts;
+import net.sf.practicalxml.xpath.XPathWrapper;
+
+
+public class TestBeanOutputHandler
+extends TestCase
+{
+//----------------------------------------------------------------------------
+// Test Data / Classes
+//----------------------------------------------------------------------------
+
+ /**
+ * An array of simple value types, along with their XSD type name and
+ * XSD-formatted value.
+ */
+ private final static Object[][] SIMPLE_VALUES = new Object[][]
+ {
+ new Object[] { Byte.valueOf((byte)123), "xsd:byte", "123" },
+ new Object[] { Short.valueOf((short)4567), "xsd:short", "4567" },
+ new Object[] { Integer.valueOf(12345678), "xsd:int", "12345678" },
+ new Object[] { Long.valueOf(12345678901234L), "xsd:long", "12345678901234" },
+ new Object[] { Float.valueOf((float)1234), "xsd:decimal", "1234.0" },
+ new Object[] { Double.valueOf(1234567890.5), "xsd:decimal", "1234567890.5" },
+ new Object[] { Boolean.TRUE, "xsd:boolean", "true" },
+ new Object[] { Boolean.FALSE, "xsd:boolean", "false" },
+ new Object[] { Character.valueOf('A'), "xsd:string", "A" },
+ new Object[] { "this is a test", "xsd:string", "this is a test" },
+ new Object[] { new Date(1247551703704L), "xsd:dateTime", "2009-07-14T06:08:23" },
+ new Object[] { new BigInteger("123456789012345"), "xsd:decimal", "123456789012345" },
+ new Object[] { new BigDecimal("123456789012345.123456789012345"), "xsd:decimal", "123456789012345.123456789012345" }
+ };
+
+
+ // has to be public so that we can introspect it
+ public static class SimpleBean
+ {
+ private String _sval;
+ private int _ival;
+ private BigDecimal _dval;
+ private boolean _bval;
+
+ public SimpleBean()
+ {
+ // nothign to see here
+ }
+
+ public SimpleBean(String sval, int ival, BigDecimal dval, boolean bval)
+ {
+ _sval = sval;
+ _ival = ival;
+ _dval = dval;
+ _bval = bval;
+ }
+
+ public String getSval() { return _sval; }
+ public void setSval(String sval) { _sval = sval; }
+
+ public int getIval() { return _ival; }
+ public void setIval(int ival) { _ival = ival; }
+
+ public BigDecimal getDval() { return _dval; }
+ public void setDval(BigDecimal dval) { _dval = dval; }
+
+ public boolean isBval() { return _bval; }
+ public void setBval(boolean bval) { _bval = bval; }
+ }
+
+
+ public static class CompoundBean
+ {
+ private SimpleBean _simple;
+ private int[] _primArray;
+ private List<String> _stringList;
+
+ public CompoundBean()
+ {
+ // nothing here
+ }
+
+ public CompoundBean(SimpleBean simple, int[] primArray, List<String> stringList)
+ {
+ super();
+ _simple = simple;
+ _primArray = primArray;
+ _stringList = stringList;
+ }
+
+ public SimpleBean getSimple() { return _simple; }
+ public void setSimple(SimpleBean simple) { _simple = simple; }
+
+ public int[] getPrimArray() { return _primArray; }
+ public void setPrimArray(int[] primArray) { _primArray = primArray; }
+
+ public List<String> getStringList() { return _stringList; }
+ public void setStringList(List<String> list) { _stringList = list; }
+ }
+
+
+//----------------------------------------------------------------------------
+// Support Code
+//----------------------------------------------------------------------------
+
+ /**
+ * Asserts that an element has the expected number of children (verifies
+ * that we didn't append to the wrong element).
+ */
+ private void assertChildCount(String message, Element parent, int expected)
+ {
+ List<Element> children = DomUtil.getChildren(parent);
+ assertEquals(message + " child count:", expected, children.size());
+ }
+
+
+ /**
+ * Asserts the name, type, and value of an element. If any of the expected
+ * values are null, the associated test isn't performed.
+ */
+ private void assertNameTypeValue(
+ String message, Element elem,
+ String expectedName, String expectedType, String expectedValue)
+ {
+ if (expectedName != null)
+ assertEquals(message + " name:", expectedName,
+ elem.getNodeName());
+ if (expectedType != null)
+ assertEquals(message + " type:", expectedType,
+ elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"));
+ if (expectedValue != null)
+ assertEquals(message + " value:", expectedValue,
+ DomUtil.getText(elem));
+ }
+
+
+ /**
+ * Asserts the name and type of a compound element, where the type is a Java classname.
+ */
+ private void assertContainerNameAndType(Element elem, String expectedName, Class<?> expectedType)
+ {
+ assertNameTypeValue("container", elem, expectedName, "java:" + expectedType.getName(), null);
+ }
+
+
+ /**
+ * A variety of assertions about added children. Assumes that we'll add
+ * a single child node per parent, and that we aren't using namespaces.
+ */
+ private void assertAppend(String message, Element parent,
+ String expectedName,
+ String expectedType,
+ String expectedValue)
+ {
+ assertChildCount(message, parent, 1);
+ assertNameTypeValue(message, DomUtil.getChildren(parent).get(0),
+ expectedName, expectedType, expectedValue);
+ }
+
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ // this test is essentially repeated in the DispatchSimpleValues tests
+ // it exists here as an initial verification of appended element structure
+ public void testDispatch() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", "bar", new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ assertAppend("", root, "foo", "", "bar");
+ }
+
+
+ public void testDispachWithNullName() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch(null, "bar", new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ assertAppend("", root, "data", "", "bar");
+ }
+
+
+ public void testNamespaceInheritance() throws Exception
+ {
+ Element root = DomUtil.newDocument("urn:zippy", "argle:bargle");
+ BeanOutputDriver.dispatch("foo", "bar", new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ List<Element> children = DomUtil.getChildren(root);
+ assertEquals("child count", 1, children.size());
+
+ Element child = children.get(0);
+ assertEquals("urn:zippy", child.getNamespaceURI());
+ assertEquals("argle", child.getPrefix());
+ assertEquals("foo", child.getLocalName());
+ }
+
+
+ public void testDispatchNullValue() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", null, new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ List<Element> children1 = DomUtil.getChildren(root);
+ assertEquals("null element added", 0, children1.size());
+
+ BeanOutputDriver.dispatch("foo", null, new BeanOutputHandler(root, BeanOutputOptions.XSI_NIL));
+ List<Element> children2 = DomUtil.getChildren(root);
+ assertEquals("null element added", 1, children2.size());
+ assertEquals("nil flag", "true",
+ children2.get(0).getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
+ }
+
+
+
+ public void testDispatchSimpleValuesWithDefaults() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
+ {
+ Object value = SIMPLE_VALUES[ii][0];
+ Element parent = DomUtil.appendChild(root, "value");
+ BeanOutputDriver.dispatch("foo", value, new BeanOutputHandler(parent));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+ assertAppend("value " + ii, parent, "foo", "", String.valueOf(value));
+ }
+ }
+
+
+ public void testDispatchSimpleValuesWithXSDFormatting() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
+ {
+ Element parent = DomUtil.appendChild(root, "value");
+ BeanOutputDriver.dispatch("foo", SIMPLE_VALUES[ii][0],
+ new BeanOutputHandler(parent, BeanOutputOptions.XSD_FORMAT));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+ assertAppend("value " + ii, parent, "foo", "", (String)SIMPLE_VALUES[ii][2]);
+ }
+ }
+
+
+ public void testDispatchSimpleValuesWithXSIType() throws Exception
+ {
+ Element root = DomUtil.newDocument("test");
+ for (int ii = 0 ; ii < SIMPLE_VALUES.length ; ii++)
+ {
+ Element parent = DomUtil.appendChild(root, "value");
+ BeanOutputDriver.dispatch("foo", SIMPLE_VALUES[ii][0],
+ new BeanOutputHandler(parent, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+ assertAppend("value " + ii, parent, "foo", (String)SIMPLE_VALUES[ii][1], (String)SIMPLE_VALUES[ii][2]);
+ }
+ }
+
+
+ public void testDispatchObjectArray() throws Exception
+ {
+ Object[] data = new String[] { "argle", "bargle" };
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data, new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ assertAppend("container", root, "foo", "", null);
+
+ Element container = DomUtil.getChild(root, "foo");
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "data", "", "argle");
+ assertNameTypeValue("child 1", children.get(1), "data", "", "bargle");
+
+ DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
+ DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
+ }
+
+
+ public void testDispatchObjectArrayWithType() throws Exception
+ {
+ Object[] data = new String[] { "argle", "bargle" };
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
+ assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
+
+ DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
+ DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
+ }
+
+
+ public void testDispatchPrimitiveArrayWithType() throws Exception
+ {
+ int[] data = new int[] { 1, 2, 3 };
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 3, children.size());
+ assertNameTypeValue("child 1", children.get(0), "data", "xsd:int", "1");
+ assertNameTypeValue("child 2", children.get(1), "data", "xsd:int", "2");
+ assertNameTypeValue("child 3", children.get(2), "data", "xsd:int", "3");
+
+ DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
+ DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
+ DomAsserts.assertEquals("child 3 index", "2", root, "/test/foo/data[3]/@index");
+ }
+
+
+ public void testDispatchListWithType() throws Exception
+ {
+ List<String> data = new ArrayList<String>();
+ data.add("argle");
+ data.add("bargle");
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
+ assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
+
+ DomAsserts.assertEquals("child 1 index", "0", root, "/test/foo/data[1]/@index");
+ DomAsserts.assertEquals("child 2 index", "1", root, "/test/foo/data[2]/@index");
+ }
+
+
+ public void testDispatchSetWithType() throws Exception
+ {
+ // use TreeSet so that order is guaranteed
+ Set<String> data = new TreeSet<String>();
+ data.add("bargle");
+ data.add("argle");
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "argle");
+ assertNameTypeValue("child 1", children.get(1), "data", "xsd:string", "bargle");
+
+ DomAsserts.assertEquals("child 1 index", "", root, "/test/foo/data[1]/@index");
+ DomAsserts.assertEquals("child 2 index", "", root, "/test/foo/data[2]/@index");
+ }
+
+
+ public void testDispatchMapWithDefaultFormat() throws Exception
+ {
+ // use TreeMap so that order is guaranteed
+ Map<String,Object> data = new TreeMap<String,Object>();
+ data.put("foo", Integer.valueOf(123));
+ data.put("argle", "bargle");
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "data", "xsd:string", "bargle");
+ assertNameTypeValue("child 1", children.get(1), "data", "xsd:int", "123");
+
+ DomAsserts.assertEquals("child 1 key", "argle", root, "/test/foo/data[1]/@key");
+ DomAsserts.assertEquals("child 2 key", "foo", root, "/test/foo/data[2]/@key");
+ }
+
+
+ public void testDispatchMapWithIntrospectFormat() throws Exception
+ {
+ // use TreeMap so that order is guaranteed
+ Map<String,Object> data = new TreeMap<String,Object>();
+ data.put("foo", Integer.valueOf(123));
+ data.put("argle", "bargle");
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", data,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE,
+ BeanOutputOptions.INTROSPECT_MAPS));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", data.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+ assertNameTypeValue("child 0", children.get(0), "argle", "xsd:string", "bargle");
+ assertNameTypeValue("child 1", children.get(1), "foo", "xsd:int", "123");
+
+ DomAsserts.assertEquals("child 1 key", "", root, "/test/foo/argle/@key");
+ DomAsserts.assertEquals("child 2 key", "", root, "/test/foo/foo/@key");
+ }
+
+
+ public void testDispatchSimpleBean() throws Exception
+ {
+ SimpleBean bean = new SimpleBean("zippy", 123, new BigDecimal("456.78"), true);
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", bean,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", bean.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 4, children.size());
+
+ Element child1 = (Element)(new XPathWrapper("//sval").evaluate(root).get(0));
+ assertNameTypeValue("sval", child1, "sval", "xsd:string", "zippy");
+
+ Element child2 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
+ assertNameTypeValue("ival", child2, "ival", "xsd:int", "123");
+
+ Element child3 = (Element)(new XPathWrapper("//dval").evaluate(root).get(0));
+ assertNameTypeValue("dval", child3, "dval", "xsd:decimal", "456.78");
+
+ Element child4 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
+ assertNameTypeValue("bval", child4, "bval", "xsd:boolean", "true");
+ }
+
+
+ public void testDispatchSimpleBeanIncludingNulls() throws Exception
+ {
+ SimpleBean bean = new SimpleBean();
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", bean,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE,
+ BeanOutputOptions.XSI_NIL));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", bean.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 4, children.size());
+
+ Element child1 = (Element)(new XPathWrapper("//sval").evaluate(root).get(0));
+ assertEquals("sval nil", "true", child1.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
+
+ Element child2 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
+ assertNameTypeValue("ival", child2, "ival", "xsd:int", "0");
+
+ Element child3 = (Element)(new XPathWrapper("//dval").evaluate(root).get(0));
+ assertEquals("dval nil", "true", child3.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"));
+
+ Element child4 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
+ assertNameTypeValue("bval", child4, "bval", "xsd:boolean", "false");
+ }
+
+
+ public void testDispatchSimpleBeanIgnoringNulls() throws Exception
+ {
+ SimpleBean bean = new SimpleBean();
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", bean,
+ new BeanOutputHandler(root, BeanOutputOptions.XSI_TYPE));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ Element container = DomUtil.getChild(root, "foo");
+ assertContainerNameAndType(container, "foo", bean.getClass());
+
+ List<Element> children = DomUtil.getChildren(container);
+ assertEquals("child count", 2, children.size());
+
+ Element child1 = (Element)(new XPathWrapper("//ival").evaluate(root).get(0));
+ assertNameTypeValue("ival", child1, "ival", "xsd:int", "0");
+
+ Element child2 = (Element)(new XPathWrapper("//bval").evaluate(root).get(0));
+ assertNameTypeValue("bval", child2, "bval", "xsd:boolean", "false");
+ }
+
+
+ public void testDispatchCompoundBean() throws Exception
+ {
+ CompoundBean bean = new CompoundBean(
+ new SimpleBean("zippy", 123, new BigDecimal("456.78"), true),
+ new int[] { 1, 2, 3 },
+ Arrays.asList("foo", "bar", "baz"));
+
+ // at this point, I'm convinced the type output works, so we'll do default
+ // output and then use XPath for all assertions
+
+ Element root = DomUtil.newDocument("test");
+ BeanOutputDriver.dispatch("foo", bean, new BeanOutputHandler(root));
+// System.out.println(OutputUtil.compactString(root.getOwnerDocument()));
+
+ DomAsserts.assertEquals("zippy", root, "/test/foo/simple/sval");
+ DomAsserts.assertEquals("123", root, "/test/foo/simple/ival");
+ DomAsserts.assertEquals("456.78", root, "/test/foo/simple/dval");
+ DomAsserts.assertEquals("true", root, "/test/foo/simple/bval");
+
+ DomAsserts.assertEquals("1", root, "/test/foo/primArray/data[1]");
+ DomAsserts.assertEquals("2", root, "/test/foo/primArray/data[2]");
+ DomAsserts.assertEquals("3", root, "/test/foo/primArray/data[3]");
+
+ DomAsserts.assertEquals("0", root, "/test/foo/primArray/data[1]/@index");
+ DomAsserts.assertEquals("1", root, "/test/foo/primArray/data[2]/@index");
+ DomAsserts.assertEquals("2", root, "/test/foo/primArray/data[3]/@index");
+
+ DomAsserts.assertEquals("foo", root, "/test/foo/stringList/data[1]");
+ DomAsserts.assertEquals("bar", root, "/test/foo/stringList/data[2]");
+ DomAsserts.assertEquals("baz", root, "/test/foo/stringList/data[3]");
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-15 16:50:31
|
Revision: 86
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=86&view=rev
Author: kdgregory
Date: 2009-07-15 16:50:25 +0000 (Wed, 15 Jul 2009)
Log Message:
-----------
update POM
Modified Paths:
--------------
branches/dev-1.1/pom.xml
Modified: branches/dev-1.1/pom.xml
===================================================================
--- branches/dev-1.1/pom.xml 2009-07-15 16:47:48 UTC (rev 85)
+++ branches/dev-1.1/pom.xml 2009-07-15 16:50:25 UTC (rev 86)
@@ -5,7 +5,7 @@
<groupId>net.sf.practicalxml</groupId>
<artifactId>practicalxml</artifactId>
<packaging>jar</packaging>
- <version>1.0.3</version>
+ <version>1.1-SNAPSHOT</version>
<name>practicalxml</name>
<url>http://sourceforge.net/projects/practicalxml/</url>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-15 16:47:49
|
Revision: 85
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=85&view=rev
Author: kdgregory
Date: 2009-07-15 16:47:48 +0000 (Wed, 15 Jul 2009)
Log Message:
-----------
add 1.1 development branch
Added Paths:
-----------
branches/dev-1.1/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-14 14:06:16
|
Revision: 84
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=84&view=rev
Author: kdgregory
Date: 2009-07-14 14:06:13 +0000 (Tue, 14 Jul 2009)
Log Message:
-----------
add XmlUtil.formatXsdDecimal()
Modified Paths:
--------------
trunk/pom.xml
trunk/src/main/java/net/sf/practicalxml/XmlUtil.java
trunk/src/test/java/net/sf/practicalxml/TestXmlUtil.java
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2009-07-14 12:26:58 UTC (rev 83)
+++ trunk/pom.xml 2009-07-14 14:06:13 UTC (rev 84)
@@ -5,7 +5,7 @@
<groupId>net.sf.practicalxml</groupId>
<artifactId>practicalxml</artifactId>
<packaging>jar</packaging>
- <version>1.0.2</version>
+ <version>1.0.3</version>
<name>practicalxml</name>
<url>http://sourceforge.net/projects/practicalxml/</url>
Modified: trunk/src/main/java/net/sf/practicalxml/XmlUtil.java
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-07-14 12:26:58 UTC (rev 83)
+++ trunk/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-07-14 14:06:13 UTC (rev 84)
@@ -15,6 +15,7 @@
package net.sf.practicalxml;
import java.text.DateFormat;
+import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@@ -99,6 +100,31 @@
/**
+ * Converts a Java <code>double</code> to a string, using the format
+ * specified by XML Schema for <code>decimal</code> elements. This
+ * method wraps the value and calls {@link #formatXsdDecimal(Number)},
+ * so call that method if you already have an object.
+ */
+ public static String formatXsdDecimal(double value)
+ {
+ return formatXsdDecimal(Double.valueOf(value));
+ }
+
+
+ /**
+ * Converts a Java <code>double</code> to a string, using the format
+ * specified by XML Schema for <code>decimal</code> elements. If
+ * passed <code>null</code>, returns an empty string
+ */
+ public static String formatXsdDecimal(Number value)
+ {
+ if (value == null)
+ return "";
+ return getXsdDecimalFormatter().format(value);
+ }
+
+
+ /**
* Parses an XML Schema <code>dateTime</code> object, accepting any of
* the legal formats. Note that this method can also be used to parse
* a generic ISO-8601 date.
@@ -231,6 +257,9 @@
private static ThreadLocal<DateFormat> _xsdDatetimeFormatter = new ThreadLocal<DateFormat>();
+ // used by getXsdDecimalFormatter()
+ private static ThreadLocal<DecimalFormat> _xsdDecimalFormatter = new ThreadLocal<DecimalFormat>();
+
/**
* Does the actual work of {@link isLegal(String)}.
*/
@@ -247,7 +276,8 @@
/**
- * Returns a DateFormat that will output our standard XSD dateTime format.
+ * Returns a DateFormat that will output the standard XSD dateTime format.
+ * This is managed as a ThreadLocal because formatters are not threadsafe.
*/
private static DateFormat getXsdDatetimeFormatter()
{
@@ -263,6 +293,30 @@
/**
+ * Returns a DecimalFormat that will output the standard XSD decimalformat.
+ * This is managed as a ThreadLocal because formatters are not threadsafe.
+ * <p>
+ * Note: output is limited to 17 digits to the right of the decimal point,
+ * because we assume a <code>double</code> input. For that reason, while
+ * you can use this method for <code>BigDecimal</code> values, that class'
+ * <code>toString()</code> is a better choice.
+ * <p>
+ * Note 2: there is no corresponding parse method; <code>Double.parseDouble()
+ * </code> will do the job for you.
+ */
+ private static DecimalFormat getXsdDecimalFormatter()
+ {
+ DecimalFormat format = _xsdDecimalFormatter.get();
+ if (format == null)
+ {
+ format = new DecimalFormat("#0.0################;-#");
+ _xsdDecimalFormatter.set(format);
+ }
+ return format;
+ }
+
+
+ /**
* Used by {@link parseXsdDatetime} to process individual fields of the
* dateTime string and store them into a calendar object. It expects to
* be called with <code>index</code> pointing to the start of the field,
Modified: trunk/src/test/java/net/sf/practicalxml/TestXmlUtil.java
===================================================================
--- trunk/src/test/java/net/sf/practicalxml/TestXmlUtil.java 2009-07-14 12:26:58 UTC (rev 83)
+++ trunk/src/test/java/net/sf/practicalxml/TestXmlUtil.java 2009-07-14 14:06:13 UTC (rev 84)
@@ -77,6 +77,17 @@
}
+ public void testFormatXsdDecimal() throws Exception
+ {
+ assertEquals("", XmlUtil.formatXsdDecimal(null));
+ assertEquals("0.0", XmlUtil.formatXsdDecimal(0));
+ assertEquals("1234.0", XmlUtil.formatXsdDecimal(1234));
+ assertEquals("-1234.0", XmlUtil.formatXsdDecimal(-1234));
+ assertEquals("1234.5", XmlUtil.formatXsdDecimal(1234.5));
+ assertEquals("1234567890.123456", XmlUtil.formatXsdDecimal(1234567890.123456));
+ }
+
+
public void testEscape() throws Exception
{
assertEquals("", XmlUtil.escape(null));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-07-14 12:27:03
|
Revision: 83
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=83&view=rev
Author: kdgregory
Date: 2009-07-14 12:26:58 +0000 (Tue, 14 Jul 2009)
Log Message:
-----------
add "converter" package (empty)
Added Paths:
-----------
trunk/src/main/java/net/sf/practicalxml/converter/
trunk/src/main/java/net/sf/practicalxml/converter/package.html
Added: trunk/src/main/java/net/sf/practicalxml/converter/package.html
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/converter/package.html (rev 0)
+++ trunk/src/main/java/net/sf/practicalxml/converter/package.html 2009-07-14 12:26:58 UTC (rev 83)
@@ -0,0 +1,6 @@
+<html>
+<body>
+ This package contains classes to convert between XML and a variety of
+ other formats.
+</body>
+</html>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|