commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rdon...@apache.org
Subject cvs commit: jakarta-commons/betwixt/xdocs/guide binding.xml
Date Thu, 14 Aug 2003 21:25:26 GMT
rdonkin     2003/08/14 14:25:26

  Added:       betwixt/xdocs/guide binding.xml
  Log:
  Split Overview into separate documents in guide directory.
  
  Revision  Changes    Path
  1.1                  jakarta-commons/betwixt/xdocs/guide/binding.xml
  
  Index: binding.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
  
   <properties>
    <title>Binding Bean To XML</title>
    <author email="jstrachan@apache.org">James Strachan</author>
   </properties>
  
  <body>
  
  <section name="Bean Naming Conventions">
  
      <p>The Java Beans specification contains various naming conventions that should

      be used when writing beans that will allow the beans introspector to 
      automatically guess the properties in a bean and their getters, their
      setter methods etc. Betwixt will use these same naming conventions to deduce how to
make the 
      beans appear as XML. There are some other naming conventions that you can use to 
      make your beans easier to output as XML or parse.
      </p>
      
      <p>
      One common requirement when mapping beans to xml is that the property and type names
from the bean 
      must be processed (in some way) before they are used in the xml. For example, a property

      called <code>WebApp</code> might need to be mapped to an element called
<code>web-app</code>.
      </p>
      
      <p>
      Betwixt supports customization of these mappings through plug-in implementations of
the 
      <code>org.apache.commons.betwixt.strategy.NameMapper</code> interface. It
is often useful to allow
      different mappings for elements and attribute and so different implementations can be
set for 
      elements and attributes. The default NameMapper implementation simply returns the type
name 
      without modification.
      </p>
      
      <p>
      <strong>Note</strong> that the attribute and element names given in a .betwixt
file (as usual)
      override the name mapping settings on the <code>XMLIntrotrospector</code>.
      </p>
  
  <subsection name="Using A Custom Type Name To Element Name Mapping">
  
      <p>
      Betwixt supports pluggable conversion of type names to element names. Setting the 
      <code>ElementNameMapper</code> property on an <code>XMLIntrospector</code>
determines
      how names from the bean will be converted into element names.
      </p>
  
  </subsection>
  
  
  <subsection name="Using A Custom Property Name To Attribute Name Mapping">
  
      <p>
      Betwixt supports pluggable conversion of type names to attribute names. Setting the

      <code>AttributeNameMapper</code> property on an <code>XMLIntrospector</code>
determines
      how names from the bean will be converted into attribute names.
      </p>
  
  </subsection>
  
  <subsection name="Custom Mapping Example">
  
      <p>
      Here's a simple bean which will be mapped to xml:
      
  <source><![CDATA[
  public class TallTreeBean {
  
      private float heightOfTree;
      
      public TallTreeBean(float height) {
          setHeightOfTree(height);
      }
      
      public float getHeightOfTree() {
          return heightOfTree;
      }	
      
      public void setHeightOfTree(float heightOfTree) {
          this.heightOfTree = heightOfTree;
      }
  }	
  ]]></source>
  
      </p>
      <p>
      Next is an application that writes that bean to xml. Custom name mappers for elements
      and attributes are set.
      
  <source><![CDATA[
  import org.apache.commons.betwixt.io.BeanWriter;
  import org.apache.commons.betwixt.strategy.DecapitalizeNameMapper;
  import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
  
  public class NameMapperExampleApp {
      
      public static final void main(String args[]) throws Exception{
          
          // create write and set basic properties
  	BeanWriter writer = new BeanWriter();
          writer.getXMLIntrospector().setAttributesForPrimitives(true);
          writer.enablePrettyPrint();
          writer.setWriteIDs(false);
          
          // set a custom name mapper for attributes
          writer.getXMLIntrospector().setAttributeNameMapper(new HyphenatedNameMapper());
          // set a custom name mapper for elements
          writer.getXMLIntrospector().setElementNameMapper(new DecapitalizeNameMapper());
          
          // write out the bean
          writer.write(new TallTreeBean(15.1f));
          System.out.println("");
      }
      
  }
  ]]></source>
      </p>
      
      <p>
      The application should print out (to System.out) an xml fragment which looks like:
      
  <source><![CDATA[
  <tallTreeBean height-of-tree="15.1"/>
  ]]></source>
      
      </p>
      <p>
      As you can see, the first letter of the element name has been decapitalized and the

      capitals in the property separated by hyphens after being converted to lower case.
      </p>
  </subsection>
  
  </section>
  
  <section name="Using Adder Methods For Composite Properties">
  
      <p>
      This naming convention is used to indicate the singular type of some composite property.
      </p>
      
      <p>
      To use: create an add method to match the getter method for 'composite 
      properties'.
      </p>
  
  <source><![CDATA[public class SomeBean {
      public <CollectionType> getFoo*();
      public void addFoo(<SingularType> foo);
  }]]></source>
  
      <p>
      Where CollectionType can be an array, a Collection, Enumeration, Iterator, 
      Map. The [SinglularType] refers to the type of an item in the collection. The 
      name of the getter property starts with 'Foo'. So 'Foo' is the singular name, 
      the plural collection name could be Foos, FooArray, FooList, FooIterator or some 
      other encoding, though the plural name should start with the singular name for 
      auto-detection to work properly.
      </p>
  
  <subsection name="Using A Custom Plural Stemmer">
      <p>
      Betwixt allows this auto-detection of plurals from singulars to be customized.
      Implementations of <code>org.apache.commons.betwixt.PluralStemmer</code>
