You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2002/06/11 18:05:21 UTC

cvs commit: jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/strategy DefaultPluralStemmer.java

jstrachan    2002/06/11 09:05:21

  Modified:    betwixt/src/java/org/apache/commons/betwixt/digester
                        XMLIntrospectorHelper.java
               betwixt/src/test/org/apache/commons/betwixt
                        TestMavenProject.java
               betwixt/src/test/org/apache/commons/betwixt/scarab
                        TestScarabSettings.java
               betwixt/src/java/org/apache/commons/betwixt
                        ElementDescriptor.java XMLIntrospector.java
               betwixt  build.xml
               betwixt/src/java/org/apache/commons/betwixt/io
                        BeanWriter.java BeanCreateRule.java
               betwixt/src/test/org/apache/commons/betwixt/strategy
                        TestHyphenatedNameMapper.java
               betwixt/src/java/org/apache/commons/betwixt/strategy
                        DefaultPluralStemmer.java
  Added:       betwixt  commons-betwixt-1.0-dev-site.tar.gz
               betwixt/src/test/org/apache/commons/betwixt/schema
                        DbDataType.java TestSchema.java Dbms.java Dbid.java
                        PhysicalSchema.java schema.xml
               betwixt/src/test/org/apache/commons/betwixt/strategy
                        TestDefaultPluralStemmer.java
                        TestDefaultNameMapper.java
                        TestDecapitalizeNameMapper.java
  Log:
  Applied Martin's patches, which are quite numerous...
  
  - Indention
  The indention didn't work the way it supposed to. If you set the
  indention level to eg 2 spaces, it would add 4 spaces.
  The default is now 2 spaces (which was what it was meant to be).
  
  - wrapCollectionsInElement
  This wasn't implemented at all. The default behaviour was to wrap them
  in collections and I kept it that way (even though the default was not
  to). It now correctly parses xml files in the format (when setting this
  option to false):
  <element>
    <subelement/>
    <subelement/>
  </element>
  The default behaviour of this will be :
  <element>
    <subelements>
      <subelement/>
      <subelement/>
    </subelements>
  <element>
  I needed to add an extra getter/setter to the ElementDescriptor to get
  this done correctly and without changing to much code.
  
  - setNameMapper
  Deprecated this in favour if setElementNameMapper and
  setAttributeNameMapper. If you just set setElementNameMapper, the
  setAttributeNameMapper will use the same NameMapper that is used in
  setElemementNameMapper. This is the way it worked, and we need to keep
  backward compatible. The original nameMapper works as the
  ElementNameMapper.
  
  - DefaultPluralStemmer
  Was a bit freely implemented when multiple matches were found.
  Say the property to get was "y" and the valaues in the map are "y",
  "yes", "yesno", it could return eg yesno, when you actually want y.
  I added a "best match" policy, which will always return the equals, when
  it is found or the closest match. (the match with the minimum length).
  Don't know if in real life this can actually happen, but in the testcase
  it can ;). It does a log.warn to actually say that we are using a
  certain match.
  
  Tests :
  
  - The tests currently in cvs are all passing, without change.
  - Tested maven from cvs with the new jar and it works (I will also
  supply a patch for maven when this is committed).
  - Didn't test the current scarab (John, just your NameMapper call is
  giving a deprecated message on compile)
  - Adjusted the maven testcase in betwixt to use the ElementNameMapper.
  - Added testcases for the strategy package, so we can insure the current
  behaviour will stay the same and if not, we actually get a failing
  testcase.
  - Added testcase for my specific xml file, which started all this
  programming in the first place. I added a new test package called
  org.apache.commons.betwixt.schema. The testcase is pretty well
  documented and can be used nicely as example code.
  
  Revision  Changes    Path
  1.2       +2 -1      jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java
  
  Index: XMLIntrospectorHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLIntrospectorHelper.java	10 Jun 2002 17:53:34 -0000	1.1
  +++ XMLIntrospectorHelper.java	11 Jun 2002 16:05:20 -0000	1.2
  @@ -86,6 +86,7 @@
     * common code shared between the digestor and introspector.</p>
     *
     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Id$
     */
   public class XMLIntrospectorHelper {
  @@ -330,7 +331,7 @@
                                   ElementDescriptor child = children[0];
                                   String localName = child.getLocalName();
                                   if ( localName == null || localName.length() == 0 ) {
  -                                    child.setLocalName( introspector.getNameMapper().mapTypeToElementName( propertyName ) );
  +                                    child.setLocalName( introspector.getElementNameMapper().mapTypeToElementName( propertyName ) );
                                   }
                               }
                           }
  
  
  
  1.2       +1 -1      jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestMavenProject.java
  
  Index: TestMavenProject.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestMavenProject.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestMavenProject.java	10 Jun 2002 17:53:32 -0000	1.1
  +++ TestMavenProject.java	11 Jun 2002 16:05:20 -0000	1.2
  @@ -207,7 +207,7 @@
           //introspector.setWrapCollectionsInElement(true);
           
           // turn bean elements into lower case
  -        introspector.setNameMapper( new DecapitalizeNameMapper() );
  +        introspector.setElementNameMapper( new DecapitalizeNameMapper() );
           
           return introspector;
       }
  
  
  
  1.2       +1 -1      jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/scarab/TestScarabSettings.java
  
  Index: TestScarabSettings.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/scarab/TestScarabSettings.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestScarabSettings.java	10 Jun 2002 17:53:35 -0000	1.1
  +++ TestScarabSettings.java	11 Jun 2002 16:05:20 -0000	1.2
  @@ -175,7 +175,7 @@
           //introspector.setWrapCollectionsInElement(true);
   
           // turn bean elements into lower case
  -        introspector.setNameMapper(new HyphenatedNameMapper());
  +        introspector.setElementNameMapper(new HyphenatedNameMapper());
   
           return introspector;
       }
  
  
  
  1.2       +22 -0     jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java
  
  Index: ElementDescriptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ElementDescriptor.java	10 Jun 2002 17:53:34 -0000	1.1
  +++ ElementDescriptor.java	11 Jun 2002 16:05:20 -0000	1.2
  @@ -73,6 +73,7 @@
     * and <code>ElementDescriptor</code>'s for it's child elements.
     *
     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Revision$
     */
   public class ElementDescriptor extends NodeDescriptor {
  @@ -107,6 +108,12 @@
       /** Whether this element refers to a primitive type (or property of a parent object) */
       private boolean primitiveType;
       
  +    /** 
  +     * Whether this collection element can be used
  +     * as a collection element. Defaults to true
  +     */
  +    private boolean wrapCollectionsInElement = true;
  +    
       /** Base constructor */
       public ElementDescriptor() {
       }
  @@ -139,6 +146,21 @@
           return attributeDescriptors != null && attributeDescriptors.length > 0;
       }
       
  +    /** Specifies if this is a collection element
  +     * Normally only used with the WrapCollectionsInElement setting
  +     * @param isCollection
  +     */
  +    public void setWrapCollectionsInElement(boolean wrapCollectionsInElement) {
  +        this.wrapCollectionsInElement = wrapCollectionsInElement;
  +    }
  +
  +    /**
  +     * Returns if this element is a collection element
  +     */
  +    public boolean isWrapCollectionsInElement() {
  +        return this.wrapCollectionsInElement;
  +    }
  +
       public void addAttributeDescriptor(AttributeDescriptor descriptor) {
           if ( attributeList == null ) {
               attributeList = new ArrayList();
  
  
  
  1.2       +68 -8     jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java
  
  Index: XMLIntrospector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLIntrospector.java	10 Jun 2002 17:53:34 -0000	1.1
  +++ XMLIntrospector.java	11 Jun 2002 16:05:20 -0000	1.2
  @@ -93,6 +93,7 @@
     * Later requests for the same class will return the cached value.</p>
     *
     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Id$
     */
   public class XMLIntrospector {
  @@ -104,7 +105,7 @@
       private boolean attributesForPrimitives = false;
       
       /** should we wrap collections in an extra element? */
  -    private boolean wrapCollectionsInElement = false;
  +    private boolean wrapCollectionsInElement = true;
       
       /** Is <code>XMLBeanInfo</code> caching enabled? */
       boolean cachingEnabled = true;
  @@ -121,7 +122,13 @@
       private PluralStemmer pluralStemmer;
       
       /** The strategy used to convert bean type names into element names */
  -    private NameMapper nameMapper;
  +    private NameMapper elementNameMapper;
  +
  +    /**
  +     * The strategy used to convert bean type names into attribute names
  +     * It will default to the normal nameMapper.
  +     */
  +    private NameMapper attributeNameMapper;
       
       /** Base constructor */
       public XMLIntrospector() {
  @@ -214,7 +221,7 @@
           Class beanClass = beanDescriptor.getBeanClass();
           
           ElementDescriptor elementDescriptor = new ElementDescriptor();
  -        elementDescriptor.setLocalName( getNameMapper().mapTypeToElementName( beanDescriptor.getName() ) );
  +        elementDescriptor.setLocalName( getElementNameMapper().mapTypeToElementName( beanDescriptor.getName() ) );
           elementDescriptor.setPropertyType( beanInfo.getBeanDescriptor().getBeanClass() );
           
           if (log.isTraceEnabled()) {
  @@ -322,22 +329,66 @@
   
       /** 
        * @return the strategy used to convert bean type names into element names
  +     * @deprecated getNameMapper is split up in {@link #getElementNameMapper()} and {@link #getAttributeNameMapper()}
        */
       public NameMapper getNameMapper() {
  -        if ( nameMapper == null ) {
  -            nameMapper = createNameMapper();
  -        }
  -        return nameMapper;
  +        return getElementNameMapper();
       }
       
       /** 
        * Sets the strategy used to convert bean type names into element names
  +     * @param nameMapper
  +     * @deprecated setNameMapper is split up in {@link #setElementNameMapper(NameMapper)} and {@link #setAttributeNameMapper(NameMapper)}
        */
       public void setNameMapper(NameMapper nameMapper) {
  -        this.nameMapper = nameMapper;
  +        setElementNameMapper(nameMapper);
       }
   
   
  +    /**
  +     * @return the strategy used to convert bean type names into element 
  +     * names. If no element mapper is currently defined then a default one is created.
  +     */
  +    public NameMapper getElementNameMapper() {
  +        if ( elementNameMapper == null ) {
  +            elementNameMapper = createNameMapper();
  +         }
  +        return elementNameMapper;
  +    }
  +     
  +    /**
  +     *  Sets the strategy used to convert bean type names into element names
  +     * @param nameMapper
  +     */
  +    public void setElementNameMapper(NameMapper nameMapper) {
  +        this.elementNameMapper = nameMapper;
  +    }
  +    
  +
  +    /**
  +     * @return the strategy used to convert bean type names into attribute
  +     * names. If no attributeNamemapper is known, it will default to the ElementNameMapper
  +     */
  +    public NameMapper getAttributeNameMapper() {
  +        if (attributeNameMapper == null) {
  +            attributeNameMapper = getElementNameMapper();
  +        }
  +        return attributeNameMapper;
  +     }
  +
  +
  +    /**
  +     * Sets the strategy used to convert bean type names into attribute names
  +     * @param nameMapper
  +     */
  +    public void setAttributeNameMapper(NameMapper nameMapper) {
  +        this.attributeNameMapper = nameMapper;
  +    }
  +
  + 
  +
  +
  +
       
       // Implementation methods
       //-------------------------------------------------------------------------        
  @@ -489,6 +540,7 @@
               
               ElementDescriptor elementDescriptor = new ElementDescriptor();
               elementDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } );
  +            elementDescriptor.setWrapCollectionsInElement(isWrapCollectionsInElement());
               
               nodeDescriptor = elementDescriptor;            
               elements.add( nodeDescriptor );
  @@ -509,6 +561,14 @@
           }
   
           nodeDescriptor.setLocalName( getNameMapper().mapTypeToElementName( propertyDescriptor.getName() ) );
  +        if (nodeDescriptor instanceof AttributeDescriptor) {
  +            // we want to use the attributemapper only when it is an attribute.. 
  +            nodeDescriptor.setLocalName( getAttributeNameMapper().mapTypeToElementName( propertyDescriptor.getName() ) );
  +        }
  +        else{
  +            nodeDescriptor.setLocalName( getElementNameMapper().mapTypeToElementName( propertyDescriptor.getName() ) );
  +        }        
  +        
           nodeDescriptor.setPropertyName( propertyDescriptor.getName() );
           nodeDescriptor.setPropertyType( type );        
           
  
  
  
  1.2       +0 -3      jakarta-commons/betwixt/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/build.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- build.xml	10 Jun 2002 17:53:32 -0000	1.1
  +++ build.xml	11 Jun 2002 16:05:20 -0000	1.2
  @@ -200,9 +200,6 @@
           <path path="${classpath}"/>
           <path path="${java.classpath}"/>
         </path>
  -      
  -      <echo message="test callback file: ${maven.test.callback.pre-test.buildFile} and target: ${maven.test.callback.pre-test.buildTarget}"/>
  -
       </target>   
   
       <target name="compile.tests" depends="compile, maven:compile-test"/>
  
  
  
  1.1                  jakarta-commons/betwixt/commons-betwixt-1.0-dev-site.tar.gz
  
  	<<Binary file>>
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/DbDataType.java
  
  Index: DbDataType.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  
  package org.apache.commons.betwixt.schema;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class DbDataType
  {
      private String name;
  
      public DbDataType()
      {
      }
      
      public void setName(String name) {
          this.name = name;
      }
      
      public String getName() {
          return this.name;
      }
      
      public String toString() {
          return getName();
      }
      
      public boolean equals(Object object) {
          if (object == null) {
              return false;
          }
          
          if (object instanceof DbDataType) {
              if (object.toString().equals(this.toString())) {
                  return true;
              }
          }
          return false;
      }
          
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/TestSchema.java
  
  Index: TestSchema.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  package org.apache.commons.betwixt.schema;
  
  import java.io.StringReader;
  import java.io.StringWriter;
  import java.io.Writer;
  
  import junit.framework.TestCase;
  import junit.framework.Test;
  import junit.framework.TestSuite;
  import org.apache.commons.betwixt.*;
  import org.apache.commons.betwixt.io.BeanReader;
  import org.apache.commons.betwixt.io.BeanWriter;
  import org.apache.commons.betwixt.strategy.DecapitalizeNameMapper;
  import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
  
  
  /**
   * This will test betwixt on handling a different kind of xml file, without
   * a "collection" tag.
   * 
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class TestSchema extends TestCase
  {
      
      public static Test suite()
      {
          return new TestSuite(TestSchema.class);
      }
  
      
      public TestSchema(String testName)
      {
          super(testName);
      }
      
      /**
       * Test the roundtrip with an xml file that doesn't have
       * collection elements, writes it with collection elements
       * and then compares the 2 object, which should end up
       * equal..
       */
      public void testCombinedRoundTrip()
      throws Exception
      {
          BeanReader reader = createBeanReader();
          PhysicalSchema schema = (PhysicalSchema) reader.parse("src/test/org/apache/commons/betwixt/schema/schema.xml");
          StringWriter buffer = new StringWriter();
          write(schema, buffer, true);
          StringReader in = new StringReader(buffer.getBuffer().toString());
          reader = createBeanReader();
          XMLIntrospector intro = createXMLIntrospector();
          // we have written the xml file back with element collections,
          // so we have to say to the reader we want to use that now
          // (the default when creating in this test is not to use them)
          intro.setWrapCollectionsInElement(true);
          // first flush the cash, else setting other options, doesn't
          // end up in rereading / mapping the object model.
          intro.flushCache();
          // set the xmlIntrospector back to the reader
          reader.setXMLIntrospector(intro);
          PhysicalSchema schemaSecond = (PhysicalSchema) reader.parse(in);
          buffer.close();
          write(schema,buffer, true);
          assertEquals(schemaSecond, schema);
      }
      /**
       * Tests we can round trip from the XML -> bean -> XML -> bean.
       * It will test if both object are identical.
       * For this to actually work I implemented a details equals in my
       * Beans..
       */
      public void testRoundTripWithoutCollectionElement()
      throws Exception
      {
          BeanReader reader = createBeanReader();
          PhysicalSchema schema = (PhysicalSchema) reader.parse("src/test/org/apache/commons/betwixt/schema/schema.xml");
          StringWriter buffer = new StringWriter();
          write(schema, buffer, false);
          StringReader in = new StringReader(buffer.getBuffer().toString());
          PhysicalSchema schemaSecond = (PhysicalSchema) reader.parse(in);
          assertEquals(schemaSecond, schema);
      }
      
      /**
       * Creates a beanReader
       */
      protected BeanReader createBeanReader()
      throws Exception
       {
          BeanReader reader = new BeanReader();
          reader.setXMLIntrospector(createXMLIntrospector());
          // register the class which maps to the root element
          // of the xml file (this depends on the NameMapper used.
          reader.registerBeanClass(PhysicalSchema.class);
          return reader;
      } 
      
      /**
       * Set up the XMLIntroSpector
       */
      protected XMLIntrospector createXMLIntrospector() {
          XMLIntrospector introspector = new XMLIntrospector();
  
          // set elements for attributes to true
          introspector.setAttributesForPrimitives(true);
  
          // Since we don't want to have collectionelements 
          // line <DBMSS>, we have to set this to false,
          // since the default is true.
          introspector.setWrapCollectionsInElement(false);
  
          // We have to use the HyphenatedNameMapper
          // Since we want the names to resolve from eg PhysicalSchema
          // to PHYSICAL_SCHEMA.
          // we pass to the mapper we want uppercase and use _ for name
          // seperation.
          // This will set our ElementMapper.
          introspector.setElementNameMapper(new HyphenatedNameMapper(true, "_"));
          // since our attribute names will use a different 
          // naming convention in our xml file (just all lowercase)
          // we set another mapper for the attributes
          introspector.setAttributeNameMapper(new DecapitalizeNameMapper());
  
          return introspector;
      }
      
      /**
       * Opens a writer and writes an object model according to the
       * retrieved bean
       */
      private void write(Object bean, Writer out, boolean wrapCollectionsInElement)
      throws Exception
      {
          BeanWriter writer = new BeanWriter(out);
          writer.setXMLIntrospector(createXMLIntrospector());
          // specifies weather to use collection elements or not.
          writer.getXMLIntrospector().setWrapCollectionsInElement(wrapCollectionsInElement);
          // we don't want to write Id attributes to every element
          // we just want our opbject model written nothing more..
          writer.setWriteIDs(false);
          // the source has 2 spaces indention and \n as line seperator.
          writer.setIndent("  ");
          writer.setEndOfLine("\n");
          writer.write(bean);
      }
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/Dbms.java
  
  Index: Dbms.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  
  package org.apache.commons.betwixt.schema;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class Dbms
  {
      private String kind;
      private ArrayList dbidCollection;
      
      public Dbms()
      {
          dbidCollection = new ArrayList();
      }
      
      public Dbms(String kind) 
      {
          System.out.println("kind constructor called");
          setKind(kind);
      }
      
      public void addDbid(Dbid dbid)
      {
          dbidCollection.add(dbid);
      }
      
      public List getDbids() {
          return this.dbidCollection;
      }
  
      public void setKind(String kind) 
      {
          this.kind = kind;
      }
      
      public String getKind()
      {
          return this.kind;
      }
      
      public boolean equals(Object object) 
      {
          if (object == null) {
              return false;
          }
          
          if (object instanceof Dbms) {
              Dbms dbms = (Dbms) object;
              if (dbms.getKind().equals(this.getKind())) {
                  if (dbms.getDbids().equals(this.getDbids())) {
                      return true;
                  }
              }
          }
          return false;
      }
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/Dbid.java
  
  Index: Dbid.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  
  package org.apache.commons.betwixt.schema;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class Dbid
  {
      private ArrayList dbDataTypeCollection;
      
      public Dbid()
      {
          dbDataTypeCollection = new ArrayList();
      }
      
      public void addDbDataType(DbDataType dbDataType) {
          dbDataTypeCollection.add(dbDataType);
      }
      
      public List getDbDataTypes() {
          return dbDataTypeCollection;
      }
      
      public boolean equals(Object object) {
          if (object == null) {
              return false;
          }
          
          if (object instanceof Dbid) {
              Dbid dbid = (Dbid) object;
              if (dbid.getDbDataTypes().equals(this.getDbDataTypes())) {
                  return true;
              }
          }
          return false;
      }
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/PhysicalSchema.java
  
  Index: PhysicalSchema.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  
  package org.apache.commons.betwixt.schema;
  
  import java.util.Vector;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class PhysicalSchema
  {
      
      private ArrayList dbmsCollection;
      
      
      private boolean autoCreate = false;
      
      public PhysicalSchema()
      {
          dbmsCollection = new ArrayList();
      }
      public PhysicalSchema(String autoCreate)
      {
          this.autoCreate = autoCreate.equalsIgnoreCase("yes");
      }
      public void setAutocreate(String autoCreate)
      {
          this.autoCreate = (autoCreate.equalsIgnoreCase("yes"));
      }
      
      public String getAutocreate() 
      {
          return this.autoCreate?"yes":"no";
      }
      
      public void addDbms(Dbms dbms)
      {
          dbmsCollection.add(dbms);
      }
      
      public List getDbmss()
      {
          return dbmsCollection;
      }
      
      public boolean equals(Object object) 
      {
          if (object == null) { 
              return false;
          }
          if (object instanceof PhysicalSchema) {
              PhysicalSchema schema = (PhysicalSchema) object;
              if (schema.getAutocreate().equals(this.getAutocreate())) {
                  if (schema.getDbmss().equals(this.getDbmss())) {
                      return true;
                  }
              }
          }
          return false;
      }
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/schema.xml
  
  Index: schema.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8" ?>
  <PHYSICAL_SCHEMA autocreate="yes">
    <DBMS kind="ODBC">
      <DBID>
        <DB_DATA_TYPE name="VARCHAR"/>
        <DB_DATA_TYPE name="INTEGER"/>
        <DB_DATA_TYPE name="CHAR"/>
        <DB_DATA_TYPE name="TEXT"/>
        <DB_DATA_TYPE name="DATETIME"/>
        <DB_DATA_TYPE name="LONG RAW"/> 
        <DB_DATA_TYPE name="CLOB"/>
        <DB_DATA_TYPE name="FLOAT"/>
      </DBID>
    </DBMS>
    <DBMS kind="TEST"/>
  </PHYSICAL_SCHEMA>
  
  
  
  1.2       +37 -10    jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java
  
  Index: BeanWriter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BeanWriter.java	10 Jun 2002 17:53:32 -0000	1.1
  +++ BeanWriter.java	11 Jun 2002 16:05:21 -0000	1.2
  @@ -125,6 +125,7 @@
     * 
     * 
     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Revision$
     */
   public class BeanWriter {
  @@ -320,6 +321,7 @@
       /**
        * <p> Switch on formatted output.
        * This sets the end of line and the indent.
  +     * The default is adding 2 spaces and a newline
        */
       public void enablePrettyPrint() {
           endOfLine = "\n";
  @@ -496,7 +498,10 @@
                                   throws 
                                       IOException, 
                                       IntrospectionException {
  -        expressElementStart( qualifiedName );
  +                                        
  +        if (elementDescriptor.isWrapCollectionsInElement()) {
  +            expressElementStart( qualifiedName );
  +        }
           
           writeRestOfElement( qualifiedName, elementDescriptor, context);
       }
  @@ -530,16 +535,25 @@
                                       IOException, 
                                       IntrospectionException {
   
  -        writeAttributes( elementDescriptor, context );
  -        
  +        if (elementDescriptor.isWrapCollectionsInElement()) {
  +            writeAttributes( elementDescriptor, context );
  +        }
  +
           if ( writeContent( elementDescriptor, context ) ) {
  -            expressElementEnd( qualifiedName );
  +            if (elementDescriptor.isWrapCollectionsInElement()) {
  +                expressElementEnd( qualifiedName );
  +            }
           }  
  -        else {            
  -            expressElementEnd();
  +        else {
  +            if (elementDescriptor.isWrapCollectionsInElement()) {
  +                expressElementEnd();
  +            }
           }
       }
       
  +
  +    
  +    
       protected void writeIDREFElement( 
                                       String qualifiedName, 
                                       String idrefAttributeName,
  @@ -570,7 +584,6 @@
           boolean writtenContent = false;
           if ( childDescriptors != null && childDescriptors.length > 0 ) {
               // process child elements
  -            ++indentLevel;
               for ( int i = 0, size = childDescriptors.length; i < size; i++ ) {
                   ElementDescriptor childDescriptor = childDescriptors[i];
                   Context childContext = context;
  @@ -586,7 +599,9 @@
                                       writtenContent = true;
                                       writer.write( ">" );
                                   }
  +                                ++indentLevel;
                                   write( qualifiedName, iter.next() );
  +                                --indentLevel;
                               }
                           }
                           else {
  @@ -594,7 +609,9 @@
                                   writtenContent = true;
                                   writer.write( ">" );
                               }
  +                            ++indentLevel;
                               write( qualifiedName, childBean );
  +                            --indentLevel;
                           }
                       }                    
                   }
  @@ -603,10 +620,17 @@
                           writtenContent = true;
                           writer.write( ">" );
                       }
  -                    write( childDescriptor.getQualifiedName(), childDescriptor, childContext );
  +                    if (childDescriptor.isWrapCollectionsInElement()) {
  +                        ++indentLevel;
  +                    }
  +
  +                     write( childDescriptor.getQualifiedName(), childDescriptor, childContext );
  +
  +                    if (childDescriptor.isWrapCollectionsInElement()) {
  +                        --indentLevel;
  +                    }
                   }
               }
  -            --indentLevel;
               if ( writtenContent ) {
                   writePrintln();
                   writeIndent();
  @@ -638,6 +662,9 @@
                       Context context ) 
                           throws 
                               IOException {
  +        if (!elementDescriptor.isWrapCollectionsInElement()) 
  +            return;
  +            
           AttributeDescriptor[] attributeDescriptors = elementDescriptor.getAttributeDescriptors();
           if ( attributeDescriptors != null ) {
               for ( int i = 0, size = attributeDescriptors.length; i < size; i++ ) {
  @@ -680,7 +707,7 @@
       protected void writeIndent() throws IOException {
           if ( indent != null ) {
               for ( int i = 0; i < indentLevel; i++ ) {
  -                writer.write( indent );
  +                writer.write( getIndent() );
               }
           }
       }
  
  
  
  1.2       +7 -1      jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanCreateRule.java
  
  Index: BeanCreateRule.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanCreateRule.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BeanCreateRule.java	10 Jun 2002 17:53:32 -0000	1.1
  +++ BeanCreateRule.java	11 Jun 2002 16:05:21 -0000	1.2
  @@ -35,6 +35,7 @@
     * from the betwixt XML metadata.</p>
     *
     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Revision$
     */
   public class BeanCreateRule extends Rule {
  @@ -236,7 +237,12 @@
                               ElementDescriptor grandChild = grandChildren[0];
                               String grandChildQName = grandChild.getQualifiedName();
                               if ( grandChildQName != null && grandChildQName.length() > 0 ) {
  -                                path += '/' + grandChildQName;
  +                                if (childDescriptor.isWrapCollectionsInElement()) {
  +                                    path += '/' + grandChildQName;
  +                                }
  +                                else{
  +                                    path = prefix + grandChildQName;
  +                                }
                               }
                           }
                           
  
  
  
  1.2       +12 -0     jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestHyphenatedNameMapper.java
  
  Index: TestHyphenatedNameMapper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestHyphenatedNameMapper.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestHyphenatedNameMapper.java	10 Jun 2002 17:53:34 -0000	1.1
  +++ TestHyphenatedNameMapper.java	11 Jun 2002 16:05:21 -0000	1.2
  @@ -16,6 +16,8 @@
   /** Test harness for the HyphenatedNameMapper
     *
     * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
  +  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  +  * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Revision$
     */
   public class TestHyphenatedNameMapper extends TestCase {
  @@ -47,5 +49,15 @@
           String result = mapper.mapTypeToElementName("FooBar");
           assertEquals("FOO_BAR", result);
       }
  +    
  +    /**
  +     * A more "complicated" exmple
  +     */
  +    public void testUpperCaseLongViaProperties() {
  +        HyphenatedNameMapper mapper = new HyphenatedNameMapper(true, "__");
  +        String result = mapper.mapTypeToElementName("FooBarFooBar");
  +        assertEquals("FOO__BAR__FOO__BAR", result);
  +
  +     }
   }
   
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestDefaultPluralStemmer.java
  
  Index: TestDefaultPluralStemmer.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  package org.apache.commons.betwixt.strategy;
  
  import junit.framework.TestCase;
  import junit.framework.Test;
  import junit.framework.TestSuite;
  import org.apache.commons.betwixt.ElementDescriptor;
  import java.util.HashMap;
  
  /**
   * Tests the defaultPluralStemmer
   * 
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class TestDefaultPluralStemmer extends TestCase
  {
  
      public static Test suite() {
          return new TestSuite(TestDefaultPluralStemmer.class);
      }
  
      public TestDefaultPluralStemmer(String testName)  {
          super(testName);
      }
      
      public void testNullMap() {
          DefaultPluralStemmer stemmer = new DefaultPluralStemmer();
          try {
              stemmer.findPluralDescriptor("test", null);
              fail("Should throw a nullpointer exception, since the map in the stemmer cannot be null");
          }catch(NullPointerException npe) {
          }
      }
      
      /**
       * This is the first match when calling the defaultStemmer.
       * It just adds an s to the the property and it should find it..
       */
      public void testFirstMatch() {
          
          ElementDescriptor des = new ElementDescriptor();
          des.setQualifiedName("FooBars");
          des.setPropertyType(java.util.List.class);
          HashMap map = new HashMap();
          map.put("FooBars", des);
          DefaultPluralStemmer dps = new DefaultPluralStemmer();
          ElementDescriptor result = dps.findPluralDescriptor("FooBar", map);
          assertEquals(des, result);
      }
      /**
       * Tests if the y is nicely replaces with ies and the correct
       * ElementDescriptor is returned
       */
      public void testSecondMatch() {
          ElementDescriptor des = new ElementDescriptor();
          des.setQualifiedName("FooBary");
          des.setPropertyType(java.util.List.class);
          HashMap map = new HashMap();
          map.put("FooBaries", des);
          DefaultPluralStemmer dps = new DefaultPluralStemmer();
          ElementDescriptor result = dps.findPluralDescriptor("FooBary", map);
          assertEquals(des, result);
      }
      
      /**
       * Tests if it actually skips the y if the length not greater than 1.
       */
      public void testSecondNonMatch() {
          ElementDescriptor des = new ElementDescriptor();
          des.setQualifiedName("y");
          des.setPropertyType(java.util.List.class);
          HashMap map = new HashMap();
          map.put("yies", des);
          DefaultPluralStemmer dps = new DefaultPluralStemmer();
          ElementDescriptor result = dps.findPluralDescriptor("y", map);
          assertNotNull(result);
      }
      
      /**
       * Uses the third if in pluralstemmer.
       * It should return the specified y, without any changing.
       */
      public void testThirdMatch() {
          ElementDescriptor des = new ElementDescriptor();
          des.setQualifiedName("y");
          des.setPropertyType(java.util.List.class);
          HashMap map = new HashMap();
          map.put("y", des);
          DefaultPluralStemmer dps = new DefaultPluralStemmer();
          ElementDescriptor result = dps.findPluralDescriptor("y", map);
          assertEquals(des, result);
      }
      
      /**
       * Tests to see if you get warned when there are multiple matches
       * found
       */
      public void testMultipleMatches() {
          ElementDescriptor des = new ElementDescriptor();
          des.setQualifiedName("y");
          des.setPropertyType(java.util.List.class);
          ElementDescriptor desyes = new ElementDescriptor();
          desyes.setQualifiedName("yes");
          desyes.setPropertyType(java.util.List.class);
          ElementDescriptor desyesno = new ElementDescriptor();
          desyesno.setQualifiedName("yesno");
          desyesno.setPropertyType(java.util.List.class);
          HashMap map = new HashMap();
          map.put("y", des);
          map.put("yes", desyes);
          map.put("yesno", desyesno);
          DefaultPluralStemmer dps = new DefaultPluralStemmer();
          ElementDescriptor result = dps.findPluralDescriptor("y", map);
          assertEquals(des, result);
          result = dps.findPluralDescriptor("yes", map);
          assertEquals(desyes, result);
          result = dps.findPluralDescriptor("yesno", map);
          assertEquals(desyesno, result);
      }
      
      /**
       *  Test if the closest match mechanisme is working
       */
      public void testClosestMatch() {
          HashMap map = new HashMap();
          ElementDescriptor yes1 = new ElementDescriptor("yes1", "yes1","");
          map.put("yes1", yes1);
          ElementDescriptor yes12 = new ElementDescriptor("yes12", "yes12","");
          map.put("yes12", yes12);
          ElementDescriptor yes123 = new ElementDescriptor("yes123", "yes123","");
          map.put("yes123", yes123);
          DefaultPluralStemmer stemmer = new DefaultPluralStemmer();
          ElementDescriptor result = stemmer.findPluralDescriptor("yes", map);
          assertEquals(yes1, result);
      }    
      
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestDefaultNameMapper.java
  
  Index: TestDefaultNameMapper.java
  ===================================================================
  /*
   * $Header$
   * $Revision$
   * $Date$
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  package org.apache.commons.betwixt.strategy;
  
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  import junit.framework.Test;
  
  /**
   * Testcase that covers the DefaultNameMapper.
   * 
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class TestDefaultNameMapper extends TestCase
  {
      
      public static Test suite() {
          return new TestSuite(TestDefaultNameMapper.class);
      }
  
      public TestDefaultNameMapper(String testName)
      {
          super(testName);
      }
      /**
       * Just put in some strings and expect them back unchanged.
       * This looks stupid, but enables us to check for unexpected
       * changes, which breaks the orignal behaviour.
       */
      public void testDefault() {
          String[] values = { "foo", "Foo", "FooBar", "fooBar", 
                              "FOOBAR", "FOOBar", "FoOBaR"};
          DefaultNameMapper mapper = new DefaultNameMapper();
          for (int i=0; i < values.length; i++) {
              String result = mapper.mapTypeToElementName(values[i]);
              assertEquals(values[i], result);
          }
      }
  
  }
  
  
  
  
  1.1                  jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestDecapitalizeNameMapper.java
  
  Index: TestDecapitalizeNameMapper.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/NodeDescriptor.java,v 1.8 2002/05/17 15:24:09 jstrachan Exp $
   * $Revision: 1.8 $
   * $Date: 2002/05/17 15:24:09 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id$
   */
  package org.apache.commons.betwixt.strategy;
  
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  import junit.framework.Test;
  
  /**
   * Test that harnasses the DecapitlizeNameMapper
   * 
   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
   * @version $Id$
   */
  public class TestDecapitalizeNameMapper extends TestCase
  {
  
      public static Test suite() {
          return new TestSuite(TestDecapitalizeNameMapper.class);
      }
      
      public TestDecapitalizeNameMapper(String testName) {
          super(testName);
      }
      
      public void testDecapitalize() {
          DecapitalizeNameMapper mapper = new DecapitalizeNameMapper();
          String result = mapper.mapTypeToElementName("FOOBAR");
          assertEquals("FOOBAR", result);
          result = mapper.mapTypeToElementName("FooBar");
          assertEquals("fooBar", result);
          result = mapper.mapTypeToElementName("FOOBar");
          assertEquals("FOOBar", result);
      }
  }
  
  
  
  
  1.2       +31 -3     jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/strategy/DefaultPluralStemmer.java
  
  Index: DefaultPluralStemmer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/strategy/DefaultPluralStemmer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultPluralStemmer.java	10 Jun 2002 17:53:34 -0000	1.1
  +++ DefaultPluralStemmer.java	11 Jun 2002 16:05:21 -0000	1.2
  @@ -66,20 +66,29 @@
   import java.util.Iterator;
   import java.util.Map;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +
   /** 
    * A default implementation of the plural name stemmer which
    * tests for some common english plural/singular patterns and
    * then uses a simple starts-with algorithm 
    * 
    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  + * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
    * @version $Revision$
    */
   public class DefaultPluralStemmer implements PluralStemmer {
   
  +    /** Log used for logging (Doh!) */
  +    protected static Log log = LogFactory.getLog( DefaultPluralStemmer.class );
  +
       /**
        * @return the plural descriptor for the given singular property name
        */
       public ElementDescriptor findPluralDescriptor( String propertyName, Map map) {
  +        int foundKeyCount = 0;
  +        String keyFound = null;
           ElementDescriptor answer = (ElementDescriptor) map.get( propertyName + "s" );
           if ( answer == null ) {
               int length = propertyName.length();
  @@ -93,12 +102,31 @@
                   for ( Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
                       String key = (String) iter.next();
                       if ( key.startsWith( propertyName ) ) {
  -                        answer = (ElementDescriptor) map.get(key);
  -                        break;
  +                        if (answer == null) {
  +                            answer = (ElementDescriptor) map.get(key);
  +                            if (key.equals(propertyName)) {
  +                                // we found the best match..
  +                                break;
  +                            }
  +                            foundKeyCount++;
  +                            keyFound = key;
  +                        }
  +                        else
  +                        {
  +                            // check if we have a better match,,
  +                            if (keyFound.length() > key.length()) {
  +                                answer = (ElementDescriptor) map.get(key);
  +                                keyFound = key;
  +                            }
  +                            foundKeyCount++;
  +
  +                        }
                       }
  -                    // ### could maybe warn if duplicate properties match
                   }
               }
  +        }
  +        if (foundKeyCount > 1) {
  +            log.warn("More then one type matches, using closest match "+keyFound);
           }
           return answer;
           
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>