[Practicalxml-commits] SF.net SVN: practicalxml:[140] branches/dev-1.1/src
Brought to you by:
kdgregory
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-18 18:46:45
|
Revision: 140 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=140&view=rev Author: kdgregory Date: 2009-09-18 18:45:53 +0000 (Fri, 18 Sep 2009) Log Message: ----------- BeanConverter now contains only static methods, is a facade Renamed Bean2XmlDriver and Xml2BeanDriver to XXXConverter Moved conversion docs into package 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/bean/Bean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/package.html branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestXml2BeanConverter.java Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestXml2BeanDriver.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-09-18 15:51:32 UTC (rev 139) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-09-18 18:45:53 UTC (rev 140) @@ -17,175 +17,32 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import net.sf.practicalxml.converter.bean.Bean2XmlDriver; +import net.sf.practicalxml.converter.bean.Bean2XmlConverter; import net.sf.practicalxml.converter.bean.Bean2XmlOptions; -import net.sf.practicalxml.converter.bean.Xml2BeanDriver; +import net.sf.practicalxml.converter.bean.Xml2BeanConverter; import net.sf.practicalxml.converter.bean.Xml2BeanOptions; /** * Converts Java objects (not just beans) to or from an XML representation. * Originally developed to support simple web services, without the overhead - * (schema definitions and/or annotations) required by JAXB. + * (schema definitions and/or annotations) required by JAXB. See the {@link + * net.sf.practicalxml.converter.bean package docs} for specifics. * <p> - * A single instance is intended for conversions in one direction only. This - * is a consequence of specifying options as varargs, but fits well with - * "normal" application design, in which input and output are handled by - * different parts of the code. You won't get an error if you try to convert - * the "wrong" way, you'll simply get default behavior. Note that, depending - * on options settings, output generated by one converter may not be valid - * input for another. + * This class provides static facade methods for + * {@link net.sf.practicalxml.converter.bean.Bean2XmlConverter} and + * {@link net.sf.practicalxml.converter.bean.Xml2BeanConverter}. If static + * methods and throwaway objects offend you then use those classes directly. * <p> - * The basic structure of XML produced/consumed by this class is that the - * root element represents the object being converted, and its child nodes - * represent the elements/properties of the object. Nodes representing complex - * objects have child elements, those representing simple (primitive) objects - * have a single text child. Objects are processed recursively, and cycles are - * <em>not</em> detected (although this may change). - * <p> - * A namespace and qualified name may be provided to {@link #convertToXml}, - * and all elements will inherit the namespace and prefix. Namespaces are - * ignored on input; all property matches uses the element's local name. - * <p> - * Each element may have an <code>xsi:type</code> attribute (where <code>xsi - * </code> references to the XML Schema instance namespace). This attribute - * is optional for both output and input; if used for output, it is merely - * informational, but for input will be examined to validate that the XML is - * appropriate for the desired object type. For primitive types, wrappers, - * and strings, it takes the form "<code>xsd:TYPE</code>", where <code>TYPE - * </code> is one of the simple types defined by XML schema. For other Java - * types, it takes the form "<code>java:TYPE</code>", where <code>TYPE</code> - * is the fully qualified Java classname. - * <p> - * On input, the desired type is specified by the caller or by introspection - * (except in the case of collection elements; see below). The <code>xsi:type - * </code> value, if any, is ignored except for validation. - * <p> - * Additional conversion rules are as follows: - * - * <table border="1"> - * <tr><th>Java Object Type - * <th>{@link #convertToXml} - * <th>{@link #convertToJava} - * <tr><td>Primitives, Wrapper objects, and String - * <td> - * <td> - * <tr><td>Arrays - * <td>Elements of the array are written in sequence to the DOM, using the - * element name "<code>data</code>". Elements are given an attribute - * named "<code>index</code>", which contains the element's position - * within the array. - * <td>Elements of the array are processed in sequence, ignoring both - * element name and "index" attribute. - * <tr><td>Lists and Sets - * <td>The collection is iterated, and elements are written in sequence to - * the DOM, using the element name "<code>data</code>". Elements are - * given an attribute named "<code>index</code>", which contains the - * element's position within the iteration (meaningful only for lists). - * <td>Elements of the are processed in sequence, ignoring both element - * name and "index" attribute. - * <p> - * If an <code>xsi:type</code> attribute is present, it will be used - * to drive conversion of the element. Otherwise, the element will be - * converted as a <code>String</code> (which will fail for complex - * types, because string conversion assumes a single text node). - * <p> - * Where the caller specifies an interface as the conversion class, the - * converter will choose an appropriate implementation class: - * <ul> - * <li> <code>ArrayList</code> for <code>List</code> or <code>Collection</code> - * <li> <code>TreeSet</code> for <code>SortedSet</code> - * <li> <code>HashSet</code> for <code>Set</code> - * </ul> - * <tr><td>Maps - * <td>The collection is iterated, and elements are written in sequence to - * the DOM. Depending on the output options, either the entry key will - * be used as the element name, or the name will be "<code>data</code>" - * and the key stored in an attribute named "<code>key</code>". The - * former option is only permitted if all keys in the map are valid - * XML element names; otherwise the converter will throw. - * <td>Elements are processed in sequence. The converter first looks for - * a "<code>key</code>" attribute, and will use it as the entry key - * if found. Otherwise, it will use the element name. If your maps - * are being reduced to a single entry, look for a missing attribute. - * <p> - * If an <code>xsi:type</code> attribute is present, it will be used - * to drive conversion of the element. Otherwise, the element will be - * converted as a <code>String</code> (which will fail for complex - * types, because string conversion assumes a single text node). - * <p> - * Where the caller specifies an interface as the conversion class, - * the converter will choose an appropriate implementation class: - * <code>TreeMap</code> for <code>SortedMap</code>, and <code>HashMap - * </code> for <code>Map</code>. - * <tr><td>Bean-structured Objects - * <td>The object is introspected, and properties are written in the order - * provided by the <code>Introspector</code>. - * <td>The bean class must provide a no-argument constructor (otherwise it - * doesn't follow the bean spec, and we can't use it). - * <p> - * The converter relies on <code>java.beans.Introspector</code> to find - * property setter methods for an object. If the object provides - * multiple methods for the property, the converter will use whichever - * one the introspector provides. - * <p> - * Elements are processed in order, and the element's localname is used - * to find the associated object property. If the XML does not contain - * an element corresponding to a bean property, that property is left - * with its default value (ie, we don't try to find an element based - * on property name). - * <p> - * If the XML contains an element that does not correspond to any bean - * property, the converter will either throw or ignore the element, - * depending on options settings. - * <tr><td>Other Objects - * <td>not supported - * <td>not supported - * </table> - * * <strong>Warning</strong>: - * <code>java.beans.Introspector</code> holds a cache of introspected objects. - * If you use this converter in an app-server you should call - * <code>Introspector.flushCaches()</code> during deploy. + * Bean-to-XML conversion uses <code>java.beans.Introspector</code>, which + * holds a cache of introspected objects. If you use this conversion in an + * app-server you should call <code>Introspector.flushCaches()</code> during + * deploy. */ public class BeanConverter { - private Bean2XmlDriver _outputDriver; - private Xml2BeanDriver _inputDriver; - - /** - * Creates an instance with all options disabled. This can be used for - * conversions in either direction, and is meant primarily for testing. - */ - public BeanConverter() - { - _outputDriver = new Bean2XmlDriver(); - _inputDriver = new Xml2BeanDriver(); - } - - - /** - * Creates an instance to be used for Bean -> XML conversion, - */ - public BeanConverter(Bean2XmlOptions... options) - { - _outputDriver = new Bean2XmlDriver(options); - _inputDriver = new Xml2BeanDriver(); - } - - - /** - * Creates an instance to be used for XML -> Bean conversion. - */ - public BeanConverter(Xml2BeanOptions options) - { - _outputDriver = new Bean2XmlDriver(); - _inputDriver = new Xml2BeanDriver(options); - } - - - /** * Creates a new DOM document from the passed bean, in which all elements * are members of the specified namespace and will inherit the root's * prefix (if any). @@ -197,10 +54,13 @@ * @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 Conversion options. */ - public Document convertToXml(Object bean, String nsUri, String rootName) + public static Document convertToXml( + Object bean, String nsUri, String rootName, Bean2XmlOptions... options) { - return _outputDriver.convert(bean, nsUri, rootName) + return new Bean2XmlConverter(options) + .convert(bean, nsUri, rootName) .getOwnerDocument(); } @@ -212,10 +72,13 @@ * bean, collection, or simple type. * @param rootName The name given to the root element of the produced * document. + * @param options Conversion options. */ - public Document convertToXml(Object bean, String rootName) + public static Document convertToXml( + Object bean, String rootName, Bean2XmlOptions... options) { - return _outputDriver.convert(bean, rootName) + return new Bean2XmlConverter(options) + .convert(bean, rootName) .getOwnerDocument(); } @@ -227,10 +90,12 @@ * @param dom The source document. * @param klass The desired class to instantiate and fill from this * document. + * @param options Conversion options. */ - public <T> T convertToJava(Document dom, Class<T> klass) + public static <T> T convertToJava( + Document dom, Class<T> klass, Xml2BeanOptions... options) { - return convertToJava(dom.getDocumentElement(), klass); + return convertToJava(dom.getDocumentElement(), klass, options); } @@ -243,9 +108,11 @@ * root element of its document. * @param klass The desired class to instantiate and fill from this * document. + * @param options Conversion options. */ - public <T> T convertToJava(Element root, Class<T> klass) + public static <T> T convertToJava( + Element root, Class<T> klass, Xml2BeanOptions... options) { - return _inputDriver.convert(root, klass); + return new Xml2BeanConverter(options).convert(root, klass); } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-09-18 15:51:32 UTC (rev 139) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-09-18 18:45:53 UTC (rev 140) @@ -25,7 +25,7 @@ /** * Packaging class used for XML output appenders. This class is a temporary - * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained + * hack, as I move intelligence into {@link Bean2XmlConverter}; the contained * classes will end up in a new package, once I figure out what the package * structure should be. */ Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java (from rev 130, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java 2009-09-18 18:45:53 UTC (rev 140) @@ -0,0 +1,253 @@ +// 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.bean; + +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.bean.Bean2XmlAppenders.*; +import net.sf.practicalxml.converter.internal.ConversionStrings; +import net.sf.practicalxml.converter.internal.DomUtilToo; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; + + +/** + * 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 Bean2XmlConverter +{ + private PrimitiveConversionHelper _helper; + private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); + + public Bean2XmlConverter(Bean2XmlOptions... options) + { + for (Bean2XmlOptions option : options) + _options.add(option); + _helper = 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); + doXsiNamespaceHack(root); + 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.ADD_XSI_TYPE); + } + + + /** + * 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.ADD_XSI_TYPE)) + { + DomUtilToo.setXsiNil(root, false); + } + } + + + private boolean tryToConvertAsPrimitiveOrNull( + Object obj, Class<?> klass, String name, Appender appender) + { + if (obj != null) + klass = obj.getClass(); + + String objType = _helper.getXsdType(klass); + if ((obj == null) || (objType != null)) + { + appender.appendValue(name, objType, _helper.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, DomUtilToo.getXsiTypeForJavaObject(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, ConversionStrings.EL_COLLECTION_ITEM, childAppender); + } + return true; + } + + + private boolean tryToConvertAsMap(Object obj, String name, Appender appender) + { + if (!(obj instanceof Map)) + return false; + + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(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, DomUtilToo.getXsiTypeForJavaObject(obj)); + Appender childAppender = new IndexedAppender(parent, _options); + for (Object value : (Collection<?>)obj) + { + convert(value, ConversionStrings.EL_COLLECTION_ITEM, childAppender); + } + return true; + } + + + private boolean tryToConvertAsBean(Object bean, String name, Appender appender) + { + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(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/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-09-18 15:51:32 UTC (rev 139) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-09-18 18:45:53 UTC (rev 140) @@ -1,253 +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.bean; - -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.bean.Bean2XmlAppenders.*; -import net.sf.practicalxml.converter.internal.ConversionStrings; -import net.sf.practicalxml.converter.internal.DomUtilToo; -import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; - - -/** - * 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 PrimitiveConversionHelper _helper; - private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); - - public Bean2XmlDriver(Bean2XmlOptions... options) - { - for (Bean2XmlOptions option : options) - _options.add(option); - _helper = 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); - doXsiNamespaceHack(root); - 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.ADD_XSI_TYPE); - } - - - /** - * 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.ADD_XSI_TYPE)) - { - DomUtilToo.setXsiNil(root, false); - } - } - - - private boolean tryToConvertAsPrimitiveOrNull( - Object obj, Class<?> klass, String name, Appender appender) - { - if (obj != null) - klass = obj.getClass(); - - String objType = _helper.getXsdType(klass); - if ((obj == null) || (objType != null)) - { - appender.appendValue(name, objType, _helper.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, DomUtilToo.getXsiTypeForJavaObject(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, ConversionStrings.EL_COLLECTION_ITEM, childAppender); - } - return true; - } - - - private boolean tryToConvertAsMap(Object obj, String name, Appender appender) - { - if (!(obj instanceof Map)) - return false; - - Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(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, DomUtilToo.getXsiTypeForJavaObject(obj)); - Appender childAppender = new IndexedAppender(parent, _options); - for (Object value : (Collection<?>)obj) - { - convert(value, ConversionStrings.EL_COLLECTION_ITEM, childAppender); - } - return true; - } - - - private boolean tryToConvertAsBean(Object bean, String name, Appender appender) - { - Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(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/bean/Xml2BeanConverter.java (from rev 130, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java 2009-09-18 18:45:53 UTC (rev 140) @@ -0,0 +1,396 @@ +// 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.bean; + +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 net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.ConversionStrings; +import net.sf.practicalxml.converter.internal.DomUtilToo; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; +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. 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 Xml2BeanConverter +{ + private EnumSet<Xml2BeanOptions> _options; + private PrimitiveConversionHelper _helper; + private Map<Class<?>,Map<String,Method>> _introspectedClasses; + + + public Xml2BeanConverter(Xml2BeanOptions... options) + { + _options = EnumSet.noneOf(Xml2BeanOptions.class); + for (Xml2BeanOptions option : options) + _options.add(option); + + _helper = new PrimitiveConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT)); + _introspectedClasses = new HashMap<Class<?>,Map<String,Method>>(); + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + /** + * Attempts to convert the passed DOM subtree into an object of the + * specified class. + */ + 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)) + { + if (!DomUtilToo.getXsiNil(elem)) + throw new ConversionException("missing/false xsi:nil", 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", 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(ConversionStrings.AT_MAP_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; + } + + + /** + * 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 = DomUtilToo.getXsiType(elem); + if (xsiType == null) + return null; + + String javaType = DomUtilToo.getJavaClassFromXsiType(xsiType); + if (javaType != null) + { + try + { + return Class.forName(javaType); + } + catch (ClassNotFoundException ee) + { + throw new ConversionException( + "invalid Java type specification: " + javaType, elem, ee); + } + } + + return _helper.getJavaType(xsiType); + } + + + private void validateXsiType(Element elem, Class<?> klass) + { + if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE)) + return; + + String xsiType = DomUtilToo.getXsiType(elem); + if (xsiType == null) + throw new ConversionException("missing xsi:type", 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(), + 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", 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 ee) + { + throw new ConversionException("unable to introspect", ee); + } + + _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", 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", elem, ee); + } + } +} Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-09-18 15:51:32 UTC (rev 139) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-09-18 18:45:53 UTC (rev 140) @@ -1,396 +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.bean; - -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 net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.internal.ConversionStrings; -import net.sf.practicalxml.converter.internal.DomUtilToo; -import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; -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. 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 Xml2BeanDriver -{ - private EnumSet<Xml2BeanOptions> _options; - private PrimitiveConversionHelper _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 PrimitiveConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT)); - _introspectedClasses = new HashMap<Class<?>,Map<String,Method>>(); - } - - -//---------------------------------------------------------------------------- -// Public Methods -//---------------------------------------------------------------------------- - - /** - * Attempts to convert the passed DOM subtree into an object of the - * specified class. - */ - 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)) - { - if (!DomUtilToo.getXsiNil(elem)) - throw new ConversionException("missing/false xsi:nil", 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", 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(ConversionStrings.AT_MAP_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; - } - - - /** - * 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 = DomUtilToo.getXsiType(elem); - if (xsiType == null) - return null; - - String javaType = DomUtilToo.getJavaClassFromXsiType(xsiType); - if (javaType != null) - { - try - { - return Class.forName(javaType); - } - catch (ClassNotFoundException ee) - { - throw new ConversionException( - "invalid Java type specification: " + javaType, elem, ee); - } - } - - return _helper.getJavaType(xsiType); - } - - - private void validateXsiType(Element elem, Class<?> klass) - { - if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE)) - return; - - String xsiType = DomUtilToo.getXsiType(elem); - if (xsiType == null) - throw new ConversionException("missing xsi:type", 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(), - 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", 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 ee) - { - throw new ConversionException("unable to introspect", ee); - } - - _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(); - } - ... [truncated message content] |