allow different
      strategies for this mapping to be plugged into <code>XMLIntrospector</code>.
      The strategy used by <code>XMLIntrospector</code> to match singlular properties
and plural methods
      is determined by the <code>PluralStemmer</code> property value.
      </p>
  
      <p>
      One important usage of custom plural stemmers is to support classes with non-english
method names.
      A custom <code>PluralStemmer</code> implementation can be created containing
the plural rules for
      the language. Betwixt will then be able to recognize matching plural and singular methods.
      </p>
  
      <p>
      The default implementation supports common english plural patterns and then falls back
to finding
      any property that starts with the singular name. For example, it will match a plural
property called
      <code>FooBars</code> for a singular property called <code>FooBar</code>.

      </p>
  </subsection>
  
  <subsection name="Reading And Writing Map Properties">
      <p>
  Maps are a special kind of composite property. Each entry in a map has a key and a value.

  Betwixt handles maps by adding extra elements which wrap each entry. Each entry is wrapped
in
  a <code>&lt;entry&gt;</code> element. That element contains the key
wrapped in a <code>&lt;key&gt;</code>
  element and the entry value wrapped in a <code>&lt;value&gt;</code>
element.
          </p>
      <p>
  The structure is something like:
  <source><![CDATA[
      ...
      <entry>
          <key>...</key>
          <value>...</value>
      <entry>
      <entry>
          <key>...</key>
          <value>...</value>
      <entry>
      ...
  ]]></source>
  The key and the value content are standard betwixt mappings of the objects.
          </p>
      <p>
  Reading map properties is an extension of the ways that Betwixt handles collections. Rather
than 
  searching for an <code>add*</code> method that takes a single parameter, now
Betwixt looks 
  (in a similar fashion) for such a method that takes two parameters.
          </p> 
  </subsection>
  
  </section>
  
  <section name="Customized Mapping (Advanced)">
  
  <subsection name="Caching and the XMLRegistry">
      
      <p>
      Introspection is slow and so caching the results improves preformance. Though the writers

      and readers can - by nature - only be used safely in a single thread, a single 
      <code>XMLIntrospector</code> instance can be safely shared amongst multiple
threads. Sharing a
      single instance will improve performance by sharing it's <code>XMLBeanInfo</code>
cache.
      </p>
      
      <p>
      The <code>XMLBeanInfoRegistry</code> interface allows finely grained, pluggable
control over 
      the caching strategy used by a <code>XMLIntrospector</code>. The implementation
used can be set
      by passing an instance to <code>XMLIntrospector.setRegistry</code>.
      </p>
      
      <p>
      Before using the standard introspection techniques to create a new <code>XMLBeanInfo</code>
instance
      for a bean, the current <code>XMLBeanInfoRegistry</code> is first checked.
Only if the registry 
      does not return an <code>XMLBeanInfo</code> will a new one be created. Once
a new instance has been
      created by introspection, the <code>XMLBeanInfoRegistry</code> implementation
