org.jdom.contrib.beans
Class BeanMapper

java.lang.Object
  |
  +--org.jdom.contrib.beans.BeanMapper

public class BeanMapper
extends java.lang.Object

Maps a JavaBean to an XML tree and vice versa. (Yes, it's yet another XML Data Binding solution.) Given a JavaBean, it will produce a JDOM tree whose elements correspond to the bean's property values. Given a JDOM tree, it will return a new instance of that bean whose properties have been set using the corresponding values in the JDOM tree.

By default, it assumes each element maps to a property of the same name, subject to normal capitalization rules. That is, an element <foo> will map to the methods setFoo and getFoo. You can change this behavior by calling the various addMapping methods. For instance, to map a an element <date> to the property "birthDate" (using methods setBirthDate and getBirthDate), call

mapper.addMapping("birthDate", "date");
You can also map a property to an attribute, either of a child or of the parent (see JavaDoc for addMapping(String property, String element, String attribute) for details).

During Bean -> JDOM conversion, if a BeanInfo object is found, it will be respected. See JavaDoc for java.beans.Introspector.

If a given property, element, or attribute is to be skipped (ignored) during conversion, call the appropriate ignore method (ignoreProperty, ignoreElement, or ignoreAttribute). This is also appropriate if your bean has multiple accessors (properties) for the same underlying data.

Support for Namespaces is rudimentary at best and has not been well-tested; if you specify a Namespace then all created elements and attributes will be in that namespace (or all elements not in that namespace will be skipped, for JDOM->Bean mapping).

If a bean property type is a Java array, its items will be mapped to multiple child elements of the bean element (multiple children at the base level, not one child). This is to provide an easier transition for XML documents whose elements contain multiple children with the same name.

Please try this out on your own beans. If there is a case that fails to do what you like (for instance, properties with custom class types), let me know and I'll try to work it out.

TODO:
 support list properties (collections other than Java arrays)
 allow lists/arrays to map to either scattered elements or a single nested element
 sort XML elements in some order other than random BeanInfo order
 support for BeanInfoSearchPaths
 multiple packages searched for beans
 better support for Namespaces (hard)
 allow stringconverter to map object -> string (not just string -> object)
 id/idref support for cyclical references
 more type converters
 custom property converters
 known issue: inner class bean can't be found jdom->bean (workaround: define mapping containing class name)
 

Example:

TestBean

 public class TestBean implements java.io.Serializable {
    public String getName() { ... }
    public int getAge() { ... }
    public Date getBirthdate() { ... }
    public TestBean getFriend() { ... }
    public void setName(String name) { ... }
    public void setAge(int age) { ... }
    public void setBirthdate(Date birthdate) { ... }
    public void setFriend(TestBean friend) { ... }
    public String toString() { ... }
 }
 

XML Representation

 <testBean>
   <dob age="31">Fri Aug 08 00:00:00 EDT 1969</dob>
   <name>Alex</name>
   <friend>
     <testBean>
       <dob age="25">Thu May 01 00:00:00 EDT 1975</dob>
       <name>Amy</name>
     </testBean>
   </friend>
 </testBean>
 

Mapping code

 BeanMapper mapper = new BeanMapper();
 mapper.addMapping("birthdate", "dob");	// element mapping
 mapper.addMapping("age", "dob", "age");	// attribute mapping
 mapper.setBeanPackage("org.jdom.contrib.beans");
 

Converting Bean to JDOM

Document doc = mapper.toDocument(alex);

Converting JDOM to Bean

TestBean alex = mapper.toBean(doc);

Author:
Alex Chaffee (alex@jguru.com)

Inner Class Summary
 class BeanMapper.Mapping
           
 
Field Summary
protected  java.lang.String beanPackage
           
static int debug
           
protected  java.util.Set ignoredAttributes
           
protected  java.util.Set ignoredElements
           
protected  java.util.Set ignoredProperties
           
protected  boolean ignoreMissingProperties
           
protected  boolean ignoreNullProperties
           
protected  java.util.List mappings
           
protected  org.jdom.Namespace namespace
           
protected  StringConverter stringconverter
           
 
Constructor Summary
BeanMapper()
          Default constructor.
 
Method Summary
 void addMapping(BeanMapper.Mapping mapping)
           
 void addMapping(java.lang.String property, java.lang.Class type, java.lang.String element, java.lang.String attribute)
          Map a property name to an element or an attribute.
 void addMapping(java.lang.String property, java.lang.String element)
          Map a property name to an XML element
 void addMapping(java.lang.String property, java.lang.String element, java.lang.String attribute)
          Map a property name to an attribute in an XML element.
protected  java.lang.Object buildArray(java.beans.PropertyDescriptor property, java.util.List children)
           
protected  java.lang.Object convertJDOMValue(java.lang.Object value, java.lang.Class type)
           
protected  java.lang.Object convertString(java.lang.String value, java.lang.Class type)
           
protected  java.lang.Object convertValue(java.lang.Object value)
          convert property value (returned from getter) to a string or element or list
protected  org.jdom.Element createElement(java.lang.String elementName)
           
protected static void debug(java.lang.String msg)
           
protected  java.beans.PropertyDescriptor findPropertyDescriptor(java.lang.Object bean, java.lang.String propertyName)
           
static java.lang.Class getArrayItemClass(java.lang.Class arrayClass)
           
protected  java.lang.String getBeanClassName(java.lang.String beanPackage, java.lang.String elementName)
           
 BeanMapper.Mapping getMappingForAttribute(java.lang.String element, java.lang.String attribute)
           
 BeanMapper.Mapping getMappingForElement(java.lang.String element)
           
 BeanMapper.Mapping getMappingForProperty(java.lang.String property)
           
 StringConverter getStringConverter()
          Get the object responsible for converting a string to a known type.
 void ignoreAttribute(java.lang.String element, java.lang.String attribute)
           
 void ignoreElement(java.lang.String element)
           
 void ignoreProperty(java.lang.String property)
           
protected  java.lang.Object instantiateBean(java.lang.String elementName)
          return a fresh new object of the appropriate bean type for the given element name.
 boolean isIgnoredAttribute(java.lang.String element, java.lang.String attribute)
           
 boolean isIgnoredElement(java.lang.String element)
           
 boolean isIgnoredProperty(java.lang.String property)
           
 void setBeanPackage(java.lang.String beanPackage)
           
protected  void setElementValue(java.lang.String propertyName, java.lang.String elementName, org.jdom.Element parent, org.jdom.Element child, java.lang.Object value)
           
 void setIgnoreMissingProperties(boolean b)
          In mapping from JDOM->Bean, if we encounter an element or attribute without a corresponding property in the bean, should we ignore it or throw an exception? Default: false
 void setIgnoreNullProperties(boolean b)
          In mapping from Bean->JDOM, if we encounter an property with a null value, should we ignore it or add an empty child element/attribute? Default: true
 void setNamespace(org.jdom.Namespace namespace)
          Use this namespace when creating the XML element and all child elements.
protected  boolean setProperty(java.lang.Object bean, java.beans.PropertyDescriptor property, org.jdom.Element parent, java.lang.Object value)
          set a property in the bean
protected  boolean setProperty(java.lang.Object bean, java.lang.String propertyName, java.lang.Object value)
          set a property in the bean
 void setStringConverter(StringConverter stringconverter)
          Set a custom string converter.
protected static java.lang.String toAttributeString(java.lang.String element, java.lang.String attribute)
           
 java.lang.Object toBean(org.jdom.Document document)
          Converts the given JDOM Document to a bean
 java.lang.Object toBean(org.jdom.Element element)
           
 org.jdom.Document toDocument(java.lang.Object bean)
          Converts the given bean to a JDOM Document.
 org.jdom.Document toDocument(java.lang.Object bean, java.lang.String elementName)
          Converts the given bean to a JDOM Document.
 org.jdom.Element toElement(java.lang.Object bean)
          Converts the given bean to a JDOM Element.
 org.jdom.Element toElement(java.lang.Object bean, java.lang.String elementName)
          Converts the given bean to a JDOM Element.
protected static java.lang.String unpackage(java.lang.String classname)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

beanPackage

protected java.lang.String beanPackage

namespace

protected org.jdom.Namespace namespace

ignoreMissingProperties

protected boolean ignoreMissingProperties

ignoreNullProperties

protected boolean ignoreNullProperties

mappings

protected java.util.List mappings

stringconverter

protected StringConverter stringconverter

ignoredProperties

protected java.util.Set ignoredProperties

ignoredElements

protected java.util.Set ignoredElements

ignoredAttributes

protected java.util.Set ignoredAttributes

debug

public static int debug
Constructor Detail

BeanMapper

public BeanMapper()
Default constructor. If you are only doing bean -> XML mapping, you may use the mapper immediately. Otherwise, you must call setBeanPackage.
Method Detail

setBeanPackage

public void setBeanPackage(java.lang.String beanPackage)
Parameters:
beanPackage - the name of the package in which to find the JavaBean classes to instantiate

setNamespace

public void setNamespace(org.jdom.Namespace namespace)
Use this namespace when creating the XML element and all child elements.

getStringConverter

public StringConverter getStringConverter()
Get the object responsible for converting a string to a known type. Once you get this, you can call its setFactory() method to add a converter for a custom type (for which toString() does not suffice). The default string converter has a factory that recognizes several date formats (including ISO8601 - e.g. "2000-09-18 18:51:22-0600" or some substring thereof).

setStringConverter

public void setStringConverter(StringConverter stringconverter)
Set a custom string converter.

setIgnoreNullProperties

public void setIgnoreNullProperties(boolean b)
In mapping from Bean->JDOM, if we encounter an property with a null value, should we ignore it or add an empty child element/attribute? Default: true
Parameters:
b - true = ignore, false = empty element

setIgnoreMissingProperties

public void setIgnoreMissingProperties(boolean b)
In mapping from JDOM->Bean, if we encounter an element or attribute without a corresponding property in the bean, should we ignore it or throw an exception? Default: false
Parameters:
b - true = ignore, false = throw exception

toDocument

public org.jdom.Document toDocument(java.lang.Object bean)
                             throws BeanMapperException
Converts the given bean to a JDOM Document.
Parameters:
bean - the bean from which to extract values

toDocument

public org.jdom.Document toDocument(java.lang.Object bean,
                                    java.lang.String elementName)
                             throws BeanMapperException
Converts the given bean to a JDOM Document.
Parameters:
bean - the bean from which to extract values
name - the name of the root element (null => use bean class name)

toElement

public org.jdom.Element toElement(java.lang.Object bean)
                           throws BeanMapperException
Converts the given bean to a JDOM Element.
Parameters:
bean - the bean from which to extract values
elementName - the name of the element (null => use bean class name)

toElement

public org.jdom.Element toElement(java.lang.Object bean,
                                  java.lang.String elementName)
                           throws BeanMapperException
Converts the given bean to a JDOM Element.
Parameters:
bean - the bean from which to extract values
elementName - the name of the element (null => use bean class name)

convertValue

protected java.lang.Object convertValue(java.lang.Object value)
                                 throws BeanMapperException
convert property value (returned from getter) to a string or element or list

setElementValue

protected void setElementValue(java.lang.String propertyName,
                               java.lang.String elementName,
                               org.jdom.Element parent,
                               org.jdom.Element child,
                               java.lang.Object value)
                        throws BeanMapperException

toBean

public java.lang.Object toBean(org.jdom.Document document)
                        throws BeanMapperException
Converts the given JDOM Document to a bean
Parameters:
document - the document from which to extract values

toBean

public java.lang.Object toBean(org.jdom.Element element)
                        throws BeanMapperException

instantiateBean

protected java.lang.Object instantiateBean(java.lang.String elementName)
                                    throws BeanMapperException
return a fresh new object of the appropriate bean type for the given element name.
Returns:
the bean

getBeanClassName

protected java.lang.String getBeanClassName(java.lang.String beanPackage,
                                            java.lang.String elementName)

findPropertyDescriptor

protected java.beans.PropertyDescriptor findPropertyDescriptor(java.lang.Object bean,
                                                               java.lang.String propertyName)
                                                        throws BeanMapperException

setProperty

protected boolean setProperty(java.lang.Object bean,
                              java.lang.String propertyName,
                              java.lang.Object value)
                       throws BeanMapperException
set a property in the bean
Parameters:
bean - the bean to modify
propertyName - the name of the property to set
value - the new value
Returns:
true if successful, false if property not found

setProperty

protected boolean setProperty(java.lang.Object bean,
                              java.beans.PropertyDescriptor property,
                              org.jdom.Element parent,
                              java.lang.Object value)
                       throws BeanMapperException
set a property in the bean
Parameters:
bean - the bean to modify
property - the property to set
value - the new value
Returns:
true if successful, false if property not found

convertString

protected java.lang.Object convertString(java.lang.String value,
                                         java.lang.Class type)

convertJDOMValue

protected java.lang.Object convertJDOMValue(java.lang.Object value,
                                            java.lang.Class type)
                                     throws BeanMapperException

buildArray

protected java.lang.Object buildArray(java.beans.PropertyDescriptor property,
                                      java.util.List children)
                               throws BeanMapperException
Returns:
an array of the appropriate type

getArrayItemClass

public static java.lang.Class getArrayItemClass(java.lang.Class arrayClass)
                                         throws java.lang.ClassNotFoundException

addMapping

public void addMapping(java.lang.String property,
                       java.lang.String element)
Map a property name to an XML element
Parameters:
property - the name of the property
element - the name of the element

addMapping

public void addMapping(java.lang.String property,
                       java.lang.String element,
                       java.lang.String attribute)
Map a property name to an attribute in an XML element. If element is null, it's an attribute on the parent element (e.g. <myBean id="123">); otherwise, it's an attribute on a child element (e.g. <myBean><thing id="123">).
Parameters:
property - the name of the property
element - the name of the element containing the attribute. null => parent element
attribute - the name of the attribute. null => set as element

addMapping

public void addMapping(java.lang.String property,
                       java.lang.Class type,
                       java.lang.String element,
                       java.lang.String attribute)
Map a property name to an element or an attribute. Can also specify which bean class to instantiate (applies to JDOM->Bean mapping).
Parameters:
property - the name of the property. null => look for property with same name as the element
type - Always convert this element name to this class. null => look for a bean with the same name as the element
element - the name of the element containing the attribute. null => parent element
attribute - the name of the attribute. null => set as element

addMapping

public void addMapping(BeanMapper.Mapping mapping)

getMappingForProperty

public BeanMapper.Mapping getMappingForProperty(java.lang.String property)

getMappingForElement

public BeanMapper.Mapping getMappingForElement(java.lang.String element)

getMappingForAttribute

public BeanMapper.Mapping getMappingForAttribute(java.lang.String element,
                                                 java.lang.String attribute)

ignoreProperty

public void ignoreProperty(java.lang.String property)

isIgnoredProperty

public boolean isIgnoredProperty(java.lang.String property)

ignoreElement

public void ignoreElement(java.lang.String element)

isIgnoredElement

public boolean isIgnoredElement(java.lang.String element)

toAttributeString

protected static java.lang.String toAttributeString(java.lang.String element,
                                                    java.lang.String attribute)

ignoreAttribute

public void ignoreAttribute(java.lang.String element,
                            java.lang.String attribute)

isIgnoredAttribute

public boolean isIgnoredAttribute(java.lang.String element,
                                  java.lang.String attribute)

createElement

protected org.jdom.Element createElement(java.lang.String elementName)

unpackage

protected static java.lang.String unpackage(java.lang.String classname)

debug

protected static void debug(java.lang.String msg)


Copyright © 2004 Jason Hunter, Brett McLaughlin. All Rights Reserved.