will be called so that
      the <code>XMLBeanInfo</code> can (if required) be cached.
      </p>
      
      <p>
      The default strategy caches everything and supports flushes. Betwixt contains an alternative

      implementation that does not cache anything. Users that require more sophisticated caching

      strategies should create custom implementations.
      </p>
      
      <p>
      The <code>XMLBeanInfoRegistry</code> can also be used to override the standard
introspection mechanism
      on a per class basis. The safest way to do this is to create a custom <code>XMLBeanInfoRegistry</code>

      implementation that pre-loads <code>XMLBeanInfo</code>'s for the required
classes. If flush is called, 
      the cache should be reset that it contains only those that it contained at the start.

      </p>
  
  </subsection>
  
  <subsection name="Other XMLIntrospector Settings">
      
      <p>
      Here are discussed the important settings that haven't been covered already. 
      </p>
      
      <p>
      The <strong><code>AttributesForPrimitives</code></strong> property
determines whether a primitive
      type (including strings) should be - by default - mapped to elements or attributes.
For example, a
      property called <code>Age</code> of a bean called <code>PersonBean</code>
would be mapped to something
      like:
      
  <source><![CDATA[
          <PersonBean>
              <age>21</age>
              ...
  ]]></source>
      
      when <code>isAttributesForPrimitives</code> is false but to 
      
  <source><![CDATA[
          <PersonBean age='21'>
              ...
  ]]></source>
      
      when it is true.
      </p>
      
      <p>
      The <strong><code>WrapCollectionsInElement</code></strong> property
determines whether the elements 
      for a composite property (ie one that returns a collection or iterator) should be wrapped
in a parent
      element. For example, if <code>isWrapCollectionsInElement</code> is true
then a property with signature 
      <code>List getChildren()</code> would wrap a <code>&lt;children&gt;</code>
element around the elements
      representing the contents of the list.
      </p>
  </subsection>
  
  <subsection name="Using .betwixt files To Read And Write Mixed Content">
      <p>
      An element with mixed content contains child elements and text. 
      For example, element <code>foo</code> has mixed content in the following:
  <source>
  <![CDATA[<foo>
          Some text
          <bar/>
      </foo>]]>
  </source>
      Betwixt supports writing mixed content through <code>text</code> elements
in the 
      .betwixt file. 
      </p>
      
      <p>
      A <code>text</code> element can be mapped to a property in which case it
must have
      a <code>property</code> attribute and may (optionally) have a <code>type</code>
attribute.
      Otherwise, the <code>text</code> element is mapped to a static value, in
which case it
      must have a <code>value</code> attribute. If a <code>text</code>
element has both 
      <code>value</code> and <code>property</code> attributes then
an exception will be thrown.
      </p>
      
      <p>
      For example, a simple bean with the .betwixt file 
  <source><![CDATA[<?xml version="1.0" encoding="UTF-8" ?>
  <info primitiveTypes="attribute">
      <element name='foo'>
          <attribute name='version' value='1.0'/>
          <element name='bar'>
              <attribute name='version' property='alpha'/>
              <text value='static text'/>
              <element name='baa' property='beta'/>
              <text property='gamma'/>
          </element>
      </element>
  </info>]]>
  </source>
      and with property values alpha='One', beta='Two' and gamma='Three' will write an output
like:
  <source>
  <![CDATA[<foo version="1.0">
      <bar version="One">static text<baa>Two</baa>Three</bar>
  </foo>
  ]]></source>
      </p>
          <p>
  Betwixt supports reading back mixed content in one special situation which happily is also
a common 
  use case. Betwixt will call a single property with all the mixed content text. So, only
one mixed content
  property is specified then the bean can be written and then read back.
      </p>
  </subsection>
  
  <subsection name='Using ConvertUtils To Customize Conversion Of Primitives'>
          <p>
  <code>ConvertUtils</code> is part of <a href='http://jakarta.apache.org/commons/beanutils.html'>commons-beanutils</a>
  and it can be used to flexibly convert strings to objects and back again. Betwixt uses ConvertUtils
to 
  perform these conversions and so standard <code>ConvertUtils</code> methods
can be called to customize these 
  conversions.
      </p>
  </subsection>
  
  </section>
  
  </body>
  </document>
  
  
  

Mime
View raw message