commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dmi...@apache.org
Subject cvs commit: jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect ReflectableInstance.java ReflectedClazzTest.java ReflectedClazzTestSupport.java ReflectedListPropertyTest.java ReflectedMappedPropertyTest.java ReflectedSuperclazzInstance.java
Date Fri, 08 Nov 2002 14:29:37 GMT
dmitri      2002/11/08 06:29:37

  Modified:    clazz/src/java/org/apache/commons/clazz Bean.java Clazz.java
                        ClazzModifiers.java ClazzOperation.java
                        ClazzProperty.java
  Added:       clazz/src/java/org/apache/commons/clazz
                        CachingClazzLibrary.java ClazzException.java
                        ClazzFeature.java ClazzLibrary.java
                        ClazzLoader.java ClazzNotFoundException.java
               clazz/src/java/org/apache/commons/clazz/reflect
                        AccessorMethodParseResults.java
                        AccessorMethodParser.java ReflectedClazz.java
                        ReflectedClazzLibrary.java
                        ReflectedClazzLoader.java ReflectedFeature.java
                        ReflectedList.java ReflectedListProperty.java
                        ReflectedListPropertyIntrospector.java
                        ReflectedListPropertyParseResults.java
                        ReflectedMap.java ReflectedMappedProperty.java
                        ReflectedMappedPropertyIntrospector.java
                        ReflectedMappedPropertyParseResults.java
                        ReflectedProperty.java
                        ReflectedPropertyIntrospector.java
                        ReflectedPropertyIntrospectorSupport.java
                        ReflectedPropertyParseResults.java
                        ReflectedScalarProperty.java
                        ReflectedScalarPropertyIntrospector.java
                        ReflectedScalarPropertyParseResults.java
               clazz/src/test/org/apache/commons/clazz/reflect
                        ReflectableInstance.java ReflectedClazzTest.java
                        ReflectedClazzTestSupport.java
                        ReflectedListPropertyTest.java
                        ReflectedMappedPropertyTest.java
                        ReflectedSuperclazzInstance.java
  Log:
  Prototype
  
  Revision  Changes    Path
  1.3       +6 -25     jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/Bean.java
  
  Index: Bean.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/Bean.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Bean.java	30 Oct 2002 21:16:06 -0000	1.2
  +++ Bean.java	8 Nov 2002 14:29:35 -0000	1.3
  @@ -61,37 +61,18 @@
    * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
    * @version $Id$
    */
  -public interface Bean extends Unit {
  +public interface Bean {
       
       /**
        * Gets the Clazz for the bean.
        * 
        * @return the meta bean for the bean
        */
  -    public String getClazz();
  +    public Clazz getClazz();
   
  -    //--------------------------------------------------------------------------
  -    
  -    /**
  -     * Get the properties of the bean.
  -     *
  -     * @return map of Property objects
  -     */
  -    public Map getPropertyMap();
  -    
  -    /**
  -     * Get the number of properties.
  -     *
  -     * @return list of Property objects
  -     */
  -    public int getPropertyCount();
  +
  +    public Object get(String propertyName);
       
  -    /**
  -     * Gets a property of the class by name.
  -     *
  -     * @param name  the name to retrieve
  -     * @return a property by name
  -     */
  -    public Property getProperty(String name);
  +    public void set(String propertyName, Object value);
       
   }
  
  
  
  1.2       +169 -76   jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/Clazz.java
  
  Index: Clazz.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/Clazz.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Clazz.java	30 Oct 2002 21:16:06 -0000	1.1
  +++ Clazz.java	8 Nov 2002 14:29:35 -0000	1.2
  @@ -53,129 +53,222 @@
    */
   package org.apache.commons.clazz;
   
  +import java.util.ArrayList;
  +import java.util.Collections;
  +import java.util.Comparator;
  +import java.util.HashSet;
   import java.util.List;
  -import java.util.Map;
  +
  +import org.apache.commons.clazz.reflect.ReflectedClazzLibrary;
  +
   /**
  - * <code>Clazz</code> defines a Java class unit, either a class or interface.
  - *
  + * 
  + * 
    * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
  + * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
    * @version $Id$
    */
  -public interface Clazz extends MetaUnit {
  +public abstract class Clazz
  +{
  +    private ClazzLibrary library;
  +    private String name;
  +    
  +    // Static fields
  +    private static ArrayList libraryList = new ArrayList();
  +    private static ClazzLibrary libraries[];
  +    
  +    static {
  +        libraryList.add(ReflectedClazzLibrary.LIBRARY);
  +    }
  +    
  +    /**
  +     * Automatically detects the ClazzLibrary for the given
  +     * object and returns the corresponding Clazz from that library.
  +     */
  +    public static Clazz getClazz(Object instance){
  +        if (instance == null){
  +            throw new NullPointerException();
  +        }
  +        
  +        if (libraries == null){
  +            constructLibraryArray();
  +        }
  +        
  +        for (int i = 0; i < libraries.length; i++){
  +            if (libraries[i].isMember(instance)){
  +                return libraries[i].getClazz(instance);
  +            }
  +        }
  +        
  +        throw new ClazzNotFoundException(instance.getClass().getName());
  +    }
  +
  +    /**
  +     * Register a global ClazzLibrary. The getClazz() method
  +     * uses registered ClazzLibraries to produce a Clazz for an instance.
  +     */
  +    public static void addClazzLibrary(ClazzLibrary clazzLibrary){
  +        libraryList.add(clazzLibrary);
  +        libraries = null;
  +    }
  +    
  +    
  +    /**
  +     * Keep the constructor protected or private, we want Clazzes to 
  +     * be created by their ClazzLoaders only.
  +     *  
  +     * @param library is the owning library
  +     * @param name must be unique within the library
  +     */
  +    protected Clazz(ClazzLibrary library, String name){
  +        this.library = library;
  +        this.name = name;
  +    }
  +    
  +    /**
  +     * Every Clazz belongs to one and only one ClazzLibrary. Its name
  +     * is unique within that library.
  +     */
  +    public ClazzLibrary getClazzLibrary(){
  +        return library;
  +    }
  +    
  +    /**
  +     * Returns the name of the Clazz. Clazz names
  +     * are unique within a ClazzLibrary.
  +     * It is ok for the same name to be present in different libraries.
  +     */
  +    public String getName(){
  +        return name;
  +    }
       
       /**
        * Gets the package name.
        * 
        * @return the package name
        */
  -    public String getPackageName();
  +    public String getPackageName(){
  +        if (name == null){
  +            return null;
  +        }
  +        int index = name.lastIndexOf('.');
  +        if (index == -1){
  +            return "";
  +        }
  +        
  +        return name.substring(0, index);
  +    }
   
       /**
        * Gets the class name (without the package).
        * 
        * @return the class name (without the package)
        */
  -    public String getShortClassName();
  -
  +    public String getShortClassName(){
  +        if (name == null){
  +            return null;
  +        }
  +        int index = name.lastIndexOf('.');
  +        if (index == -1){
  +            return name;
  +        }
  +        
  +        return name.substring(index + 1);
  +    }
  +    
       /**
  -     * Queries if the clazz is an interface or a class.
  -     * 
  -     * @return true if the clazz is an interface
  +     * Returns the superclazz for this Clazz, or null if there is none.
        */
  -    public boolean isInterface();
  -
  -    //--------------------------------------------------------------------------
  +    public abstract Clazz getSuperclazz();
       
       /**
  -     * Gets the interfaces of the type in order.
  -     * 
  -     * @return list of AInterface objects
        */
  -    public List getInterfaces();
  +    public boolean isAssignableFrom(Clazz clazz){
  +        // @todo: provide default implementation
  +        return false;
  +    }
   
       /**
  -     * Gets all the interfaces of the type in order.
  -     * 
  -     * @return list of AInterface objects
  +     * Returns properties declared by this Clazz, not its superclazzes
        */
  -    public List getAllInterfaces();
  +    public abstract List getDeclaredProperties();
   
       /**
  -     * Gets the superclass of the class.
  -     *
  -     * @return the superclass
  +     * Returns all properties for this clazz, including those declared
  +     * by superclazzes.
        */
  -    public Clazz getSuperClass();
  -    
  +    public abstract List getProperties();
  +
       /**
  -     * Gets all the superclass of the class in order.
  -     *
  -     * @return the superclass
  +     * Returns the properties that match the Predicate.
        */
  -    public List getAllSuperClasses();
  -    
  -    //--------------------------------------------------------------------------
  -    
  +//    public abstract List getProperties(Predicate predicate);
  +
       /**
  -     * Get the property map of the bean.
  -     *
  -     * @return map of ClazzProperty objects
  +     * Returns a ClazzProperty for the given name
        */
  -    public Map getClazzPropertyMap();
  -    
  +    public abstract ClazzProperty getProperty(String name);
  +
       /**
  -     * Gets the number of properties.
  -     *
  -     * @return the number of properties
  +     * Returns all Operations for this clazz.
        */
  -    public int getClazzPropertyCount();
  -    
  +    public abstract List getOperations();
  +
       /**
  -     * Gets a field of the class by name.
  -     *
  -     * @param name  the name to retrieve
  -     * @return a field by name
  +     * Returns all Operations declared by this clazz, not its superclazzes.
        */
  -    public ClazzProperty getClazzProperty(String name);
  -    
  -    //--------------------------------------------------------------------------
  -    
  +    public abstract List getDeclaredOperations();
  +
       /**
  -     * Get the operations of the class in order.
  -     *
  -     * @return list of ClazzOperation objects
  +     * Returns the Operations that match the Predicate.
        */
  -    public List getClazzOperationList();
  -    
  +//    public abstract List getOperations(Predicate predicate);
  +
       /**
  -     * Gets the number of operations.
  -     *
  -     * @return the number of operations
  +     * Returns Operations for the given name
        */
  -    public int getClazzOperationCount();
  -    
  +    public abstract List getOperation(String name);
  +
       /**
  -     * Gets a operation of the class by index.
  -     *
  -     * @param index  the index to retrieve
  -     * @return a operation by index
  +     * Creates a new instance of this Clazz
        */
  -    public ClazzOperation getClazzOperation(int index);
  +    public abstract Object newInstance();
  +
  +    /**
  +     * Creates a new instance of this Clazz using the supplied parameters
  +     */
  +    public abstract Object newInstance(Object[] parameters);
       
  -    //--------------------------------------------------------------------------
       
  +    private static final ClazzLibrary[] CLASS_LIBRARY_ARRAY = 
  +            new ClazzLibrary[0];
  +            
       /**
  -     * Creates a new instance of the bean.
  -     *
  -     * @return a new instance of the object, whatever that might be
  +     * Sort libraryList by priority and convert to array for speed
        */
  -    public Object newInstance();
  +    private static void constructLibraryArray(){
  +        // Sort in the descending order of priority
  +        Collections.sort(libraryList, new Comparator(){
  +            public int compare(Object o1, Object o2){
  +                int priority1 = ((ClazzLibrary)o1).getPriority();
  +                int priority2 = ((ClazzLibrary)o2).getPriority();
  +                return priority2 - priority1;
  +            }
  +        });
  +        
  +        libraries = (ClazzLibrary[])libraryList.toArray(CLASS_LIBRARY_ARRAY);
  +    }
  +    
  +    private static HashSet loggingEnabledClasses = new HashSet();
       
       /**
  -     * Creates a new instance of the bean.
  -     *
  -     * @return a new instance as a Bean.
  +     * Enable diagnistic logging for the specified class.
        */
  -    public Bean newBean();
  +    public static void enableLogging(String className){
  +        loggingEnabledClasses.add(className);
  +    }
       
  +    public static boolean isLoggingEnabled(String className){
  +        return loggingEnabledClasses.contains(className);
  +    }
   }
  
  
  
  1.2       +5 -4      jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzModifiers.java
  
  Index: ClazzModifiers.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzModifiers.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ClazzModifiers.java	30 Oct 2002 21:16:06 -0000	1.1
  +++ ClazzModifiers.java	8 Nov 2002 14:29:35 -0000	1.2
  @@ -56,8 +56,9 @@
   import java.lang.reflect.Modifier;
   
   import org.apache.commons.lang.StringUtils;
  +
   /**
  - * <code>AModifiers</code> defines the modifiers in a manipulable way.
  + * <code>ClazzModifiers</code> defines the modifiers in a manipulable way.
    *
    * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
    * @version $Id$
  @@ -464,7 +465,7 @@
        * @return a debug string
        */
       public String toString() {
  -        StringBuffer sb = new StringBuffer("AModifiers[");
  +        StringBuffer sb = new StringBuffer("Modifiers[");
       
           if (isPublicScope()) {
               sb.append("public ");
  @@ -505,7 +506,7 @@
               sb.append("strictfp ");
           }
       
  -        if (sb.length() > 11) {
  +        if (sb.charAt(sb.length() - 1) == ' ') {
               sb.setCharAt(sb.length() - 1, ']');
           } else {
               sb.append(']');
  
  
  
  1.2       +9 -42     jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzOperation.java
  
  Index: ClazzOperation.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzOperation.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ClazzOperation.java	30 Oct 2002 21:16:06 -0000	1.1
  +++ ClazzOperation.java	8 Nov 2002 14:29:35 -0000	1.2
  @@ -53,51 +53,18 @@
    */
   package org.apache.commons.clazz;
   
  -import java.util.List;
   /**
  - * <code>ClazzOperation</code> defines a Java method.
  - *
  + * @todo
  + * 
    * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
  + * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
    * @version $Id$
    */
  -public interface ClazzOperation extends MetaUnit {
  +public interface ClazzOperation extends ClazzFeature {
  +
  +    Clazz[] getParameterClazzes();
       
  -    /**
  -     * Gets the clazz that this property is contained in.
  -     *
  -     * @return the owning meta bean
  -     */
  -    public Clazz getClazz();
  -    
  -    /**
  -     * Get the return type of the method.
  -     *
  -     * @return the return type
  -     */
  -    public Clazz getReturnType();
  -    
  -    /**
  -     * Get the parameters of the method in order.
  -     *
  -     * @return list of Clazz objects
  -     */
  -    public List getParameters();
  -    
  -    /**
  -     * Gets a parameter of the method by index.
  -     *
  -     * @param index  the index to retrieve
  -     * @return a parameter by index
  -     */
  -    public Clazz getParameter(int index);
  -    
  -    /**
  -     * Invokes the operation on a specified instance.
  -     *
  -     * @param instance  the instance to invoke
  -     * @param params  the parameters to pass to the operation
  -     * @return the result of calling the operation
  -     */
  -    public Object invoke(Object instance, Object[] params);
  +    Clazz getReturnClazz();
       
  +    Object invoke(Object target, Object[] parameters);
   }
  
  
  
  1.2       +26 -29    jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzProperty.java
  
  Index: ClazzProperty.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzProperty.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ClazzProperty.java	30 Oct 2002 21:16:06 -0000	1.1
  +++ ClazzProperty.java	8 Nov 2002 14:29:35 -0000	1.2
  @@ -54,55 +54,52 @@
   package org.apache.commons.clazz;
   
   /**
  - * <code>ClazzProperty</code> defines a field in a Java class.
  - *
  + * Describes a Property of instances of a Clazz.
  + * 
  + * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
    * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
    * @version $Id$
    */
  -public interface ClazzProperty extends MetaUnit {
  -    
  +public interface ClazzProperty extends ClazzFeature
  +{
       /**
  -     * Gets the clazz that this property is contained in.
  -     *
  -     * @return the owning meta bean
  -     */
  -    public Clazz getClazz();
  -    
  +     * Returns the name of the property.
  +     * 
  +     * @return String
  +     */    
  +    String getName();
  +
       /**
  -     * Gets the type of the property.
  -     *
  -     * @return the type of the property
  +     * Returns the property type.
        */
  -    public Clazz getType();
  +    Clazz getClazz();
       
       /**
  -     * Gets the type of the item if a List, Array or Map.
  +     * Gets the type of the item if a List or Map.
        *
        * @return the type of the item
        */
  -    public Clazz getContentType();
  +    public Clazz getContentClazz();
       
       /**
        * Gets the type of the key if a Map.
        *
        * @return the type of the key
        */
  -    public Clazz getKeyType();
  +    public Clazz getKeyClazz();
       
       /**
  -     * Gets the value of the property.
  -     *
  -     * @param instance  the instance to query
  -     * @return the value of the property in that instance
  +     * @return true if the property can not be changed
        */
  -    public Object get(Object instance);
  +    public boolean isReadOnly();
       
       /**
  -     * Sets the value of the property.
  -     *
  -     * @param instance  the instance to query
  -     * @param value  the value of the property in that instance
  +     * @todo
        */
  -    public void set(Object instance, Object value);
  +    Object get(Object instance);
       
  -}
  +    /**
  +     * @todo
  +     */
  +    void set(Object instance, Object value);
  +}
  \ No newline at end of file
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/CachingClazzLibrary.java
  
  Index: CachingClazzLibrary.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  import java.util.HashMap;
  
  /**
   * An implementation of <code>ClazzLibrary</code> that caches clazzes by name.
   *
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: CachingClazzLibrary.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public abstract class CachingClazzLibrary extends ClazzLibrary {
  
      private HashMap clazzMap = new HashMap();
      
      /**
       * @see org.apache.commons.clazz.ClazzLibrary#getClazzForName(java.lang.String)
       */
      public Clazz getClazzForName(String name) {
          Clazz clazz = (Clazz)clazzMap.get(name);
          if (clazz == null){
              ClazzLoader loaders[] = getClazzLoaders();
              for (int i = 0; i < loaders.length; i++){
                  clazz = loaders[i].getClazzForName(name);
                  if (clazz != null){
                      clazzMap.put(name, clazz);
                      break;
                  }
              }
          }
          return clazz;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzLibrary#getClazz(java.lang.Object)
       */
      public Clazz getClazz(Object instance){
          String name = getClazzName(instance);
          Clazz clazz = (Clazz)clazzMap.get(name);
          if (clazz == null){
              ClazzLoader loaders[] = getClazzLoaders();
              for (int i = 0; i < loaders.length; i++){
                  clazz = loaders[i].getClazz(instance);
                  if (clazz != null){
                      clazzMap.put(clazz.getName(), clazz);
                      break;
                  }
              }
          }
          return clazz;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzException.java
  
  Index: ClazzException.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ClazzException.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ClazzException extends RuntimeException {
  
      private Throwable cause;
      
      /**
       * Constructor for ClazzException.
       */
      public ClazzException() {
          super();
      }
  
      /**
       * Constructor for ClazzException.
       * @param s
       */
      public ClazzException(String s) {
          super(s);
      }
      
      /**
       * Constructor for ClazzException.
       * @param s
       */
      public ClazzException(String s, Throwable cause) {
          super(s);
      }
      
      public String getMessage(){
          if (cause == null){
              return super.getMessage();
          }
          return super.getMessage() + cause.getMessage(); 
      }
      
      public Throwable getCause(){
          return cause;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzFeature.java
  
  Index: ClazzFeature.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  /**
   * Common superinterface for ClazzProperty, ClazzOperation...
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ClazzFeature.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
 */
  public interface ClazzFeature {
      
      /**
       */
      Clazz getDeclaringClazz();
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzLibrary.java
  
  Index: ClazzLibrary.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Comparator;
  
  /**
   * Maintains a set of Clazzes for a certain programming model.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ClazzLibrary.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
 */
  public abstract class ClazzLibrary
  {
      private ArrayList loaderList = new ArrayList();
      private ClazzLoader loaders[];
  
      /**
       * Returns true iff this library has or can construct a Clazz for
       * the supplied instance.
       */
      public abstract boolean isMember(Object instance);
  
      /**
       * Returns the clazz name for the supplied instance.
       */
      public abstract String getClazzName(Object instance);
  
      /**
       * Given a Clazz name, returns the corresponding Clazz. Caches
       * clazzes.
       */
      public Clazz getClazzForName(String name) {
          Clazz clazz = null;
          ClazzLoader loaders[] = getClazzLoaders();
          for (int i = 0; i < loaders.length; i++){
              clazz = loaders[i].getClazzForName(name);
              if (clazz != null){
                  break;
              }
          }
          return clazz;
      }
  
      /**
       * Returns the Clazz for the supplied instance.
       */
      public Clazz getClazz(Object instance){
          Clazz clazz = null;
          ClazzLoader loaders[] = getClazzLoaders();
          for (int i = 0; i < loaders.length; i++){
              clazz = loaders[i].getClazz(instance);
              if (clazz != null){
                  break;
              }
          }
          return clazz;
      }
      
      /**
       * Registers an ClazzLoader, which is a Library plugin that does
       * the actual loading or construction of Clazzes.
       */
      public void addClazzLoader(ClazzLoader loader){
          loaderList.add(loader);
          loaders = null;
      }
  
      private static final ClazzLoader[] CLASS_LOADER_ARRAY = 
              new ClazzLoader[0];
      
      /**
       * Returns clazzloaders in the descending order of priority
       * 
     * @return ClazzLoader[] an array of clazz loaders
     */
      protected ClazzLoader[] getClazzLoaders(){
          if (loaders == null){
              // Sort in the descending order of priority
              Collections.sort(loaderList, new Comparator(){
                  public int compare(Object o1, Object o2){
                      int priority1 = ((ClazzLoader)o1).getPriority();
                      int priority2 = ((ClazzLoader)o2).getPriority();
                      return priority2 - priority1;
                  }
              });
              
              loaders = (ClazzLoader[])loaderList.toArray(CLASS_LOADER_ARRAY);            
          }
          return loaders;
      }
  
      /**
       * When Clazz is looking for a ClazzLibrary to produce a Clazz,
       * it does so in the descending order of library priorities.
       */
      public int getPriority(){
          return 0;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzLoader.java
  
  Index: ClazzLoader.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  /**
   * Constructs/loads Clazzes. ClazzLoaders are accessed indirectly
   * via ClazzLibraries.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ClazzLoader.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
 */
  public abstract class ClazzLoader
  {
      /**
       * Given a Clazz name, returns the corresponding Clazz. Does not
       * cache clazzes, that's the job of ClazzLibrary.  Return null
       * if there is no Clazz for this name.
       */
      public abstract Clazz getClazzForName(String name);
  
      /**
       * Returns true iff this library has or can construct a Clazz for
       * the supplied instance.
       */
      public abstract boolean isMember(Object instance);
  
      /**
       * Returns the Clazz for the supplied instance.
       */
      public abstract Clazz getClazz(Object instance);
  
      /**
       * When ClazzLibrary is looking for a ClazzLoader to produce a Clazz,
       * it does so in the descending order of loader priorities.
       */
      public int getPriority(){
          return 0;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/ClazzNotFoundException.java
  
  Index: ClazzNotFoundException.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz;
  
  /**
   * @todo
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ClazzNotFoundException.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
 */
  public class ClazzNotFoundException extends RuntimeException {
  
      private String className;
      
      public ClazzNotFoundException(String className){
          this.className = className;
      }
      
      public String getMessage(){
          return "Clazz not found for instance of class " + className;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/AccessorMethodParseResults.java
  
  Index: AccessorMethodParseResults.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  
  /**
   * Container for the results of method parsing: propertyName 
   * and two types. The types are used differently depending on
   * how the corresponding AccessorMethodParser uses them. 
   *  
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: AccessorMethodParseResults.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class AccessorMethodParseResults {
  
      private Method method;
      private String propertyName;
      private Class type;
      private Class parameterType;
      
      public AccessorMethodParseResults(Method method, 
                          String propertyName, Class type, Class parameterType)
      {
          this.method = method;
          this.propertyName = propertyName;
          this.type = type;
          this.parameterType = parameterType;
      }
      
      /**
       * Returns the method.
       * @return Method
       */
      public Method getMethod() {
          return method;
      }
  
      /**
       * Returns the propertyName.
       * @return String
       */
      public String getPropertyName() {
          return propertyName;
      }
  
      /**
       * Returns the type.
       * @return Class
       */
      public Class getType() {
          return type;
      }
  
      /**
       * Returns the parameterType.
       * @return Class
       */
      public Class getParameterType() {
          return parameterType;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/AccessorMethodParser.java
  
  Index: AccessorMethodParser.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: AccessorMethodParser.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class AccessorMethodParser {
      
      /**
       * If a method parsed by this parser must have a number or parameters,
       * override and return that number.  
       */
      protected int requiredParameterCount() {
          return -1;
      }
  
      /**
       * If a method parsed by this parser must have a certain prefix,
       * override and return a non-null prefix string  
       */
      protected String requiredPrefix() {
          return null;
      }
  
      /**
       * To check constraints on the return type of methods parsed
       * by this parser, override and perform the check.
       *  
     * @param javaClass The return type of the method (never null)
     * @return boolean True if the return type passes the parser's constraints
     */    
      protected boolean testReturnType(Class javaClass){
          return true;
      }
      
      /**
       * To check constraints on the type of a parameter, override 
       * and perform the check.
       *  
       * @param javaClass The return type of the method (never null)
       * @return boolean True if the return type passes the parser's constraints
       */    
      protected boolean testParameterType(int index, Class parameterType){
          return true;
      }
      
      /**
       * If a method parsed by this parser must have a certain suffix,
       * override this method, check that it does and remove the
       * suffix.
       */
      protected String testAndRemoveSuffix(String methodName){
          return methodName;
      }
      
      /**
       * Extract the value type from the method. Depending on the type
       * of method, it could be the return type or the type of a parameter.
       */
      protected Class getValueType(Method method){
          return null;
      }
      
      /**
       * Extract the parameter type from the method, if it has one. 
       * For example a mapped property "get" method might have
       * a "key" parameter.
       */
      protected Class getParameterType(Method method){
          return null;
      }
  
      /**
       * Parses the supplied method according to the parser's configuration.
       * If the parse process fails, returns null.
       * 
     * @param method
     * @return AccessorMethodParseResults
     */
      public AccessorMethodParseResults parse(Method method){
          int modifiers = method.getModifiers();
  
          // An accessor methods must be public and non-static
          if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers)){
              return null;
          }
  
          Class returnType = method.getReturnType();
          if (returnType == null){
              returnType = Void.TYPE; 
          }
          if (!testReturnType(returnType)){
              return null;
          }
          
          int reqParamCount = requiredParameterCount();
          if (reqParamCount != -1){
              Class paramTypes[] = method.getParameterTypes();
              if (paramTypes.length != reqParamCount){
                  return null;
              }
              
              for (int i = 0; i < paramTypes.length; i++) {
                  if (!testParameterType(i, paramTypes[i])){
                      return null;
                  }
              }
          }
          
          String propertyName = parseMethodName(method);
          if (propertyName == null) {
              return null;
          }
          
          return new AccessorMethodParseResults(
                          method, 
                          propertyName, 
                          getValueType(method), 
                          getParameterType(method));
      }
      
      /**
       * Parse method name and return the corresponding property name.
       * Return null if the method name does not satisfy the parser's
       * grammar.
       * <p>
       * The default implementation of the method checks if the 
       * method name starts with the specified prefix followed
       * by an optionally capitalized property name.
       * 
     * @param methodName
     * @return String
     */
      protected String parseMethodName(Method method){
          String name = method.getName();
          name = testAndRemoveSuffix(name);
          if (name == null){
              return null;
          }
          
          String prefix = requiredPrefix(); 
          if (prefix == null){
              return name;
          }
          
          if (name.length() <= prefix.length()){
              return null;
          }
          
          if (name.startsWith(prefix)){
              return decapitalize(name.substring(prefix.length()));
          }
          return null;
      }
      
      /**
       * Changes the first character of the <code>string</code>
       * to lower case, unless the second character is
       * upper case.  This is consistent with the JavaBean specification.
       * 
       * @param candidate
       * @return String
       */
      protected String decapitalize(String string)
      {
          char firstChar = string.charAt(0);
          if (!Character.isUpperCase(firstChar)){
              return string;
          }
          
          int len = string.length();
          if (len == 1){
              return String.valueOf(Character.toLowerCase(firstChar));
          }
          else if (Character.isLowerCase(string.charAt(1))){
              char buffer[] = new char[len];
              buffer[0] = Character.toLowerCase(firstChar);
              string.getChars(1, len, buffer, 1);
              return new String(buffer);
          }
          
          return string;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedClazz.java
  
  Index: ReflectedClazz.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzLibrary;
  import org.apache.commons.clazz.ClazzOperation;
  import org.apache.commons.clazz.ClazzProperty;
  
  /**
   * This implementation of Clazz is based on Java reflection. 
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedClazz.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedClazz extends Clazz {
  
      private boolean superClazzKnown;
      private Clazz superClazz;
      private Class javaClass;
      private Map propertyMap;
      private List propertyList;
      private List declaredPropertyList;
      
      /**
       * The default list of introspectors consists of List, Mapped and Scalar
       * property introspectors.
     */
      private static final ReflectedPropertyIntrospector[] DEFAULT_INTROSPECTORS =
          new ReflectedPropertyIntrospector[] {
              ReflectedListPropertyIntrospector.INTROSPECTOR,
              ReflectedMappedPropertyIntrospector.INTROSPECTOR,
              ReflectedScalarPropertyIntrospector.INTROSPECTOR };
      
      /**
       * Constructor for ReflectedClazz.
       * 
       * @param library
       * @param name
       */
      public ReflectedClazz(ClazzLibrary library, Class javaClass) {
          super(library, javaClass.getName());
          this.javaClass = javaClass;
      }
  
      /**
       * The default list of introspectors consists of List, Mapped and Scalar
       * property introspectors. The order of introspectors is significant,
       * they are invoked sequencially. Once a property has been recoginzed
       * by an introspector, it will not be overridden by subsequently invoked
       * ones.
       */
      protected ReflectedPropertyIntrospector[] 
                          getReflectedPropertyIntrospectors() 
      {
          return DEFAULT_INTROSPECTORS;
      }
      
      /**
       * Returns true if diagnostic is enabled for this clazz
     */
      protected boolean isLoggingEnabled(){
          return Clazz.isLoggingEnabled(getName());
      }
      
      /**
       * Returns the class this ReflectedClazz is based upon.
     * @return Class
     */
      public Class getReflectedClass(){
          return javaClass;
      }
      
      /**
       * @see org.apache.commons.clazz.Clazz#getSuperClazz()
       */
      public Clazz getSuperclazz() {
          if (!superClazzKnown){
              superClazzKnown = true;
              Class superclass = javaClass.getSuperclass();
              if (superclass == null){
                  superClazz = null;
              }
              else {
                  superClazz = getClazzLibrary().
                          getClazzForName(superclass.getName());
              }
          }
          return superClazz;
      }
  
      /**
       * Returns properties introduced by this clazz as compared 
       * to the superclazz.  Note, that some of the methods comprizing
       * a property may be declared on the superclass. This makes it
       * impossible to build a list of declared properties by looking
       * exclusively at the current class - we have to reflected all
       * properties of this clazz, then all properties of the superclazz
       * and then subtract the latter from the former.
       */
      public List getDeclaredProperties() {
          if (declaredPropertyList == null){
              if (javaClass.getSuperclass() == null){
                  declaredPropertyList = getProperties();
              }
              else {
                  List superProperties = getSuperclazz().getProperties();
                  if (superProperties.size() == 0){
                      declaredPropertyList = getProperties();
                  }
                  else {
                      HashSet superNames = new HashSet();
                      for (int i = 0; i < superProperties.size(); i++){
                          ClazzProperty property = 
                                  (ClazzProperty)superProperties.get(i);
                          superNames.add(property.getName());
                      } 
                      
                      List properties = getProperties();
                      declaredPropertyList = new ArrayList();                    
                      for (int i = 0; i < properties.size(); i++){
                          ClazzProperty property =
                              (ClazzProperty) properties.get(i);
                          String name = property.getName();
                          if (!superNames.contains(name)){
                              declaredPropertyList.add(property);
                          }                        
                      }
                  }
              }
          }
          return declaredPropertyList;
      }
  
      /**
       */
      public List getProperties() {
          if (propertyList == null){
              introspectProperties();
          }
          return propertyList;
      }
  
      /**
       */
      public ClazzProperty getProperty(String name) {
          if (propertyMap == null){
              introspectProperties();
          }
          return (ClazzProperty)propertyMap.get(name);
      }
  
      protected void addProperty(ReflectedProperty property){
          propertyMap.put(property.getName(), property);
          String[] aliases = property.getAliases();
          for (int i = 0; i < aliases.length; i++) {
              propertyMap.put(aliases[i], property);
          }
          propertyList.add(property);
      }
      
      /**
       */
      public List getOperations() {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.Clazz#getDeclaredOperations()
       */
      public List getDeclaredOperations() {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.Clazz#getOperation(java.lang.String)
       */
      public List getOperation(String name) {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.Clazz#newInstance()
       */
      public Object newInstance() {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.Clazz#newInstance(java.lang.Object)
       */
      public Object newInstance(Object[] parameters) {
          return null;
      }
  
      /**
       * Override this method to provide an alternate way of mapping
       * fields and methods to properties.
       */   
      protected void introspectProperties()
      {
          propertyMap = new HashMap();
          propertyList = new ArrayList();
  
          ReflectedPropertyIntrospector[] introspectors =
                  getReflectedPropertyIntrospectors();
          for (int i = 0; i < introspectors.length; i++) {
              List properties =
                      introspectors[i].introspectProperties(this, javaClass);
              for (int j = 0; j < properties.size(); j++) {
                  ReflectedProperty property =
                          (ReflectedProperty) properties.get(j);
                  addProperty(property);
              }
          }
  
          if (isLoggingEnabled()) {
              logPropertyParseResults();
          }
      }
      
          
      private List propertyParseResults;
      
      /**
       * Called by ReflectedPropertyIntrospector's to log results of
       * introspection, successful or not.
       */
      protected void logPropertyParseResults(
              ReflectedPropertyParseResults parseResults) 
      {
          if (propertyParseResults == null){
              propertyParseResults = new ArrayList();
          }
          propertyParseResults.add(parseResults);
      }
      
      /**
       * Prints diagnostics of property introspection.
     */
      protected void logPropertyParseResults(){
          if (propertyParseResults == null){
              return;
          }
                  
          Collections.sort(propertyParseResults, new Comparator(){
              public int compare(Object o1, Object o2) {
                  String n1 =
                      ((ReflectedPropertyParseResults) o1).getPropertyName();
                  String n2 =
                      ((ReflectedPropertyParseResults) o2).getPropertyName();
                  return n1.compareTo(n2);
              }
          });
          
          // @todo: use a logger
          System.err.println("[Clazz: " + getName());
          for (int i = 0; i < propertyParseResults.size(); i++){
              System.err.println(propertyParseResults.get(i));            
          }
          System.err.println("]");
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedClazzLibrary.java
  
  Index: ReflectedClazzLibrary.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import org.apache.commons.clazz.CachingClazzLibrary;
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzLibrary;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedClazzLibrary.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedClazzLibrary extends CachingClazzLibrary {
  
      public static final ReflectedClazzLibrary LIBRARY =
                                  new ReflectedClazzLibrary();
  
      static {                           
          LIBRARY.addClazzLoader(new ReflectedClazzLoader(LIBRARY));
      }
      
      protected ReflectedClazzLibrary(){
      }
          
      /**
       * @see org.apache.commons.clazz.ClazzLibrary#isMember(java.lang.Object)
       */
      public boolean isMember(Object instance) {
          return true;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzLibrary#getClazzName(java.lang.Object)
       */
      public String getClazzName(Object instance) {
          if (instance == null){
              return null;
          }
          return instance.getClass().getName();
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzLibrary#getPriority()
       */
      public int getPriority() {
          return -1;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedClazzLoader.java
  
  Index: ReflectedClazzLoader.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzLibrary;
  import org.apache.commons.clazz.ClazzLoader;
  import org.apache.commons.clazz.ClazzNotFoundException;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedClazzLoader.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedClazzLoader extends ClazzLoader {
  
      private ClazzLibrary library;
      
      public ReflectedClazzLoader(ClazzLibrary library){
          this.library = library;
      }
      
      /**
       * @see org.apache.commons.clazz.ClazzLoader#getClazzForName(java.lang.String)
       */
      public Clazz getClazzForName(String name) {
          Class javaClass;
          try {
              javaClass = Class.forName(name);
          }
          catch (ClassNotFoundException ex){
              throw new ClazzNotFoundException(name);
          }
          return new ReflectedClazz(library, javaClass);
      }
  
      /**
       * Returns <code>true</code> for all objects.
       * 
       * @see org.apache.commons.clazz.ClazzLoader#isMember(java.lang.Object)
       */
      public boolean isMember(Object instance) {
          return true;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzLoader#getClazz(java.lang.Object)
       */
      public Clazz getClazz(Object instance) {
          if (instance == null){
              return null;
          }
          
          return new ReflectedClazz(library, instance.getClass());
      }
  
      /**
       * Return -1, the lowest allowed priority
       * 
       * @see org.apache.commons.clazz.ClazzLoader#getPriority()
       */
      public int getPriority() {
          return -1;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedFeature.java
  
  Index: ReflectedFeature.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzFeature;
  import org.apache.commons.clazz.ClazzProperty;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedFeature.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedFeature implements ClazzFeature {
  
      private Clazz declaringClazz;
  
      /**
       * Constructor for ClazzFeature.
       */
      public ReflectedFeature(Clazz declaringClazz) {
          this.declaringClazz = declaringClazz;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzFeature#getDeclaringClazz()
       */
      public Clazz getDeclaringClazz() {
          return declaringClazz;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedList.java
  
  Index: ReflectedList.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Array;
  import java.lang.reflect.Method;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.List;
  import java.util.ListIterator;
  
  import org.apache.commons.clazz.ClazzException;
  
  /**
   * This is an implementation of the <code>List</code> interface
   * that is based on a List property.  Whenever possible, it
   * uses concrete methods on the owner of the property to manipulate 
   * the list or array.
   * <p>
   * Consider the following example:
   * <pre>
   *      List list = (List)clazz.getProperty("fooList").get(instance);
   *      Object value = list.get(3);
   * </pre>
   * 
   * If <code>instance</code> has a <code>getFoo(int index)</code> method,
   * this code will implicitly invoke it like this: <code>getFoo(3)</code>,
   * otherwise it will obtain the whole list or array and extract the 
   * requested element.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedList.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedList implements List {
      
      private Object instance;
      private ReflectedListProperty property;
      
      /**
       * Constructor for ReflectedList.
       */
      public ReflectedList(
              Object instance,
              ReflectedListProperty property) 
      {
          this.instance = instance;
          this.property = property;
      }
  
      /**
       * @see java.util.Collection#size()
       */
      public int size() {
          Method sizeMethod = property.getSizeMethod();
          if (sizeMethod != null){
              try {
                  Object value = sizeMethod.invoke(instance, null);
                  return ((Integer)value).intValue();
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot get list size: "
                          + property.getName()
                          + ": cannot invoke method: "
                          + sizeMethod.getName(),
                      ex);
              }
          }
          else {
              Object list = property.getList(instance);
              if (list == null){
                  return 0;
              }
              
              if (list instanceof List){
                  return ((List)list).size();
              }
             
              return Array.getLength(list);
          }
      }
  
      /**
       * @see java.util.Collection#isEmpty()
       */
      public boolean isEmpty() {
          return false;
      }
  
      /**
       * @see java.util.Collection#contains(java.lang.Object)
       */
      public boolean contains(Object o) {
          return false;
      }
  
      /**
       * @see java.util.Collection#iterator()
       */
      public Iterator iterator() {
          return null;
      }
  
      /**
       * @see java.util.Collection#toArray()
       */
      public Object[] toArray() {
          return null;
      }
  
      /**
       * @see java.util.Collection#toArray(java.lang.Object)
       */
      public Object[] toArray(Object[] a) {
          return null;
      }
  
      /**
       * @see java.util.Collection#add(java.lang.Object)
       */
      public boolean add(Object o) {
          return false;
      }
  
      /**
       * @see java.util.Collection#remove(java.lang.Object)
       */
      public boolean remove(Object o) {
          return false;
      }
  
      /**
       * @see java.util.Collection#containsAll(java.util.Collection)
       */
      public boolean containsAll(Collection c) {
          return false;
      }
  
      /**
       * @see java.util.Collection#addAll(java.util.Collection)
       */
      public boolean addAll(Collection c) {
          return false;
      }
  
      /**
       * @see java.util.List#addAll(int, java.util.Collection)
       */
      public boolean addAll(int index, Collection c) {
          return false;
      }
  
      /**
       * @see java.util.Collection#removeAll(java.util.Collection)
       */
      public boolean removeAll(Collection c) {
          return false;
      }
  
      /**
       * @see java.util.Collection#retainAll(java.util.Collection)
       */
      public boolean retainAll(Collection c) {
          return false;
      }
  
      /**
       * @see java.util.Collection#clear()
       */
      public void clear() {
      }
  
      /**
       * @see java.util.List#get(int)
       */
      public Object get(int index) {
          Method getMethod = property.getGetMethod();
          if (getMethod != null){
              Object value;
              try {
                  value =
                      getMethod.invoke(
                          instance,
                          new Object[] { new Integer(index)});
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot get property : "
                          + property.getName()
                          + ": cannot invoke method: "
                          + getMethod.getName(),
                      ex);
              }
              return value;
          }
          else {
              Object list = property.getList(instance);
              if (list == null){
                  return null;
              }
              
              if (list instanceof List){
                  return ((List)list).get(index);
              }
             
              return Array.get(list, index);
          }
      }
  
      /**
       * @see java.util.List#set(int, java.lang.Object)
       */
      public Object set(int index, Object element) {
          Method setMethod = property.getSetMethod();
          if (setMethod != null){
              Object oldValue = get(index);
              try {
                  setMethod.invoke(
                      instance,
                      new Object[] { new Integer(index), element });
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot set property : "
                          + property.getName()
                          + ": cannot invoke method: "
                          + setMethod.getName(),
                      ex);
              }
              return oldValue;
          }
          else {
              Object list = property.getList(instance);
              if (list == null){
                  return null;
              }
              
              if (list instanceof List){
                  return ((List)list).set(index, element);
              }
             
              Object oldValue = Array.get(list, index);
              Array.set(list, index, element);
              return oldValue;
          }
      }
  
      /**
       * @see java.util.List#add(int, java.lang.Object)
       */
      public void add(int index, Object element) {
      }
  
      /**
       * @see java.util.List#remove(int)
       */
      public Object remove(int index) {
          return null;
      }
  
      /**
       * @see java.util.List#indexOf(java.lang.Object)
       */
      public int indexOf(Object o) {
          return 0;
      }
  
      /**
       * @see java.util.List#lastIndexOf(java.lang.Object)
       */
      public int lastIndexOf(Object o) {
          return 0;
      }
  
      /**
       * @see java.util.List#listIterator()
       */
      public ListIterator listIterator() {
          return null;
      }
  
      /**
       * @see java.util.List#listIterator(int)
       */
      public ListIterator listIterator(int index) {
          return null;
      }
  
      /**
       * @see java.util.List#subList(int, int)
       */
      public List subList(int fromIndex, int toIndex) {
          return null;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedListProperty.java
  
  Index: ReflectedListProperty.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedListProperty.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedListProperty extends ReflectedProperty {
  
      private Class contentType;
      private Method sizeMethod;
      private Method getMethod;
      private Method addMethod;
      private Method addIndexedMethod;
      private Method setMethod;
      private Method removeMethod;
      
      /**
       * Constructor for ReflectedListProperty.
       * @param declaringClazz
       * @param name
       */
      public ReflectedListProperty(Clazz declaringClazz, String name) {
          super(declaringClazz, name);
      }
  
      /**
       * Returns the contentType.
       * @return Class
       */
      public Class getContentType() {
          return contentType;
      }
  
      /**
       * Sets the contentType.
       * @param contentType The contentType to set
       */
      public void setContentType(Class valueType) {
          this.contentType = valueType;
      }
      
      /**
       * Returns the getMethod.
       * @return Method
       */
      public Method getGetMethod() {
          return getMethod;
      }
  
      /**
       * Sets the getMethod.
       * @param getMethod The getMethod to set
       */
      public void setGetMethod(Method getMethod) {
          this.getMethod = getMethod;
      }
      
     /**
       * Returns the setMethod.
       * @return Method
       */
      public Method getSetMethod() {
          return setMethod;
      }
  
      /**
       * Sets the setMethod.
       * @param setMethod The setMethod to set
       */
      public void setSetMethod(Method setMethod) {
          this.setMethod = setMethod;
      }
  
      /**
       * Returns the addMethod.
       * @return Method
       */
      public Method getAddMethod() {
          return addMethod;
      }
  
      /**
       * Sets the addMethod.
       * @param addMethod The addMethod to set
       */
      public void setAddMethod(Method addMethod) {
          this.addMethod = addMethod;
      }
  
      /**
       * Returns the addIndexedMethod.
       * @return Method
       */
      public Method getAddIndexedMethod() {
          return addIndexedMethod;
      }
  
      /**
       * Sets the addIndexedMethod.
       * @param addIndexedMethod The addIndexedMethod to set
       */
      public void setAddIndexedMethod(Method addIndexedMethod) {
          this.addIndexedMethod = addIndexedMethod;
      }
  
      /**
       * Returns the removeMethod.
       * @return Method
       */
      public Method getRemoveMethod() {
          return removeMethod;
      }
  
      /**
       * Sets the removeMethod.
       * @param removeMethod The removeMethod to set
       */
      public void setRemoveMethod(Method removeMethod) {
          this.removeMethod = removeMethod;
      }
  
      /**
       * Returns the sizeMethod.
       * @return Method
       */
      public Method getSizeMethod() {
          return sizeMethod;
      }
  
      /**
       * Sets the sizeMethod.
       * @param sizeMethod The sizeMethod to set
       */
      public void setSizeMethod(Method sizeMethod) {
          this.sizeMethod = sizeMethod;
      }
  
      public String toString(){
          StringBuffer buffer = new StringBuffer("[ReflectedListProperty ");
          if (getType() != null){
              buffer.append(getType().getName());
              buffer.append(" ");
          }
          if (getContentType() != null){
              buffer.append("[content: ");
              buffer.append(getContentType().getName());
              buffer.append("] ");
          }
          buffer.append(getName());
          if (getReadMethod() != null){
              buffer.append("\n   [read method]   ");
              buffer.append(getReadMethod());            
          }
          if (getWriteMethod() != null){
              buffer.append("\n   [write method]  ");
              buffer.append(getWriteMethod());            
          }
          if (getGetMethod() != null){
              buffer.append("\n   [get method]    ");
              buffer.append(getGetMethod());            
          }
          if (getSetMethod() != null){
              buffer.append("\n   [set method]    ");
              buffer.append(getSetMethod());            
          }
          if (getAddMethod() != null){
              buffer.append("\n   [add method]    ");
              buffer.append(getAddMethod());            
          }
          if (getAddIndexedMethod() != null){
              buffer.append("\n   [add(i) method] ");
              buffer.append(getAddIndexedMethod());            
          }
          if (getRemoveMethod() != null){
              buffer.append("\n   [remove method] ");
              buffer.append(getRemoveMethod());            
          }
          if (getSizeMethod() != null){
              buffer.append("\n   [size method]   ");
              buffer.append(getSizeMethod());            
          }
          buffer.append("]");
          return buffer.toString();
      }
      /**
       * @see org.apache.commons.clazz.ClazzProperty#get(java.lang.Object)
       */
      public Object get(Object instance) {
          return new ReflectedList(instance, this);
      }
      
      public Object getList(Object instance) {
          if (getReadMethod() == null){
              return null;
          }
          
          return super.get(instance);
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#set(java.lang.Object, java.lang.Object)
       */
      public void set(Object instance, Object value) {
          super.set(instance, value);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedListPropertyIntrospector.java
  
  Index: ReflectedListPropertyIntrospector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * A ReflectedPropertyIntrospector that discovers list (aka indexed) properties.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedListPropertyIntrospector.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedListPropertyIntrospector
      extends ReflectedPropertyIntrospectorSupport 
  {
  
      /**
       * The global instance of ReflectedListPropertyIntrospector that
       * should be used by ReflectedClass to create list properties.
     */
      public static final ReflectedListPropertyIntrospector INTROSPECTOR =
              new ReflectedListPropertyIntrospector();
   
      /**
       * Singleton - not supposed to be allocated by clients. Use
       * the <code>INTROSPECTOR</code> static field instead.
       */
      protected ReflectedListPropertyIntrospector(){
      }
      
      public void introspectProperties(
              ReflectedClazz clazz,
              Class javaClass,
              Map parseResultMap)
      {
          HashMap parseResultMapSingular = new HashMap();
          Method methods[] = javaClass.getMethods();
          ReflectedListPropertyParseResults parseResults;
          AccessorMethodParseResults results;
          for (int i = 0; i < methods.length; i++) {
              Method method = methods[i];
  
              // Check getFooCount() before we check getFooList(),
              // because the parser for the latter is generic enough
              // to include the former            
              results = parseSizeMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setSizeMethodParseResults(results);
                  continue;
              }
              
              results = parseReadMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setReadMethodParseResults(results);
                  continue;
              }
  
              results = parseWriteMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setWriteMethodParseResults(results);
                  continue;
              }
  
              results = parseGetMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setGetMethodParseResults(results);
                  continue;
              }
              
              results = parseSetMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setSetMethodParseResults(results);
                  continue;
              }
              
              results = parseAddMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setAddMethodParseResults(results);
                  continue;
              }
              
              results = parseAddIndexedMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setAddIndexedMethodParseResults(results);
                  continue;
              }
              
              results = parseRemoveMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setRemoveMethodParseResults(results);
                  continue;
              }
          }
          
          Iterator iter = parseResultMap.entrySet().iterator();
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              ReflectedListPropertyParseResults result = 
                  (ReflectedListPropertyParseResults) entry.getValue();
              if (!result.isList()){
                  iter.remove();
              }
          }
          
          mergeSingularMethods(parseResultMap, parseResultMapSingular);
      }
  
      /**
       * Parser for the <code>getFooMap()</code> method:
       * <ul>
       *  <li>Return type not void</li>
       *  <li>Name starts with "get" followed by capitalized property name</li>
       *  <li>No parameters</li>
       * </ul>
       * 
       * We don't check if the parameter is a List here. If it is not,
       * we want to recognize the method and them mark the corresponding
       * property as NotAProperty.
       */
      protected static AccessorMethodParser READ_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class returnType){
              return !returnType.equals(Void.TYPE);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 0;
          }
  
          protected Class getValueType(Method method){
              return method.getReturnType();
          }
          
      };
              
      /**
       * Looks at the method to see if it has the signature
       * of a property read method, like "List getIntegerList()", parses it
       * and returns the results of parsing.  If the method signature 
       * does not fit the criteria, returns <code>null</code>.
       */
      protected AccessorMethodParseResults parseReadMethod(Method method) {
          return READ_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>setFooList(List)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "set" followed by capitalized property name</li>
       *  <li>One parameter</li>
       * </ul>
       * 
       * We don't check if the parameter is a List here. If it is not,
       * we want to recognize the method and them mark the corresponding
       * property as NotAProperty.
       */            
      protected static AccessorMethodParser WRITE_METHOD_PARSER =
              new AccessorMethodParser()
      {
          protected boolean testReturnType(Class returnType){
              return returnType.equals(Void.TYPE);
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected String requiredPrefix(){
              return "set";
          }
                  
          protected Class getValueType(Method method){
              return method.getParameterTypes()[0];
          }
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseWriteMethod(Method method) {
          return WRITE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>getFoo(int)</code> method:
       * <ul>
       *  <li>Return type not void</li>
       *  <li>Name starts with "get" followed by capitalized singular
       *      form of the property name</li>
       *  <li>One integer parameter</li>
       * </ul>
       */            
      protected static AccessorMethodParser GET_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class returnType){
              return !returnType.equals(Void.TYPE);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected boolean testParameterType(int index, Class parameterType){            
              return parameterType.equals(Integer.TYPE);
          }
          
          protected Class getValueType(Method method){
              return method.getReturnType();
          }
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseGetMethod(Method method) {
          return GET_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>setFoo(index, value)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "set" followed by capitalized singular
       *      form of the property name</li>
       *  <li>Two parameters, first integer</li>
       * </ul>
       */                        
      protected static AccessorMethodParser SET_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "set";
          }
          
          protected int requiredParameterCount(){
              return 2;
          }
  
          protected boolean testParameterType(int index, Class parameterType){
              if (index == 0){            
                  return parameterType.equals(Integer.TYPE);
              }
              return true;
          }
          
          protected Class getValueType(Method method){
              return method.getParameterTypes()[1];
          }                
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseSetMethod(Method method) {
          return SET_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>addFoo(value)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "add" followed by capitalized singular
       *      form of the property name</li>
       *  <li>One parameter</li>
       * </ul>
       */                        
      protected static AccessorMethodParser ADD_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "add";
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected Class getValueType(Method method){
              return method.getParameterTypes()[0];
          }        
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseAddMethod(Method method) {
          return ADD_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>addFoo(index, value)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "add" followed by capitalized singular
       *      form of the property name</li>
       *  <li>Two parameters, first integer</li>
       * </ul>
       */                        
      protected static AccessorMethodParser ADD_INDEXED_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "add";
          }
          
          protected int requiredParameterCount(){
              return 2;
          }
  
          protected boolean testParameterType(int index, Class parameterType){            
              if (index == 0){            
                  return parameterType.equals(Integer.TYPE);
              }
              return true;
          }
          
          protected Class getValueType(Method method){
              return method.getParameterTypes()[1];
          }        
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseAddIndexedMethod(Method method) {
          return ADD_INDEXED_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>removeFoo(index)</code> method:
       * <ul>
       *  <li>Name starts with "remove" followed by capitalized singular
       *      form of the property name</li>
       *  <li>One parameter</li>
       * </ul>
       */                        
      protected static AccessorMethodParser REMOVE_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "remove";
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected Class getValueType(Method method){
              return method.getParameterTypes()[0];
          }
      };
                          
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseRemoveMethod(Method method) {
          return REMOVE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>getFooCount()</code> method:
       * <ul>
       *  <li>Returns integer</li>
       *  <li>Name starts with "get" followed by capitalized singular
       *      form of the property name, followed by "Count" or "Size"</li>
       *  <li>No parameters</li>
       * </ul>
       */                        
      protected static AccessorMethodParser SIZE_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class javaClass){
              return javaClass.equals(Integer.TYPE);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 0;
          }
          
          protected String testAndRemoveSuffix(String methodName){
              if (methodName.endsWith("Count")){                
                  return methodName.substring(0, methodName.length() - 5);
              }
              if (methodName.endsWith("Size")){
                  return methodName.substring(0, methodName.length() - 4);
              }
              return null;
          }
      };
                          
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseSizeMethod(Method method) {
          return SIZE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Combines data collected from singular methods like 
       * <code>getFoo(index)</code> with Properties, which already
       * contain data about plural methods like <code>getFooList()</code>. 
       */    
      protected void mergeSingularMethods(
              Map parseResultMapPlural, Map parseResultMapSingular)
      {
          Iterator iter = parseResultMapSingular.values().iterator();
          while (iter.hasNext()) {
              
              ReflectedListPropertyParseResults singular =
                  (ReflectedListPropertyParseResults) iter.next();
                  
              ReflectedListPropertyParseResults plural =
                  findBySingularName(
                          parseResultMapPlural, singular.getPropertyName());
              
              if (plural != null) {
                  plural.merge(singular);
              }
              else {
                  // We don't have any plural methods - let's just use
                  // the singular ones then
                  parseResultMapPlural.put(singular.getPropertyName(), singular);
              }
          }
      }
  
      /**
       * Given a singular form of a property name, locates parse results
       * for a property with the corresponding plural name.
       */
      protected ReflectedListPropertyParseResults findBySingularName(
              Map parseResultMapPlural,
              String singularName) 
      {
          ReflectedListPropertyParseResults plural =
              (ReflectedListPropertyParseResults) 
                  parseResultMapPlural.get(singularName);
          if (plural != null) {
              return plural;
          }
  
          Iterator iter = parseResultMapPlural.entrySet().iterator();
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              if (isCorrectPluralForm(singularName, (String) entry.getKey())) {
                  return (ReflectedListPropertyParseResults) entry.getValue();
              }
          }
          return null;
      }
  
      /**
       * Returns <code>true</code> if the suffix is "s" or 
       * "List", "Array" or "Vector".
       *  
       * @see org.apache.commons.clazz.reflect.ReflectedPropertyFactorySupport#isCorrectPluralSuffix(String, String)
       */
      protected boolean isCorrectPluralSuffix(String singular, String suffix){
          return super.isCorrectPluralSuffix(singular, suffix) || 
                  suffix.equals("List") ||
                  suffix.equals("Array") ||
                  suffix.equals("Vector");
      }
      /**
       * Finds a ReflectedListPropertyParseResults for the given
       * propertyName or creates a new one and puts it in the map.
       */
      protected ReflectedListPropertyParseResults getParseResults(
              ReflectedClazz clazz,
              Map parseResultMap,
              String propertyName) 
      {
          ReflectedListPropertyParseResults parseResults =
              (ReflectedListPropertyParseResults) parseResultMap.get(
                  propertyName);
          if (parseResults == null) {
              parseResults =
                  new ReflectedListPropertyParseResults(clazz, propertyName);
              parseResultMap.put(propertyName, parseResults);
          }
          return parseResults;
      }
      
      /**
       * Creates a new ReflectedListProperty based on parse results. 
       */
      protected ReflectedProperty createProperty(
          ReflectedClazz clazz,
          ReflectedPropertyParseResults parseResults)
      {
          ReflectedListProperty property =
              new ReflectedListProperty(clazz, parseResults.getPropertyName());
  
          ReflectedListPropertyParseResults parseResultsList =
                  (ReflectedListPropertyParseResults)parseResults;
          
          property.setAliases(parseResultsList.getAliases());
          property.setType(parseResultsList.getPropertyType());
          property.setContentType(parseResultsList.getContentType());
          property.setReadMethod(parseResultsList.getReadMethod());
          property.setWriteMethod(parseResultsList.getWriteMethod());
          property.setGetMethod(parseResultsList.getGetMethod());
          property.setSetMethod(parseResultsList.getSetMethod());
          property.setAddMethod(parseResultsList.getAddMethod());
          property.setAddIndexedMethod(parseResultsList.getAddIndexedMethod());
          property.setRemoveMethod(parseResultsList.getRemoveMethod());
          property.setSizeMethod(parseResultsList.getSizeMethod());
          return property;
      }     
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedListPropertyParseResults.java
  
  Index: ReflectedListPropertyParseResults.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.List;
  import java.util.Map;
  
  /**
   * Holds parse results for individual accessor methods for a 
   * list property.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedListPropertyParseResults.java,v 1.1 2002/11/08 14:29:35 dmitri Exp $
   */
  public class ReflectedListPropertyParseResults 
              extends ReflectedPropertyParseResults
  {
      private AccessorMethodParseResults getMethodParseResults;
      private AccessorMethodParseResults setMethodParseResults;
      private AccessorMethodParseResults addMethodParseResults;
      private AccessorMethodParseResults addIndexedMethodParseResults;
      private AccessorMethodParseResults removeMethodParseResults;
      
      private AccessorMethodParseResults sizeMethodParseResults;
      
  
      /**
       * Constructor for ReflectedMappedPropertyParseResults.
       */
      public ReflectedListPropertyParseResults(
              ReflectedClazz clazz, String propertyName) 
      {
          super(clazz, propertyName);
      }
      
      protected String getPropertyCategory(){
          return "list";
      }
      
      /**
       * Returns <code>true</code> if the property is an array or 
       * implements java.util.List.
       */
      protected boolean isList(){
          if (readMethodParseResults != null &&
                  isList(readMethodParseResults.getType())){
              return true;
          }
          if (writeMethodParseResults != null &&
                  isList(writeMethodParseResults.getType())){
              return true;
          }
          return false;        
      }
          
      /**
       * Returns <code>true</code> if javaClass is an array or 
       * implements java.util.List.
       */
      protected boolean isList(Class javaClass){
          return javaClass != null
              && (List.class.isAssignableFrom(javaClass) || javaClass.isArray());
      }
      
      /**
       * Returns the type of the list/array element, if known. 
       * Returns <code>null</code> otherwise.
     */
      public Class getContentType(){
          if (getMethodParseResults != null){
              return getMethodParseResults.getType();
          }
          if (setMethodParseResults != null){
              return setMethodParseResults.getType();
          }
          if (addMethodParseResults != null){
              return addMethodParseResults.getType();
          }
          if (addIndexedMethodParseResults != null){
              return addIndexedMethodParseResults.getType();
          }
          if (removeMethodParseResults != null){
              return removeMethodParseResults.getType();
          }
          return null;
      }
  
      public void setGetMethodParseResults(
                  AccessorMethodParseResults getMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.getMethodParseResults,
              getMethodParseResults);
          this.getMethodParseResults = getMethodParseResults;
      }
  
      public Method getGetMethod() {
          if (getMethodParseResults == null){
              return null;
          }
          return getMethodParseResults.getMethod();
      }
      
      public void setSetMethodParseResults(
                  AccessorMethodParseResults setMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.setMethodParseResults,
              setMethodParseResults);
          this.setMethodParseResults = setMethodParseResults;
      }
  
      public Method getSetMethod() {
          if (setMethodParseResults == null){
              return null;
          }
          return setMethodParseResults.getMethod();
      }
      
      public void setAddMethodParseResults(
                  AccessorMethodParseResults addMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.addMethodParseResults,
              addMethodParseResults);
          this.addMethodParseResults = addMethodParseResults;
      }
  
      public Method getAddMethod() {
          if (addMethodParseResults == null){
              return null;
          }
          return addMethodParseResults.getMethod();
      }
      
      public void setAddIndexedMethodParseResults(
                  AccessorMethodParseResults addIndexedMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.addIndexedMethodParseResults,
              addIndexedMethodParseResults);
          this.addIndexedMethodParseResults = addIndexedMethodParseResults;
      }
      
      public Method getAddIndexedMethod() {
          if (addIndexedMethodParseResults == null){
              return null;
          }
          return addIndexedMethodParseResults.getMethod();
      }
          
      public void setRemoveMethodParseResults(
                  AccessorMethodParseResults removeMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.removeMethodParseResults,
              removeMethodParseResults);
          this.removeMethodParseResults = removeMethodParseResults;
      }
      
      public Method getRemoveMethod() {
          if (removeMethodParseResults == null){
              return null;
          }
          return removeMethodParseResults.getMethod();
      }
      
  
      public void setSizeMethodParseResults(
                  AccessorMethodParseResults sizeMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.sizeMethodParseResults,
              sizeMethodParseResults);
          this.sizeMethodParseResults = sizeMethodParseResults;
      }
      
      public Method getSizeMethod() {
          if (sizeMethodParseResults == null){
              return null;
          }
          return sizeMethodParseResults.getMethod();
      }
      
      /**
       * Combines parse results from another instance of 
       * <code>ReflectedMappedPropertyParseResults</code> with
       * results contained by this object.
       * <p>
       * Node that the property name is not copied from the 
       * <code>other</code> object.
       */        
      public void merge(ReflectedListPropertyParseResults other){
          super.merge(other);
          if (other.readMethodParseResults != null){
              setReadMethodParseResults(other.readMethodParseResults);
          }
          if (other.writeMethodParseResults != null){
              setWriteMethodParseResults(other.writeMethodParseResults);
          }
          if (other.getMethodParseResults != null){
              setGetMethodParseResults(other.getMethodParseResults);
          }
          if (other.setMethodParseResults != null){
              setSetMethodParseResults(other.setMethodParseResults);
          }
          if (other.addMethodParseResults != null){
              setAddMethodParseResults(other.addMethodParseResults);
          }
          if (other.addIndexedMethodParseResults != null){
              setAddIndexedMethodParseResults(other.addIndexedMethodParseResults);
          }
          if (other.removeMethodParseResults != null){
              setRemoveMethodParseResults(other.removeMethodParseResults);
          }
          if (other.sizeMethodParseResults != null){
              setSizeMethodParseResults(other.sizeMethodParseResults);
          }
      }
      
      protected void appendDescription(StringBuffer buffer){
          super.appendDescription(buffer);
          Class contentType = getContentType();
          if (contentType != null){
              buffer.append("\n  [content type]   ");
              buffer.append(contentType.getName());
          }
      }
      
      protected void appendMethodDescriptions(StringBuffer buffer){
          super.appendMethodDescriptions(buffer);
          if (getMethodParseResults != null){
              buffer.append("\n    [get~(int)]    ");
              buffer.append(getMethodParseResults.getMethod());
          }
          if (setMethodParseResults != null){
              buffer.append("\n    [set~(int,v)]  ");
              buffer.append(setMethodParseResults.getMethod());
          }
          if (addMethodParseResults != null){
              buffer.append("\n    [add~(v)]      ");
              buffer.append(addMethodParseResults.getMethod());
          }
          if (addIndexedMethodParseResults != null){
              buffer.append("\n    [add~(int,v)]  ");
              buffer.append(addIndexedMethodParseResults.getMethod());
          }
          if (removeMethodParseResults != null){
              buffer.append("\n    [remove~(v)]   ");
              buffer.append(removeMethodParseResults.getMethod());
          }
          if (sizeMethodParseResults != null){
              buffer.append("\n    [get~Count()]  ");
              buffer.append(sizeMethodParseResults.getMethod());
          }
      }
      
      public boolean checkConsistency(){        
          if (!super.checkConsistency()){
              return false;
          }
                  
          if (readMethodParseResults == null && getMethodParseResults == null){
              return false;
          }
  
          if (readMethodParseResults != null){
              Class type = readMethodParseResults.getType();
              if (writeMethodParseResults != null){
                  if (!type.equals(writeMethodParseResults.getType())){
                      return false;
                  }
              }
          }
                  
          Class contentType = null;
           
          if (getMethodParseResults != null){
              contentType = getMethodParseResults.getType();
          }
          
          if (setMethodParseResults != null){
              if (contentType == null){
                  contentType = setMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(setMethodParseResults.getType())) {
                      return false;
                  }
              }
          }
          
          if (addMethodParseResults != null){
              if (contentType == null){
                  contentType = addMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(addMethodParseResults.getType())) {
                      return false;
                  }
              }
          }
          
          if (addIndexedMethodParseResults != null){
              if (contentType == null){
                  contentType = addIndexedMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(
                          addIndexedMethodParseResults.getType())){
                      return false;
                  }
              }
          }
          
          if (removeMethodParseResults != null) {
              if (contentType != null){
                  if (!contentType.equals(removeMethodParseResults.getType())){
                      return false;
                  }
              }
          }
          
          return true;
      }
          
      protected boolean appendInconsistencyDescriptions(StringBuffer buffer){
          if (!super.appendInconsistencyDescriptions(buffer)){
              return false;
          }        
          
          if (readMethodParseResults == null && getMethodParseResults == null){
              buffer.append(
                  "\n     - Does not have either get() or get(int) method");
              return true;
          }
  
          if (readMethodParseResults != null){
              Class type = readMethodParseResults.getType();
              if (writeMethodParseResults != null){
                  if (!type.equals(writeMethodParseResults.getType())){
                      buffer.append(
                          "\n     - Get() and set(v) types do not match");
                  }
              }
          }
          
          Class contentType = null;
           
          if (getMethodParseResults != null){
              contentType = getMethodParseResults.getType();
          }
          
          if (setMethodParseResults != null){
              if (contentType == null){
                  contentType = setMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(setMethodParseResults.getType())) {
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(int) and set(int,v)");
                  }
              }
          }
          
          if (addMethodParseResults != null){
              if (contentType == null){
                  contentType = addMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(addMethodParseResults.getType())) {
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(int) and add(v)");
                  }
              }
          }
          
          if (addIndexedMethodParseResults != null){
              if (contentType == null){
                  contentType = addIndexedMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(
                          addIndexedMethodParseResults.getType())){
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(int) and add(int,v)");
                  }
              }
          }
          
          if (removeMethodParseResults != null) {
              if (contentType != null){
                  Class removeType = removeMethodParseResults.getType(); 
                  if (removeType != null && !contentType.equals(removeType)){
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(int) and remove(v)");
                  }
              }
          }        
          return true;
      }  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedMap.java
  
  Index: ReflectedMap.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.Set;
  
  import org.apache.commons.clazz.ClazzException;
  
  /**
   * This is an implementation of the <code>Map</code> interface
   * that is based on a Mapped property.  Whenever possible, it
   * uses concrete methods on the owner of the property to manipulate the map.
   * <p>
   * Consider the following example:
   * <pre>
   *      Map map = (Map)clazz.getProperty("fooMap").get(instance);
   *      Object value = map.get("bar");
   * </pre>
   * 
   * If <code>instance</code> has a <code>getFoo(String key)</code> method,
   * this code will implicitly invoke it like this: <code>getFoo("bar")</code>.
   * otherwise it will obtain the whole map and extract the 
   * requested value.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedMap.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedMap implements Map 
  {
      private Object instance;
      private ReflectedMappedProperty property;
      
      /**
       * Constructor for ReflectedMap.
       */
      public ReflectedMap(
              Object instance,
              ReflectedMappedProperty property) 
      {
          this.instance = instance;
          this.property = property;
      }
  
      /**
       * If there is a removeFoo(key) method, calls that for every key.
       * Otherwise, calls getFooMap().clear()
       * 
       * @see java.util.Map#clear()
       */
      public void clear() {
      }
  
      /**
       * @see java.util.Map#containsKey(java.lang.Object)
       */
      public boolean containsKey(Object key) {
          return false;
      }
  
      /**
       * @see java.util.Map#containsValue(java.lang.Object)
       */
      public boolean containsValue(Object value) {
          return false;
      }
  
      /**
       * @see java.util.Map#entrySet()
       */
      public Set entrySet() {
          return null;
      }
  
      /**
       * If there is a getFoo(key) method, calls that for every key.
       * Otherwise, calls getFooMap().get(key)
       * 
       * @see java.util.Map#get(java.lang.Object)
       */
      public Object get(Object key) {
          Method getMethod = property.getGetMethod();
          if (getMethod != null){
              Object value;
              try {
                  value = getMethod.invoke(instance, new Object[]{key});
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot get property : "
                          + property.getName()
                          + ": cannot invoke method: "
                          + getMethod.getName(),
                      ex);
              }
              return value;
          }
          else {
              Map map = property.getMap(instance);
              if (map == null){
                  return null;
              }
              return map.get(key);
          }
      }
  
      /**
       * @see java.util.Map#isEmpty()
       */
      public boolean isEmpty() {
          return false;
      }
  
      /**
       * @see java.util.Map#keySet()
       */
      public Set keySet() {
          Method keySetMethod = property.getKeySetMethod();
          if (keySetMethod != null){
              Set set;
              try {
                  Object value = keySetMethod.invoke(instance, null);
                  if (value == null){
                      set = Collections.EMPTY_SET;
                  }
                  else if (value instanceof Set){
                      set = (Set)value;
                  }
                  else if (value instanceof Collection){
                      set = new HashSet((Collection)value);
                  }
                  else {
                      set = new HashSet(Arrays.asList((Object[])value));
                  }
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot get key set: "
                          + property.getName()
                          + ": cannot invoke method: "
                          + keySetMethod.getName(),
                      ex);
              }
              return set;
          }
          else {
              Map map = property.getMap(instance);
              if (map == null){
                  return Collections.EMPTY_SET;
              }
              return map.keySet();
          }
      }
  
      /**
       * @see java.util.Map#put(java.lang.Object, java.lang.Object)
       */
      public Object put(Object key, Object value) {        
          Method putMethod = property.getPutMethod();
          if (putMethod != null){
              Object oldValue = null;
              try {
                  oldValue = get(key);
              }
              catch (Throwable t){
                  // Ignore
              }
              
              try {
                  putMethod.invoke(instance, new Object[]{key, value});
              }
              catch (Exception ex) {
                  throw new ClazzException(
                      "Cannot set property : "
                          + property.getName()
                          + ": cannot invoke method: "
                          + putMethod.getName(),
                      ex);
              }
              return oldValue;
          }
          else {
              Map map = property.getMap(instance);
              if (map == null){
                  map = new HashMap();
                  
                  Method writeMethod = property.getWriteMethod();
                  if (writeMethod != null){
                      try {
                          writeMethod.invoke(instance, new Object[]{map});
                      }
                      catch (Exception ex) {
                          throw new ClazzException(
                              "Cannot set property : "
                                  + property.getName()
                                  + ": cannot invoke method: "
                                  + writeMethod.getName(),
                              ex);
                      }        
                  }
                  else {
                      throw new ClazzException(
                          "Cannot set property : "
                              + property.getName()
                              + ": no write method");
                  }
              }
              return map.put(key, value);
          }
      }
  
      /**
       * @see java.util.Map#putAll(java.util.Map)
       */
      public void putAll(Map t) {
      }
  
      /**
       * @see java.util.Map#remove(java.lang.Object)
       */
      public Object remove(Object key) {
          return null;
      }
  
      /**
       * @see java.util.Map#size()
       */
      public int size() {
          return 0;
      }
  
      /**
       * @see java.util.Map#values()
       */
      public Collection values() {
          return null;
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedMappedProperty.java
  
  Index: ReflectedMappedProperty.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedMappedProperty.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedMappedProperty extends ReflectedProperty {
  
      private Class keyType;
      private Class contentType;
      private Method sizeMethod;
      private Method getMethod;
      private Method putMethod;
      private Method removeMethod;
      private Method keySetMethod;
      
      /**
       * Constructor for ReflectedMappedProperty.
       * @param declaringClazz
       * @param name
       */
      public ReflectedMappedProperty(Clazz declaringClazz, String name) {
          super(declaringClazz, name);
      }
  
      /**
       * Returns the keyType.
       * @return Class
       */
      public Class getKeyType() {
          return keyType;
      }
  
      /**
       * Sets the keyType.
       * @param keyType The keyType to set
       */
      public void setKeyType(Class keyType) {
          this.keyType = keyType;
      }
  
      /**
       * Returns the contentType.
       * @return Class
       */
      public Class getContentType() {
          return contentType;
      }
  
      /**
       * Sets the contentType.
       * @param contentType The contentType to set
       */
      public void setContentType(Class valueType) {
          this.contentType = valueType;
      }
      
      /**
       * Returns the getMethod.
       * @return Method
       */
      public Method getGetMethod() {
          return getMethod;
      }
  
      /**
       * Sets the getMethod.
       * @param getMethod The getMethod to set
       */
      public void setGetMethod(Method getMethod) {
          this.getMethod = getMethod;
      }
      
      /**
       * Returns the putMethod.
       * @return Method
       */
      public Method getPutMethod() {
          return putMethod;
      }
  
      /**
       * Sets the putMethod.
       * @param putMethod The putMethod to set
       */
      public void setPutMethod(Method putMethod) {
          this.putMethod = putMethod;
      }
  
      /**
       * Returns the removeMethod.
       * @return Method
       */
      public Method getRemoveMethod() {
          return removeMethod;
      }
  
      /**
       * Sets the removeMethod.
       * @param removeMethod The removeMethod to set
       */
      public void setRemoveMethod(Method removeMethod) {
          this.removeMethod = removeMethod;
      }
  
      /**
       * Returns the keySetMethod.
       * @return Method
       */
      public Method getKeySetMethod() {
          return keySetMethod;
      }
  
      /**
       * Sets the keySetMethod.
       * @param keySetMethod The keySetMethod to set
       */
      public void setKeySetMethod(Method keySetMethod) {
          this.keySetMethod = keySetMethod;
      }
  
      public String toString(){
          StringBuffer buffer = new StringBuffer("[ReflectedMappedProperty ");
          if (getType() != null){
              buffer.append(getType().getName());
              buffer.append(" ");
          }
          if (getKeyType() != null){
              buffer.append("[key: ");
              buffer.append(getKeyType().getName());
              buffer.append("] ");
          }
          if (getContentType() != null){
              buffer.append("[content: ");
              buffer.append(getContentType().getName());
              buffer.append("] ");
          }
          buffer.append(getName());
          if (getReadMethod() != null){
              buffer.append("\n   [read method]   ");
              buffer.append(getReadMethod());            
          }
          if (getWriteMethod() != null){
              buffer.append("\n   [write method]  ");
              buffer.append(getWriteMethod());            
          }
          if (getGetMethod() != null){
              buffer.append("\n   [get method]    ");
              buffer.append(getGetMethod());            
          }
          if (getPutMethod() != null){
              buffer.append("\n   [put method]    ");
              buffer.append(getPutMethod());            
          }
          if (getRemoveMethod() != null){
              buffer.append("\n   [remove method] ");
              buffer.append(getRemoveMethod());            
          }
          if (getKeySetMethod() != null){
              buffer.append("\n   [keySet method] ");
              buffer.append(getKeySetMethod());            
          }
          buffer.append("]");
          return buffer.toString();
      }
      /**
       * @see org.apache.commons.clazz.ClazzProperty#get(java.lang.Object)
       */
      public Object get(Object instance) {
          return new ReflectedMap(instance, this);
      }
      
      public Map getMap(Object instance) {
          if (getReadMethod() == null){
              return null;
          }
          
          return (Map)super.get(instance);
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#set(java.lang.Object, java.lang.Object)
       */
      public void set(Object instance, Object value) {
          super.set(instance, value);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedMappedPropertyIntrospector.java
  
  Index: ReflectedMappedPropertyIntrospector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * A ReflectedPropertyIntrospector that discovers mapped properties.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedMappedPropertyIntrospector.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedMappedPropertyIntrospector
      extends ReflectedPropertyIntrospectorSupport 
  {
  
      /**
       * The global instance of ReflectedMappedPropertyIntrospector that
       * should be used by ReflectedClass to create mapped properties.
     */
      public static final ReflectedMappedPropertyIntrospector INTROSPECTOR =
              new ReflectedMappedPropertyIntrospector();
   
      /**
       * Singleton - not supposed to be allocated by clients. Use
       * the <code>INTROSPECTOR</code> static field instead.
       */
      protected ReflectedMappedPropertyIntrospector(){
      }
      
      /**
       * Goes over methods of the supplied class and creates 
       * ReflectedProperty objects for discovered properties.
     */
      public void introspectProperties(
              ReflectedClazz clazz,
              Class javaClass,
              Map parseResultMap)
      {
          HashMap parseResultMapSingular = new HashMap();
          Method methods[] = javaClass.getMethods();
          ReflectedMappedPropertyParseResults parseResults;
          AccessorMethodParseResults results;
          for (int i = 0; i < methods.length; i++) {
              Method method = methods[i];
              
              // Check getFooKeys() before we check getFooList(),
              // because the parser for the latter is generic enough
              // to include the former            
              results = parseKeySetMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setKeySetMethodParseResults(results);
                  continue;
              }
              
              results = parseReadMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setReadMethodParseResults(results);
                  continue;
              }
  
              results = parseWriteMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setWriteMethodParseResults(results);
                  continue;
              }
  
              results = parseGetMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setGetMethodParseResults(results);
                  continue;
              }
              
              results = parsePutMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setPutMethodParseResults(results);
                  continue;
              }
              
              results = parseRemoveMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMapSingular,
                          results.getPropertyName());
                  parseResults.setRemoveMethodParseResults(results);
                  continue;
              }
          }
          
          Iterator iter = parseResultMap.entrySet().iterator();
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              ReflectedMappedPropertyParseResults result = 
                  (ReflectedMappedPropertyParseResults) entry.getValue();
              if (!result.isMap()){
                  iter.remove();
              }
          }
          
          mergeSingularMethods(parseResultMap, parseResultMapSingular);
      }
  
      /**
       * Parser for the <code>getFooMap()</code> method:
       * <ul>
       *  <li>Return type not void</li>
       *  <li>Name starts with "get" followed by capitalized property name</li>
       *  <li>No parameters</li>
       * </ul>
       * 
       * We don't check if the parameter is a Map here. If it is not,
       * we want to recognize the method and them mark the corresponding
       * property as NotAProperty.
       */
      protected static AccessorMethodParser READ_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class returnType){
              return !returnType.equals(Void.TYPE);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 0;
          }
  
          protected Class getValueType(Method method){
              return method.getReturnType();
          }
          
      };
              
      /**
       * Looks at the method to see if it has the signature
       * of a property read method, like "Map getIntegerMap()", parses it
       * and returns the results of parsing.  If the method signature 
       * does not fit the criteria, returns <code>null</code>.
       */
      protected AccessorMethodParseResults parseReadMethod(Method method) {
          return READ_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>setFooMap(Map)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "set" followed by capitalized property name</li>
       *  <li>One parameter</li>
       * </ul>
       * 
       * We don't check if the parameter is a Map here. If it is not,
       * we want to recognize the method and them mark the corresponding
       * property as NotAProperty.
       */            
      protected static AccessorMethodParser WRITE_METHOD_PARSER =
              new AccessorMethodParser()
      {
          protected boolean testReturnType(Class returnType){
              return returnType.equals(Void.TYPE);
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected String requiredPrefix(){
              return "set";
          }
                  
          protected Class getValueType(Method method){
              return method.getParameterTypes()[0];
          }
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseWriteMethod(Method method) {
          return WRITE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>getFoo(key)</code> method:
       * <ul>
       *  <li>Return type not void</li>
       *  <li>Name starts with "get" followed by capitalized singular
       *      form of the property name</li>
       *  <li>One parameter</li>
       * </ul>
       */            
      protected static AccessorMethodParser GET_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class returnType){
              return !returnType.equals(Void.TYPE);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected Class getValueType(Method method){
              return method.getReturnType();
          }
          
          protected Class getParameterType(Method method){
              return method.getParameterTypes()[0];
          }
          
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseGetMethod(Method method) {
          return GET_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>setFoo(key, value)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "set" followed by capitalized singular
       *      form of the property name</li>
       *  <li>Two parameters</li>
       * </ul>
       */                        
      protected static AccessorMethodParser PUT_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "set";
          }
          
          protected int requiredParameterCount(){
              return 2;
          }
  
          protected Class getValueType(Method method){
              return method.getParameterTypes()[1];
          }
          
          protected Class getParameterType(Method method){
              return method.getParameterTypes()[0];
          }
          
      };
      
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parsePutMethod(Method method) {
          return PUT_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>removeFoo(key)</code> method:
       * <ul>
       *  <li>Name starts with "remove" followed by capitalized singular
       *      form of the property name</li>
       *  <li>One parameter</li>
       * </ul>
       */                        
      protected static AccessorMethodParser REMOVE_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected String requiredPrefix(){
              return "remove";
          }
          
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected Class getValueType(Method method){
              Class returnType = method.getReturnType();
              if (Void.TYPE.equals(returnType)){
                  return null;
              }
              return returnType;
          }
          
          protected Class getParameterType(Method method){
              return method.getParameterTypes()[0];
          }
          
      };
                          
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseRemoveMethod(Method method) {
          return REMOVE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>getFooKeys()</code> method:
       * <ul>
       *  <li>Returns integer</li>
       *  <li>Name starts with "get" followed by capitalized singular
       *      form of the property name, followed by "Keys" or "KeySet"</li>
       *  <li>No parameters</li>
       * </ul>
       */                        
      protected static AccessorMethodParser KEY_SET_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class javaClass){
              return javaClass.isArray() ||
                  Collection.class.isAssignableFrom(javaClass);
          }
          
          protected String requiredPrefix(){
              return "get";
          }
          
          protected int requiredParameterCount(){
              return 0;
          }
          
          protected String testAndRemoveSuffix(String methodName){
              if (methodName.endsWith("Keys")){                
                  return methodName.substring(0, methodName.length() - 4);
              }
              if (methodName.endsWith("KeySet")){
                  return methodName.substring(0, methodName.length() - 6);
              }
              return null;
          }
      };
                          
      /**
       * @see #parseReadMethod
       */
      public AccessorMethodParseResults parseKeySetMethod(Method method) {
          return KEY_SET_METHOD_PARSER.parse(method);
      }
  
      /**
       * Combines data collected from singular methods like 
       * <code>getFoo(key)</code> with parse results for plural methods 
       * like <code>getFooMap()</code>. 
     */    
      protected void mergeSingularMethods(
              Map parseResultMapPlural, Map parseResultMapSingular)
      {
          Iterator iter = parseResultMapSingular.values().iterator();
          while (iter.hasNext()) {
              
              ReflectedMappedPropertyParseResults singular =
                  (ReflectedMappedPropertyParseResults) iter.next();
                  
              ReflectedMappedPropertyParseResults plural =
                  findBySingularName(
                          parseResultMapPlural, singular.getPropertyName());
              
              if (plural != null) {
                  plural.merge(singular);
              }
              else {
                  // We don't have any plural methods - let's just use
                  // the singular ones then
                  parseResultMapPlural.put(singular.getPropertyName(), singular);
              }
          }
      }
  
      /**
       * Given a singular form of a property name, locates parse results
       * for a property with the corresponding plural name.
     */
      protected ReflectedMappedPropertyParseResults findBySingularName(
              Map parseResultMapPlural,
              String singularName) 
      {
          ReflectedMappedPropertyParseResults plural =
              (ReflectedMappedPropertyParseResults) 
                  parseResultMapPlural.get(singularName);
          if (plural != null) {
              return plural;
          }
  
          Iterator iter = parseResultMapPlural.entrySet().iterator();
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              if (isCorrectPluralForm(singularName, (String) entry.getKey())) {
                  return (ReflectedMappedPropertyParseResults) entry.getValue();
              }
          }
          return null;
      }
  
      /**
       * Returns <code>true</code> if the suffix is "s" or "Map".
       *  
       * @see org.apache.commons.clazz.reflect.ReflectedPropertyFactorySupport#isCorrectPluralSuffix(String, String)
       */
      protected boolean isCorrectPluralSuffix(String singular, String suffix){
          return super.isCorrectPluralSuffix(singular, suffix) || 
                  suffix.equals("Map");
      }
      
       
      /**
       * Finds a ReflectedMappedPropertyParseResults for the given
       * propertyName or creates a new one and puts it in the map.
       */
      protected ReflectedMappedPropertyParseResults getParseResults(
              ReflectedClazz clazz,
              Map parseResultMap,
              String propertyName) 
      {
          ReflectedMappedPropertyParseResults parseResults =
              (ReflectedMappedPropertyParseResults) parseResultMap.get(
                  propertyName);
          if (parseResults == null) {
              parseResults =
                  new ReflectedMappedPropertyParseResults(clazz, propertyName);
              parseResultMap.put(propertyName, parseResults);
          }
          return parseResults;
      }
      
      /**
       * Creates a new ReflectedMappedProperty based on parse results. 
       */
      protected ReflectedProperty createProperty(
          ReflectedClazz clazz,
          ReflectedPropertyParseResults parseResults)
      {
          ReflectedMappedProperty property =
              new ReflectedMappedProperty(clazz, parseResults.getPropertyName());
  
          ReflectedMappedPropertyParseResults parseResultsMapped =
                  (ReflectedMappedPropertyParseResults)parseResults;
  
          property.setAliases(parseResultsMapped.getAliases());                 
          property.setType(parseResultsMapped.getPropertyType());
          property.setKeyType(parseResultsMapped.getKeyType());
          property.setContentType(parseResultsMapped.getContentType());
          property.setReadMethod(parseResultsMapped.getReadMethod());
          property.setWriteMethod(parseResultsMapped.getWriteMethod());
          property.setGetMethod(parseResultsMapped.getGetMethod());
          property.setPutMethod(parseResultsMapped.getPutMethod());
          property.setRemoveMethod(parseResultsMapped.getRemoveMethod());
          property.setKeySetMethod(parseResultsMapped.getKeySetMethod());
          return property;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedMappedPropertyParseResults.java
  
  Index: ReflectedMappedPropertyParseResults.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.Map;
  
  /**
   * Holds parse results for individual accessor methods for a 
   * mapped property.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedMappedPropertyParseResults.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedMappedPropertyParseResults 
              extends ReflectedPropertyParseResults
  {
      private AccessorMethodParseResults getMethodParseResults;
      private AccessorMethodParseResults putMethodParseResults;
      private AccessorMethodParseResults removeMethodParseResults;
      private AccessorMethodParseResults keySetMethodParseResults;
  
      /**
       * Constructor for ReflectedMappedPropertyParseResults.
       */
      public ReflectedMappedPropertyParseResults(
              ReflectedClazz clazz, String propertyName) 
      {
          super(clazz, propertyName);
      }
      
      protected String getPropertyCategory(){
          return "mapped";
      }
  
      /**
       * Returns <code>true</code> if the property is 
       * java.util.Map or implements java.util.Map.
       */
      protected boolean isMap(){
          if (readMethodParseResults != null &&
                  isMap(readMethodParseResults.getType())){
              return true;
          }
          if (writeMethodParseResults != null &&
                  isMap(writeMethodParseResults.getType())){
              return true;
          }
          return false;        
      }
          
      private boolean isMap(Class javaClass){
          return javaClass != null && Map.class.isAssignableFrom(javaClass);
      }
      
      public Class getKeyType(){
          if (getMethodParseResults != null){
              return getMethodParseResults.getParameterType();
          }
          if (putMethodParseResults != null){
              return putMethodParseResults.getParameterType();
          }
          if (removeMethodParseResults != null){
              return removeMethodParseResults.getParameterType();
          }
          return null;        
      }
  
      public Class getContentType(){
          if (getMethodParseResults != null){
              return getMethodParseResults.getType();
          }
          if (putMethodParseResults != null){
              return putMethodParseResults.getType();
          }
          if (removeMethodParseResults != null){
              return removeMethodParseResults.getType();
          }
          return null;
          
      }
  
      public void setGetMethodParseResults(
                  AccessorMethodParseResults getMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.getMethodParseResults,
              getMethodParseResults);
          this.getMethodParseResults = getMethodParseResults;
      }
  
      public Method getGetMethod() {
          if (getMethodParseResults == null){
              return null;
          }
          return getMethodParseResults.getMethod();
      }
      
  
      public void setPutMethodParseResults(
                  AccessorMethodParseResults putMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.putMethodParseResults,
              putMethodParseResults);
          this.putMethodParseResults = putMethodParseResults;
      }
      
      public Method getPutMethod() {
          if (putMethodParseResults == null){
              return null;
          }
          return putMethodParseResults.getMethod();
      }
          
      public void setRemoveMethodParseResults(
                  AccessorMethodParseResults removeMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.removeMethodParseResults,
              removeMethodParseResults);
          this.removeMethodParseResults = removeMethodParseResults;
      }
      
      public Method getRemoveMethod() {
          if (removeMethodParseResults == null){
              return null;
          }
          return removeMethodParseResults.getMethod();
      }
      
      public void setKeySetMethodParseResults(
                  AccessorMethodParseResults keySetMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.keySetMethodParseResults,
              keySetMethodParseResults);
          this.keySetMethodParseResults = keySetMethodParseResults;
      }
      
      public Method getKeySetMethod() {
          if (keySetMethodParseResults == null){
              return null;
          }
          return keySetMethodParseResults.getMethod();
      }
      
      /**
       * Combines parse results from another instance of 
       * <code>ReflectedMappedPropertyParseResults</code> with
       * results contained by this object.
       * <p>
       * Node that the property name is not copied from the 
       * <code>other</code> object.
       */        
      public void merge(ReflectedMappedPropertyParseResults other){
          super.merge(other);
          if (other.readMethodParseResults != null){
              setReadMethodParseResults(other.readMethodParseResults);
          }
          if (other.writeMethodParseResults != null){
              setWriteMethodParseResults(other.writeMethodParseResults);
          }
          if (other.getMethodParseResults != null){
              setGetMethodParseResults(other.getMethodParseResults);
          }
          if (other.putMethodParseResults != null){
              setPutMethodParseResults(other.putMethodParseResults);
          }
          if (other.removeMethodParseResults != null){
              setRemoveMethodParseResults(other.removeMethodParseResults);
          }
          if (other.keySetMethodParseResults != null){
              setKeySetMethodParseResults(other.keySetMethodParseResults);
          }
      }
      
      protected void appendDescription(StringBuffer buffer){
          super.appendDescription(buffer);
          Class keyType = getKeyType();
          if (keyType != null){
              buffer.append("\n  [key type]       ");
              buffer.append(keyType.getName());
          }
          
          Class contentType = getContentType();
          if (contentType != null){
              buffer.append("\n  [content type]   ");
              buffer.append(contentType.getName());
          }
      }
      
      protected void appendMethodDescriptions(StringBuffer buffer){
          super.appendMethodDescriptions(buffer);
          if (getMethodParseResults != null){
              buffer.append("\n    [get~(key)]    ");
              buffer.append(getMethodParseResults.getMethod());
          }
          if (putMethodParseResults != null){
              buffer.append("\n    [set~(key,v)]  ");
              buffer.append(putMethodParseResults.getMethod());
          }
          if (removeMethodParseResults != null){
              buffer.append("\n    [remove~(key)] ");
              buffer.append(removeMethodParseResults.getMethod());
          }
          if (keySetMethodParseResults != null){
              buffer.append("\n    [get~KeySet()] ");
              buffer.append(keySetMethodParseResults.getMethod());
          }
      }
      
      public boolean checkConsistency(){        
          if (!super.checkConsistency()){
              return false;
          }
                  
          if (readMethodParseResults == null && getMethodParseResults == null){
              return false;
          }
  
          if (readMethodParseResults != null){
              Class type = readMethodParseResults.getType();
              if (writeMethodParseResults != null){
                  if (!type.equals(writeMethodParseResults.getType())){
                      return false;
                  }
              }
          }
                  
          Class keyType = null;
          Class contentType = null;
           
          if (getMethodParseResults != null){
              keyType = getMethodParseResults.getParameterType();
              contentType = getMethodParseResults.getType();
          }
          
          if (putMethodParseResults != null){
              if (keyType == null){
                  keyType = putMethodParseResults.getParameterType();
              }
              else {
                  if (!keyType.equals(putMethodParseResults.getParameterType())){
                      return false;
                  }
              }
              
              if (contentType == null){
                  contentType = putMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(
                          putMethodParseResults.getType())){
                      return false;
                  }
              }
          }
          
          if (removeMethodParseResults != null) {
              if (keyType != null
                  && !keyType.
                          equals(removeMethodParseResults.getParameterType())) {
                  return false;
              }
                          
              if (contentType != null){
                  Class removeType = removeMethodParseResults.getType(); 
                  if (removeType != null && !contentType.equals(removeType)){
                      return false;
                  }
              }
          }
          
          return true;
      }
          
      protected boolean appendInconsistencyDescriptions(StringBuffer buffer){
          if (!super.appendInconsistencyDescriptions(buffer)){
              return false;
          }        
          
          if (readMethodParseResults == null && getMethodParseResults == null){
              buffer.append(
                  "\n     - Does not have either get() or get(key) method");
              return true;
          }
  
          if (readMethodParseResults != null){
              Class type = readMethodParseResults.getType();
              if (writeMethodParseResults != null){
                  if (!type.equals(writeMethodParseResults.getType())){
                      buffer.append(
                          "\n     - Get() and set(v) types do not match");
                  }
              }
          }
          
          Class keyType = null;
          Class contentType = null;
           
          if (getMethodParseResults != null){
              keyType = getMethodParseResults.getParameterType();
              contentType = getMethodParseResults.getType();
          }
          
          if (putMethodParseResults != null){
              if (keyType == null){
                  keyType = putMethodParseResults.getParameterType();
              }
              else {
                  if (!keyType.equals(putMethodParseResults.getParameterType())){
                      buffer.append(
                          "\n     - Key type mismatch between "
                              + "get(key) and set(key,v)");
                  }
              }
              
              if (contentType == null){
                  contentType = putMethodParseResults.getType();
              }
              else {
                  if (!contentType.equals(
                          putMethodParseResults.getType())){
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(key) and set(key,v)");
                  }
              }
          }
          
          if (removeMethodParseResults != null) {
              if (keyType != null
                  && !keyType.
                          equals(removeMethodParseResults.getParameterType())) {
                  buffer.append(
                      "\n     - Key type mismatch between "
                          + "get(key) and remove(key)");
              }
                          
              if (contentType != null){
                  Class removeType = removeMethodParseResults.getType(); 
                  if (removeType != null && !contentType.equals(removeType)){
                      buffer.append(
                          "\n     - Content type mismatch between "
                              + "get(key) and set(key,v)");
                  }
              }
          }        
          return true;
      }  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedProperty.java
  
  Index: ReflectedProperty.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzException;
  import org.apache.commons.clazz.ClazzProperty;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedProperty.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedProperty extends ReflectedFeature implements ClazzProperty 
  {
      private String name;
      private static final String[] EMPTY_STRING_ARRAY = new String[0];
      private String[] aliases = EMPTY_STRING_ARRAY;
      private Class type;
      private Clazz clazz;
      private Field field;
      private Method readMethod;
      private Method writeMethod;
      
      /**
       * Constructor for ReflectedClazzProperty.
       */
      public ReflectedProperty(Clazz declaringClazz, String name) {
          super(declaringClazz);
          this.name = name;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#getName()
       */
      public String getName() {
          return name;
      }
      
      /**
       * Returns the aliases.
       * @return String[]
       */
      public String[] getAliases() {
          return aliases;
      }
  
      /**
       * Sets the aliases.
       * @param aliases The aliases to set
       */
      public void setAliases(String[] aliases) {
          this.aliases = aliases;
      }
      
      /**
       * @see org.apache.commons.clazz.ClazzProperty#getClazz()
       */
      public Clazz getClazz() {
          if (clazz == null){
              clazz = getDeclaringClazz().
                  getClazzLibrary().getClazzForName(type.getName());
          }
          return clazz;
      }
      
      /**
       * @see org.apache.commons.clazz.ClazzProperty#getContentClazz()
       */
      public Clazz getContentClazz() {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#getKeyClazz()
       */
      public Clazz getKeyClazz() {
          return null;
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#isReadOnly()
       */
      public boolean isReadOnly() {
          return false;
      }
  
      /**
       * Returns the field.
       * @return Field
       */
      public Field getField() {
          return field;
      }
  
      /**
       * Returns the readMethod.
       * @return Method
       */
      public Method getReadMethod() {
          return readMethod;
      }
  
  
      /**
       * Sets the field.
       * @param field The field to set
       */
      public void setField(Field field) {
          this.field = field;
      }
  
      /**
       * Sets the readMethod.
       * @param readMethod The readMethod to set
       */
      public void setReadMethod(Method readMethod) {
          this.readMethod = readMethod;
      }
      
      /**
       * Returns the writeMethod.
       * @return Method
       */
      public Method getWriteMethod() {
          return writeMethod;
      }
      
      /**
       * Sets the writeMethod.
       * @param writeMethod The writeMethod to set
       */
      public void setWriteMethod(Method writeMethod) {
          this.writeMethod = writeMethod;
      }
      
      /**
       * @see org.apache.commons.clazz.ClazzProperty#get(java.lang.Object)
       */
      public Object get(Object instance) {
          if (readMethod == null){
              throw new ClazzException(
                  "Cannot read property " + name + ": no read method");
          }
          try {
              return readMethod.invoke(instance, null);
          }
          catch (Exception ex) {
              throw new ClazzException(
                  "Cannot get property : "
                      + name
                      + ": cannot invoke method: "
                      + readMethod.getName(),
                  ex);
          }
      }
  
      /**
       * @see org.apache.commons.clazz.ClazzProperty#set(java.lang.Object, java.lang.Object)
       */
      public void set(Object instance, Object value) {
          if (writeMethod == null){
              throw new ClazzException(
                  "Cannot modify property " + name + ": no write method");
          }
          try {
              writeMethod.invoke(instance, new Object[]{value});
          }
          catch (Exception ex) {
              throw new ClazzException(
                  "Cannot set property : "
                      + name
                      + ": cannot invoke method: "
                      + writeMethod.getName(),
                  ex);
          }
      }
  
  
      /**
       * Returns the valueClass.
       * @return Class
       */
      public Class getType() {
          return type;
      }
  
      /**
       * Sets the type.
       * @param type The type to set
       */
      public void setType(Class type) {
          this.type = type;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedPropertyIntrospector.java
  
  Index: ReflectedPropertyIntrospector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.util.List;
  
  /**
   * Performs introspection for one kind of property - scalar, indexed, mapped,
   * etc.  In the process of introspection ReflectedClazz invokes 
   * ReflectedPropertyFactories one after another, discovering properties
   * of one kind at a time.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedPropertyIntrospector.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public interface ReflectedPropertyIntrospector {
  
      /**
       * Find methods and fields constituting properties of the
       * corresponding kind.  Create ClazzProperty objects and 
       * return them as a list.  The clazz may already 
       * have been populated with properties created by other factories.
       */
      public List introspectProperties(ReflectedClazz clazz, Class javaClass);
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedPropertyIntrospectorSupport.java
  
  Index: ReflectedPropertyIntrospectorSupport.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedPropertyIntrospectorSupport.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public abstract class ReflectedPropertyIntrospectorSupport
      implements ReflectedPropertyIntrospector 
  {
      /**
       */
      public List introspectProperties(ReflectedClazz clazz, Class javaClass) {        
          HashMap parseResultMap = new HashMap();
          introspectProperties(clazz, javaClass, parseResultMap);
          
          boolean loggingEnabled = clazz.isLoggingEnabled();
          
          ArrayList list = new ArrayList();
          Iterator iter = parseResultMap.values().iterator();
          while (iter.hasNext()) {
              ReflectedPropertyParseResults parseResults = 
                      (ReflectedPropertyParseResults) iter.next();
              if (clazz.getProperty(parseResults.getPropertyName()) != null){
                  continue;
              }
              
              boolean aliasExists = false;
              String aliases[] = parseResults.getAliases();
              for (int i = 0; i < aliases.length; i++){
                  if (clazz.getProperty(aliases[i]) != null){
                      aliasExists = true;
                      break;
                  }
              }
              if (aliasExists){
                  continue;
              }
  
              boolean consistent = parseResults.checkConsistency();
              if (consistent){                
                  list.add(createProperty(clazz, parseResults));
              }
              if (loggingEnabled){
                  clazz.logPropertyParseResults(parseResults);
              }
          }
          return list;
      }
      
      public abstract void introspectProperties(
          ReflectedClazz clazz,
          Class javaClass,
          Map parseResultMap);
              
      /**
       * Creates a new ReflectedProperty based on parse results. 
       */
      protected abstract ReflectedProperty createProperty(
          ReflectedClazz clazz,
          ReflectedPropertyParseResults parseResults);
      
      
      /**
       * Returns true if the <code>plural</code> parameter is
       * a correct plural form for the property names <code>singular</code>.
       * If the plural.startsWith(singular), calls isCorrectPluralSuffix
       * with the singular form and the remaining part of the plural form.
       * Separately handles the "~y" - "~ies" substitution for English.
       */
      protected boolean isCorrectPluralForm(String singular, String plural){
          if (plural.startsWith(singular)){            
              return isCorrectPluralSuffix(
                      singular,
                      plural.substring(singular.length()));
          }
          else if (singular.endsWith("y") &&
                  plural.endsWith("ies") && 
                  plural.substring(0, plural.length() - 3).
                          equals(singular.substring(singular.length() - 1))){
              return true;
          }
          return false;
      }
      
      protected boolean isCorrectPluralSuffix(String singular, String suffix){
          return suffix.equals("s");
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedPropertyParseResults.java
  
  Index: ReflectedPropertyParseResults.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Base class for <code>Reflected*PropertyParseResults</code> classes;
   * aggregates parse results for individual accessor methods.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedPropertyParseResults.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public abstract class ReflectedPropertyParseResults {
      private ReflectedClazz clazz;
      private String propertyName;
      private List aliases;
      
      protected AccessorMethodParseResults readMethodParseResults;
      protected AccessorMethodParseResults writeMethodParseResults;
      protected List extraneousAccessors;
      
      private static final String[] EMPTY_STRING_ARRAY = new String[0];
      
      public ReflectedPropertyParseResults(
              ReflectedClazz clazz,
              String propertyName) 
      {
          this.clazz = clazz;
          this.propertyName = propertyName;
      }
      
      public ReflectedClazz getClazz(){
          return clazz;
      }
      
      /**
       * Returns the propertyName.
       * @return String
       */
      public String getPropertyName() {
          return propertyName;
      }
      
      public String[] getAliases(){
          if (aliases == null){
              return EMPTY_STRING_ARRAY;
          }
          return (String[])aliases.toArray(EMPTY_STRING_ARRAY);
      }
      
      public void addAlias(String alias){
          if (!alias.equals(propertyName)){
              if (aliases == null){
                  aliases = new ArrayList();
                  aliases.add(alias);
              }
              else if (!aliases.contains(alias)){
                  aliases.add(alias);
              }
          }
      }
      
      protected abstract String getPropertyCategory();
      
      public void merge(ReflectedPropertyParseResults other){
          addAlias(other.getPropertyName());
          String[] aliases = other.getAliases();
          for (int i = 0; i < aliases.length; i++) {
              addAlias(aliases[i]);
          }
      }    
      
      public Class getPropertyType(){
          if (readMethodParseResults != null){
              return readMethodParseResults.getType();
          }
          if (writeMethodParseResults != null){
              return writeMethodParseResults.getType();
          }
          return null;
      }
          
      public Method getReadMethod() {
          if (readMethodParseResults == null){
              return null;
          }
          return readMethodParseResults.getMethod();
      }
      
      public Method getWriteMethod() {
          if (writeMethodParseResults == null){
              return null;
          }
          return writeMethodParseResults.getMethod();
      }
      
      /**
       * Sets the readMethodParseResults.
       * @param readMethodParseResults The readMethodParseResults to set
       */
      public void setReadMethodParseResults(
                  AccessorMethodParseResults readMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.readMethodParseResults,
              readMethodParseResults);
          this.readMethodParseResults = readMethodParseResults;
      }
      
      /**
       * Sets the writeMethodParseResults.
       * @param writeMethodParseResults The writeMethodParseResults to set
       */
      public void setWriteMethodParseResults(
              AccessorMethodParseResults writeMethodParseResults) 
      {
          checkForExtraneousAccessor(
              this.writeMethodParseResults,
              writeMethodParseResults);
          this.writeMethodParseResults = writeMethodParseResults;
      }
      
      /**
       * Checks if there is an existing parse result recorded and if
       * so saves it into the extraneousAccessors for error reporting.
     */
      protected void checkForExtraneousAccessor(
              AccessorMethodParseResults currentValue, 
              AccessorMethodParseResults newValue)
      {
          if (currentValue != null && newValue != null &&
                  currentValue != newValue){
              if (extraneousAccessors == null){
                  extraneousAccessors = new ArrayList();
                  extraneousAccessors.add(currentValue);
              }
          }
      }
          
      public boolean checkConsistency(){        
          if (extraneousAccessors != null){
              return false;
          }
          
          return true;
      }
      
      public String toString(){
          boolean consistent = checkConsistency();
          
          StringBuffer buffer = new StringBuffer();
          buffer.append("[");
          if (consistent){
              buffer.append(propertyName);
              if (!getPropertyCategory().equals("scalar")){            
                  buffer.append(" (");
                  buffer.append(getPropertyCategory());
                  buffer.append(")");
              }
          }
          else {
              buffer.append("*");
              buffer.append(propertyName);            
              buffer.append(" - NOT a ");
              if (!getPropertyCategory().equals("scalar")){            
                  buffer.append(getPropertyCategory());
              }
              buffer.append(" property");
              appendInconsistencyDescriptions(buffer);
          }
          if (aliases != null){
              buffer.append("\n  [aliases: ");
              for (int i = 0; i < aliases.size(); i++){
                  if (i != 0){
                      buffer.append(", ");
                  }
                  buffer.append(aliases.get(i));
              }
              buffer.append("]");
          }
          appendDescription(buffer);
          buffer.append("\n  [accessor methods:");
          appendMethodDescriptions(buffer);
          buffer.append("\n  ]");
          buffer.append("\n]");
          return buffer.toString();
      }
      
      protected void appendDescription(StringBuffer buffer){
          Class type = getPropertyType();
          if (type != null){
              buffer.append("\n  [type]           ");
              buffer.append(type.getName());
          }
      }
      
      protected void appendMethodDescriptions(StringBuffer buffer){        
          if (readMethodParseResults != null){
              buffer.append("\n    [get~()]       ");
              buffer.append(readMethodParseResults.getMethod());
          }
          if (writeMethodParseResults != null){
              buffer.append("\n    [set~(v)]      ");
              buffer.append(writeMethodParseResults.getMethod());
          }
      }
      
      protected boolean appendInconsistencyDescriptions(StringBuffer buffer){        
          if (extraneousAccessors != null){
              buffer.append(
                  "\n     - Has extraneous accessors:");
              for (int i = 0; i < extraneousAccessors.size(); i++) {
                  AccessorMethodParseResults results =
                      (AccessorMethodParseResults)extraneousAccessors.get(i); 
                  buffer.append("\n         ");
                  buffer.append(results.getMethod());
              }
          }    
          return true;
      }    
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedScalarProperty.java
  
  Index: ReflectedScalarProperty.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  
  import org.apache.commons.clazz.Clazz;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedScalarProperty.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedScalarProperty extends ReflectedProperty {
      /**
       * Constructor for ReflectedScalarProperty.
       * @param declaringClazz
       * @param name
       */
      public ReflectedScalarProperty(Clazz declaringClazz, String name) {
          super(declaringClazz, name);
      }
          
      public String toString(){
          StringBuffer buffer = new StringBuffer("[ReflectedScalarProperty ");
          if (getType() != null){
              buffer.append(getType().getName());
              buffer.append(" ");
          }
          buffer.append(getName());
          if (getReadMethod() != null){
              buffer.append("\n   [read method]  ");
              buffer.append(getReadMethod());            
          }
          if (getWriteMethod() != null){
              buffer.append("\n   [write method] ");
              buffer.append(getWriteMethod());            
          }
          buffer.append("]");
          return buffer.toString();
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedScalarPropertyIntrospector.java
  
  Index: ReflectedScalarPropertyIntrospector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  /**
   * A ReflectedPropertyIntrospector that discovers scalar properties.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedScalarPropertyIntrospector.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedScalarPropertyIntrospector 
              extends ReflectedPropertyIntrospectorSupport 
  {
      public static final ReflectedScalarPropertyIntrospector INTROSPECTOR =
              new ReflectedScalarPropertyIntrospector();
   
      /**
       * Singleton - not supposed to be allocated by clients. Use
       * the <code>INTROSPECTOR</code> static field instead.
       */
      protected ReflectedScalarPropertyIntrospector(){
      }
      
      public void introspectProperties(
              ReflectedClazz clazz,
              Class javaClass,
              Map parseResultMap)
      {
          Method methods[] = javaClass.getMethods();
          ReflectedScalarPropertyParseResults parseResults;
          AccessorMethodParseResults results;
          for (int i = 0; i < methods.length; i++){
              Method method = methods[i];
              if (method.getDeclaringClass().equals(Object.class)){
                  continue;
              }
              
              results = parseReadMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setReadMethodParseResults(results);
                  continue;
              }
              
              results = parseWriteMethod(method);
              if (results != null){
                  parseResults =
                      getParseResults(
                          clazz,
                          parseResultMap,
                          results.getPropertyName());
                  parseResults.setWriteMethodParseResults(results);
                  continue;
              }    
          }
      }
      
      /**
       * Parser for the <code>getFoo()</code> method:
       * <ul>
       *  <li>Return type not void</li>
       *  <li>Name starts with "get" followed by capitalized property name.
       *      If the property is boolean the name may also start with "is".</li>
       *  <li>No parameters</li>
       * </ul>
       */
      protected static AccessorMethodParser READ_METHOD_PARSER = 
              new AccessorMethodParser()
      {               
          protected boolean testReturnType(Class returnType){
              return !returnType.equals(Void.TYPE);
          }
          
          protected int requiredParameterCount(){
              return 0;
          }
          
          protected String parseMethodName(Method method){
              String name = method.getName();
              String propertyName = null;
              if (name.startsWith("get")){
                  propertyName = decapitalize(name.substring(3));
              }
              else if (method.getReturnType().equals(Boolean.TYPE) && 
                          name.startsWith("is")){
                  propertyName = decapitalize(name.substring(2));
              }
              return propertyName;           
          }
  
          protected Class getValueType(Method method){
              return method.getReturnType();
          }
      };
              
      /**
       * Looks at the method to see if it has the signature
       * of a property read method, like "int getInteger()", parses it
       * and returns the results of parsing.  If the method signature 
       * does not fit the criteria, returns <code>null</code>.
       */
      public AccessorMethodParseResults parseReadMethod(Method method) {
          return READ_METHOD_PARSER.parse(method);
      }
  
      /**
       * Parser for the <code>setFoo(value)</code> method:
       * <ul>
       *  <li>Return type void</li>
       *  <li>Name starts with "set" followed by capitalized property name</li>
       *  <li>One parameter</li>
       * </ul>
       */            
      protected static AccessorMethodParser WRITE_METHOD_PARSER =
              new AccessorMethodParser()
      {
          protected int requiredParameterCount(){
              return 1;
          }
  
          protected String requiredPrefix(){
              return "set";
          }
                  
          protected boolean testReturnType(Class returnType){
              return returnType.equals(Void.TYPE);
          }
          
          protected Class getValueType(Method method){
              return method.getParameterTypes()[0];
          }
      };
  
      /**
       * @see #parseReadMethod(Method)
     */
      public AccessorMethodParseResults parseWriteMethod(Method method) {
          return WRITE_METHOD_PARSER.parse(method);
      }
  
      /**
       * Finds a ReflectedScalarPropertyParseResults for the given
       * propertyName or creates a new one and puts it in the map.
       */
      protected ReflectedScalarPropertyParseResults getParseResults(
              ReflectedClazz clazz,
              Map parseResultMap,
              String propertyName) 
      {
          ReflectedScalarPropertyParseResults parseResults =
              (ReflectedScalarPropertyParseResults) parseResultMap.get(
                  propertyName);
          if (parseResults == null) {
              parseResults =
                  new ReflectedScalarPropertyParseResults(clazz, propertyName);
              parseResultMap.put(propertyName, parseResults);
          }
          return parseResults;
      }
      
      /**
       * Creates a new ReflectedProperty based on parse results. 
     */
      protected ReflectedProperty createProperty(
          ReflectedClazz clazz,
          ReflectedPropertyParseResults parseResults)
      {
          ReflectedScalarProperty property =
              new ReflectedScalarProperty(clazz, parseResults.getPropertyName());
  
          property.setType(parseResults.getPropertyType());
          property.setReadMethod(parseResults.getReadMethod());
          property.setWriteMethod(parseResults.getWriteMethod());
          return property;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/java/org/apache/commons/clazz/reflect/ReflectedScalarPropertyParseResults.java
  
  Index: ReflectedScalarPropertyParseResults.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  /**
   * Holds parse results for individual accessor methods for a 
   * scalar property.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedScalarPropertyParseResults.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedScalarPropertyParseResults 
              extends ReflectedPropertyParseResults
  {
      /**
       * Constructor for ReflectedScalarPropertyParseResults.
       */
      public ReflectedScalarPropertyParseResults(
              ReflectedClazz clazz, String propertyName) 
      {
          super(clazz, propertyName);
      }
      
      protected String getPropertyCategory(){
          return "scalar";
      }
      
      public boolean checkConsistency(){        
          if (!super.checkConsistency()){
              return false;
          }
                  
          if (readMethodParseResults == null){
              return false;
          }
  
          Class type = readMethodParseResults.getType();
          if (writeMethodParseResults != null){
              if (!type.equals(writeMethodParseResults.getType())){
                  return false;
              }
          }
          return true;
      }
          
      protected boolean appendInconsistencyDescriptions(StringBuffer buffer){
          if (!super.appendInconsistencyDescriptions(buffer)){
              return false;
          }
                  
          if (readMethodParseResults == null){
              buffer.append("\n     - Does not have a get() method");
              return true;
          }
  
          Class type = readMethodParseResults.getType();
          if (writeMethodParseResults != null){
              if (!type.equals(writeMethodParseResults.getType())){
                  buffer.append("\n     - Get() and set(v) types do not match");
              }
          }
          return true;  
      }  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectableInstance.java
  
  Index: ReflectableInstance.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  /**
   * This is a JavaBean used for testing of ReflectClazz.
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectableInstance.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectableInstance extends ReflectedSuperclazzInstance
  {    
      private ArrayList traceList = new ArrayList();
      private int integerProperty;
      private boolean booleanProperty;
      private Map mappedStrings = new HashMap();
      private Map mappedIntegers = new HashMap();
      private Map mappedBooleans;
      private int[] intArray;
      private List stringList = new ArrayList();
      private String notAProperty;        // Get/set have different types
      
      public List trace(){
          return traceList;
      }
      
      public void resetTrace(){
          traceList.clear();
      }
      
      private void trace(String methodName){
          traceList.add(methodName);
      }
      
      
      /**
       * Please note that the write method for this property
       * is declared by the superclass.
       * 
     * @return String
     */
      public String getHalfProperty(){
          trace("getHalfProperty()");
          return halfProperty;
      }
       
      /**
       * Returns the integerProperty.
       * @return int
       */
      public int getIntegerProperty() {
          trace("getIntegerProperty()");
          return integerProperty;
      }
  
      /**
       * Sets the integerProperty.
       * @param integerProperty The integerProperty to set
       */
      public void setIntegerProperty(int integerProperty) {
          trace("setIntegerProperty()");
          this.integerProperty = integerProperty;
      }
  
      /**
       * Returns the booleanProperty.
       * @return boolean
       */
      public boolean isBooleanProperty() {
          trace("isBooleanProperty()");
          return booleanProperty;
      }
  
      /**
       * Sets the booleanProperty.
       * @param booleanProperty The booleanProperty to set
       */
      public void setBooleanProperty(boolean booleanProperty) {
          trace("setBooleanProperty()");
          this.booleanProperty = booleanProperty;
      }
  
      public Map getMappedStrings(){
          trace("getMappedStrings()");
          return mappedStrings;
      }
      
      public void setMappedStrings(Map mappedStrings){
          trace("setMappedStrings(Map)");
          this.mappedStrings = new HashMap(mappedStrings);
      }   
      
      public void setMappedString(String key, String value){
          trace("setMappedString(String,String)");
          mappedStrings.put(key, value);
      }
      
      public String getMappedString(String key){
          trace("getMappedString(String)");
          return (String)mappedStrings.get(key);
      }
      
      public void removeMappedString(String key){
          trace("removeMappedString(String)");
          mappedStrings.remove(key);
      }
      
      public Set getMappedStringKeys(){
          trace("getMappedStringKeys()");
          return mappedStrings.keySet();
      }
          
      /*
       * The mappedInteger property does not have "normal" get/set methods.
     */    
      public void setMappedInteger(Integer key, Integer value){
          trace("setMappedInteger(Integer,Integer)");
          mappedIntegers.put(key, value);
      }
      
      public Integer getMappedInteger(Integer key){
          trace("getMappedInteger(Integer)");
          return (Integer)mappedIntegers.get(key);
      }
      
      public void removeMappedInteger(Integer key){
          trace("removeMappedInteger(Integer)");
          mappedIntegers.remove(key);
      }
      
      public Integer[] getMappedIntegerKeys(){
          trace("getMappedIntegerKeys()");
          return (Integer[])mappedIntegers.keySet().toArray(new Integer[0]);
      }
      
  
      /*
       * The mappedBooleans property does not have 
       * parameterized get/set/remove methods.
       */    
      public Map getMappedBooleans(){
          trace("getMappedBooleans()");
          return mappedBooleans;
      }
      
      public void setMappedBooleans(Map mappedBooleans){
          trace("setMappedBooleans(Map)");
          this.mappedBooleans = mappedBooleans;
      }    
  
  
      public int[] getIntArray(){
          trace("getIntArray()");
          return intArray;
      }
      
      public void setIntArray(int[] array){
          trace("setIntArray(int[])");
          this.intArray = array;
      }
      
      public String getString(int index){
          trace("getString(int)");
          return (String)stringList.get(index);
      }
          
      public void setString(int index, String string){
          trace("setString(int,String)");
          stringList.set(index, string);
      }
      
      public void addString(int index, String string){
          trace("addString(int,String)");
          stringList.add(index, string);
      }
      
      public void addString(String string){
          trace("addString()");
          stringList.add(string);
      }
      
      public void removeString(String string){
          trace("removeString(String)");
          stringList.remove(string);
      }
      
      public int getStringCount(){
          trace("getStringCount()");
          return stringList.size();
      }
      
      /**
       * Returns the notAProperty.
       * @return String
       */
      public Object getNotAProperty() {
          trace("getNotAProperty()");
          return notAProperty;
      }
  
      /**
       * Returns the notAProperty.
       * @return String
       */
      public boolean isNotAProperty() {
          trace("isNotAProperty()");
          return false;
      }
  
      /**
       * Sets the notAProperty.
       * @param notAProperty The notAProperty to set
       */
      public void setNotAProperty(String notAProperty) {
          trace("setNotAProperty(String)");
          this.notAProperty = notAProperty;
      }
  
      /**
       * If there is not "get" method, there is no mapped property
     */
      public void setNotAMappedProperty(String key, String value){
          trace("setNotAMappedProperty(String,String)");
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectedClazzTest.java
  
  Index: ReflectedClazzTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzProperty;
  
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedClazzTest.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedClazzTest extends ReflectedClazzTestSupport {
  
      /**
       * Constructor for ReflectedClazzTest.
       * @param name
       */
      public ReflectedClazzTest(String name) {
          super(name);
      }
  
      public static void main(String[] args) {
          junit.textui.TestRunner.run(ReflectedClazzTest.suite());
      }
  
      public static TestSuite suite(){
          TestSuite suite = new TestSuite();
          suite.addTestSuite(ReflectedClazzTest.class);
          suite.addTestSuite(ReflectedListPropertyTest.class);
          suite.addTestSuite(ReflectedMappedPropertyTest.class);
          return suite;
      }
      
      public void testGetSuperClazz() {
          assertEquals(
                  ReflectableInstance.class.getSuperclass().getName(), 
                  clazz.getSuperclazz().getName());
      }
  
       
      public void testGetProperties() {
          assertPropertyList(
              "Get properties",
              new String[]{
                  "baseProperty",
                  "booleanProperty",
                  "halfProperty",
                  "integerProperty",
                  "intArray",
                  "string",
                  "mappedBooleans",
                  "mappedInteger",
                  "mappedStrings",
                  "mappedIntegerKeys",
                  "mappedStringKeys",
                  "stringCount",
              },
              clazz.getProperties());
      }
  
      public void testGetPropertiesForSuperclazz() {
          assertPropertyList(
              "Get properties for superclazz",
              new String[]{
                  "baseProperty",
              },
              clazz.getSuperclazz().getProperties());
      }
  
      public void testGetDeclaredProperties() {
          assertPropertyList(
              "Get declared properties",
              new String[]{
                  "booleanProperty",
                  "halfProperty",
                  "integerProperty",
                  "intArray",
                  "string",
                  "mappedBooleans",
                  "mappedInteger",
                  "mappedStrings",
                  "mappedIntegerKeys", 
                  "mappedStringKeys",
                  "stringCount",
              },
              clazz.getDeclaredProperties());
      }
  
      public void testGetDeclaredPropertiesForSuperclazz() {
          assertPropertyList(
              "Get declared properties for superclazz",
              new String[]{
                  "baseProperty",
              },
              clazz.getSuperclazz().getDeclaredProperties());
      }
      
      public void assertPropertyList(
              String testName,
              String[] expectedNames,
              List properties) 
      {
          List expectedList = Arrays.asList(expectedNames);
          Collections.sort(expectedList);
          List names = new ArrayList();
          for (Iterator iter = properties.iterator(); iter.hasNext();) {
              ClazzProperty property = (ClazzProperty) iter.next();
              names.add(property.getName());
          }
          Collections.sort(names);
  //        System.out.println("Expected: " + testName + expectedList);
  //        System.out.println("Actual:   " + testName + names);
          assertEquals(testName, expectedList, names);
      }
  
      /**
       * Checks that get/set methods are recognized properly.
     */
      public void testRecognitionOfScalarPropertyMethods(){
          ReflectedScalarProperty property = 
              (ReflectedScalarProperty)clazz.getProperty("integerProperty");
              
          assertMethodSignature("Read method",
              "getIntegerProperty()",
              property.getReadMethod());
              
          assertMethodSignature("Write method",
              "setIntegerProperty(int)",
              property.getWriteMethod());
      }
      
      /**
       * Checks that the "is" method is recognized for a boolean property.
       */
      public void testRecognitionOfScalarBooleanPropertyMethods(){
          ReflectedScalarProperty property = 
              (ReflectedScalarProperty)clazz.getProperty("booleanProperty");
              
          assertMethodSignature("Read method",
              "isBooleanProperty()",
              property.getReadMethod());
              
          assertMethodSignature("Write method",
              "setBooleanProperty(boolean)",
              property.getWriteMethod());
      }
      
  
      public void testGetFields() {
      }
  
      public void testGetField() {
      }
  
      public void testGetOperations() {
      }
  
      public void testGetDeclaredOperations() {
      }
  
      public void testGetOperation() {
      }
  
      /*
       * Test for Object newInstance()
       */
      public void testNewInstance() {
      }
  
      /*
       * Test for Object newInstance(Object[])
       */
      public void testNewInstanceObjectArray() {
      }
  
      public void testGetName() {
          assertEquals(instance.getClass().getName(), clazz.getName());
      }
  
      public void testGetPackageName() {
          String pname = ReflectableInstance.class.getName().substring(0, 
                  ReflectableInstance.class.getName().lastIndexOf('.'));
          assertEquals(pname, clazz.getPackageName());
      }
  
      public void testGetShortClassName() {
          String cname = ReflectableInstance.class.getName().substring( 
                  ReflectableInstance.class.getName().lastIndexOf('.') + 1);
          assertEquals(cname, clazz.getShortClassName());
      }
  
      public void testIsAssignableFrom() {
      }
  
      public void testGetScalarPropertyValue(){
          ClazzProperty property =
              (ClazzProperty) clazz.getProperty("integerProperty");
          Object result = property.get(instance);
          assertTrace(
              "getting scalar property value",
              "getIntegerProperty()");
          assertEquals(result, new Integer(0));
      }
      
      public void testPutScalarPropertyValue(){
          ClazzProperty property =
              (ClazzProperty) clazz.getProperty("integerProperty");
          property.set(instance, new Integer(3));
          assertTrace(
              "setting scalar property value",
              "setIntegerProperty()");
          assertEquals(3, instance.getIntegerProperty());
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectedClazzTestSupport.java
  
  Index: ReflectedClazzTestSupport.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  
  import org.apache.commons.clazz.Clazz;
  import org.apache.commons.clazz.ClazzProperty;
  
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedClazzTestSupport.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedClazzTestSupport extends TestCase 
  {
      protected ReflectableInstance instance;
      protected Clazz clazz;
      
      /**
       * Constructor for ReflectedClazzTestSupport.
       * @param name
       */
      public ReflectedClazzTestSupport(String name) {
          super(name);
      }
  
  
      /**
       * @see TestCase#setUp()
       */
      protected void setUp() throws Exception {
          instance = new ReflectableInstance();
          clazz = Clazz.getClazz(instance);
          clazz.enableLogging(clazz.getName());
      }
  
      protected void assertMethodSignature(
              String text,
              String signature,
              Method method) 
      {
          assertNotNull(text + " is null", method);
          
          StringBuffer buffer = new StringBuffer();
          buffer.append(method.getName());
          buffer.append("(");
          Class paramTypes[] = method.getParameterTypes();
          for (int i = 0; i < paramTypes.length; i++) {
              if (i > 0){
                  buffer.append(",");
              }
              buffer.append(paramTypes[i].getName());
          }
          buffer.append(")");
          assertEquals(text, signature, buffer.toString());
      }
  
      protected void assertTraceEmpty(String text)
      {
          assertEquals(
              "Methods invoked for " + text,
              Collections.EMPTY_LIST,
              instance.trace());
      }
  
      protected void assertTrace(String text, String method) {
          List methods = new ArrayList();
          methods.add(method);
          assertEquals("Methods invoked for " + text, methods, instance.trace());
      }
  
      protected void assertTrace(String text, String method1, String method2) {
          List methods = new ArrayList();
          methods.add(method1);
          methods.add(method2);
          assertEquals("Methods invoked for " + text, methods, instance.trace());
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectedListPropertyTest.java
  
  Index: ReflectedListPropertyTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import junit.framework.TestSuite;
  
  import org.apache.commons.clazz.ClazzProperty;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedListPropertyTest.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedListPropertyTest extends ReflectedClazzTestSupport
  {
      private ReflectedListProperty intArrayProperty;
      private ReflectedListProperty stringProperty;
      
      /**
       * Constructor for ReflectedPropertyMapTest.
       * @param name Is the test method name
       */
      public ReflectedListPropertyTest(String name) {
          super(name);
      }
  
      public static void main(String[] args) {
          junit.textui.TestRunner.run(ReflectedListPropertyTest.suite());
      }
  
      public static TestSuite suite(){
          return new TestSuite(ReflectedListPropertyTest.class);
      }
      
      public void setUp() throws Exception {
          super.setUp();
          intArrayProperty = 
              (ReflectedListProperty)clazz.getProperty("intArray");
          stringProperty = 
              (ReflectedListProperty)clazz.getProperty("string");
      }
      
      /**
       * Checks the set of methods recognized for a List property that
       * does not have regular get/set methods.
       */
      public void testRecognitionOfListPropertyWithoutReadWriteMethods(){
          assertNull("Read method",
              stringProperty.getReadMethod());
              
          assertNull("Write method",
              stringProperty.getWriteMethod());
  
          assertMethodSignature("Get method",
              "getString(int)",
              stringProperty.getGetMethod());
  
          assertMethodSignature("Set method",
              "setString(int,java.lang.String)",
              stringProperty.getSetMethod());
              
          assertMethodSignature("Add method",
              "addString(java.lang.String)",
              stringProperty.getAddMethod());
              
          assertMethodSignature("Add(i) method",
              "addString(int,java.lang.String)",
              stringProperty.getAddIndexedMethod());
              
          assertMethodSignature("Remove method",
              "removeString(java.lang.String)",
              stringProperty.getRemoveMethod());            
  
          assertMethodSignature("Size method",
              "getStringCount()",
              stringProperty.getSizeMethod());            
      }
      
      /**
       * Checks the a property is recognized as List even if it
       * does not have parameterized get/set/remove methods.
       */
      public void testRecognitionOfListPropertyWithoutGetSetAddRemoveMethods(){            
          assertMethodSignature("Read method",
              "getIntArray()",
              intArrayProperty.getReadMethod());
              
          assertMethodSignature("Write method",
              "setIntArray([I)",
              intArrayProperty.getWriteMethod());
  
          assertNull("Get method",
              intArrayProperty.getGetMethod());
  
          assertNull("Set method",
              intArrayProperty.getSetMethod());
  
          assertNull("Add method",
              intArrayProperty.getAddMethod());
  
          assertNull("Add(i) method",
              intArrayProperty.getAddIndexedMethod());
  
          assertNull("Remove method",
              intArrayProperty.getRemoveMethod());
  
          assertNull("Size method",
              intArrayProperty.getSizeMethod());
      }
      
      public void testGetListPropertyValue(){
          Object result = intArrayProperty.get(instance);
          assertTraceEmpty(
              "getting List property value");
              
          assertTrue(result instanceof ReflectedList);
      }
          
      public void testSizeWithArray() {
          instance.setIntArray(new int[]{1, 2, 3});
          instance.resetTrace();
          
          List list = (List)intArrayProperty.get(instance);
          int count = list.size();
          
          assertTrace(
              "getting size with direct getter",
              "getIntArray()");
          assertEquals(3, count);
      }
  
      public void testSizeWithList() {
          instance.addString("foo");
          instance.addString("bar");
          instance.addString("baz");
          instance.resetTrace();
          
          List list = (List)stringProperty.get(instance);
          int count = list.size();
          
          assertTrace(
              "getting size with count getter",
              "getStringCount()");
          assertEquals(3, count);
      }
      
      public void testSizeWithEmpty() {
          List list = (List)intArrayProperty.get(instance);
          int count = list.size();
          
          assertTrace(
              "getting size with count getter",
              "getIntArray()");
          assertEquals(0, count);
      }
      
      public void testIsEmpty() {
      }
  
      public void testContains() {
      }
  
      public void testIterator() {
      }
  
      /*
       * Test for Object[] toArray()
       */
      public void testToArray() {
      }
  
      /*
       * Test for Object[] toArray(Object[])
       */
      public void testToArrayObjectArray() {
      }
  
      /*
       * Test for boolean add(Object)
       */
      public void testAddObject() {
      }
  
      /*
       * Test for boolean remove(Object)
       */
      public void testRemoveObject() {
      }
  
      public void testContainsAll() {
      }
  
      /*
       * Test for boolean addAll(Collection)
       */
      public void testAddAllCollection() {
      }
  
      /*
       * Test for boolean addAll(int, Collection)
       */
      public void testAddAllICollection() {
      }
  
      public void testRemoveAll() {
      }
  
      public void testRetainAll() {
      }
  
      public void testClear() {
      }
  
      public void testGetWithArray() {
          instance.setIntArray(new int[]{1, 2, 3});
          instance.resetTrace();
          
          List list = (List)intArrayProperty.get(instance);
          Object value = list.get(1);
          
          assertTrace(
              "getting value with direct getter",
              "getIntArray()");
          assertEquals(new Integer(2), value);
      }
  
      public void testGetWithList() {
          instance.addString("foo");
          instance.addString("bar");
          instance.addString("baz");
          instance.resetTrace();
          
          List list = (List)stringProperty.get(instance);
          Object value = list.get(1);
          
          assertTrace(
              "getting value with parameterized getter",
              "getString(int)");
              
          assertEquals("bar", value);
      }
  
      public void testSetWithArray() {
          instance.setIntArray(new int[]{1, 2, 3});
          instance.resetTrace();
          
          List list = (List)intArrayProperty.get(instance);
          list.set(1, new Integer(7));
          
          assertTrace(
              "setting value with direct getter",
              "getIntArray()");
          assertEquals(7, instance.getIntArray()[1]);
      }
      
      public void testSetWithList() {
          instance.addString("foo");
          instance.addString("bar");
          instance.addString("baz");
          instance.resetTrace();
          
          List list = (List)stringProperty.get(instance);
          list.set(1, "biz");
          
          assertTrace(
              "setting value with parameterized setter",
              "getString(int)",
              "setString(int,String)");
              
          assertEquals("biz", instance.getString(1));
      }
  
      /*
       * Test for void add(int, Object)
       */
      public void testAddIObject() {
      }
  
      /*
       * Test for Object remove(int)
       */
      public void testRemoveI() {
      }
  
      public void testIndexOf() {
      }
  
      public void testLastIndexOf() {
      }
  
      /*
       * Test for ListIterator listIterator()
       */
      public void testListIterator() {
      }
  
      /*
       * Test for ListIterator listIterator(int)
       */
      public void testListIteratorI() {
      }
  
      public void testSubList() {
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectedMappedPropertyTest.java
  
  Index: ReflectedMappedPropertyTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.Set;
  
  import junit.framework.TestSuite;
  
  import org.apache.commons.clazz.ClazzProperty;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedMappedPropertyTest.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedMappedPropertyTest extends ReflectedClazzTestSupport
  {
      private ReflectedMappedProperty mappedStringsProperty;
      private ReflectedMappedProperty mappedIntegerProperty;
      private ReflectedMappedProperty mappedBooleansProperty;
      
      /**
       * Constructor for ReflectedPropertyMapTest.
       * @param name Is the test method name
       */
      public ReflectedMappedPropertyTest(String name) {
          super(name);
      }
  
      public static void main(String[] args) {
          junit.textui.TestRunner.run(ReflectedMappedPropertyTest.suite());
      }
  
      public static TestSuite suite(){
          return new TestSuite(ReflectedMappedPropertyTest.class);
      }
      
      public void setUp() throws Exception {
          super.setUp();
          mappedStringsProperty = 
              (ReflectedMappedProperty)clazz.getProperty("mappedStrings");
          mappedIntegerProperty = 
              (ReflectedMappedProperty)clazz.getProperty("mappedInteger");
          mappedBooleansProperty = 
              (ReflectedMappedProperty)clazz.getProperty("mappedBooleans");        
      }
      
      /**
       * Checks the full set of methods recognized for a mapped property.
       */
      public void testRecognitionOfMappedPropertyMethods(){
              
          assertMethodSignature("Read method",
              "getMappedStrings()",
              mappedStringsProperty.getReadMethod());
              
          assertMethodSignature("Write method",
              "setMappedStrings(java.util.Map)",
              mappedStringsProperty.getWriteMethod());
  
          assertMethodSignature("Get method",
              "getMappedString(java.lang.String)",
              mappedStringsProperty.getGetMethod());
  
          assertMethodSignature("Put method",
              "setMappedString(java.lang.String,java.lang.String)",
              mappedStringsProperty.getPutMethod());
  
          assertMethodSignature("Remove method",
              "removeMappedString(java.lang.String)",
              mappedStringsProperty.getRemoveMethod());
              
          assertMethodSignature("KeySet method",
              "getMappedStringKeys()",
              mappedStringsProperty.getKeySetMethod());
      }
      
      /**
       * Checks the set of methods recognized for a mapped property that
       * does not have regular get/set methods.
       */
      public void testRecognitionOfMappedPropertyWithoutReadWriteMethods(){
          assertNull("Read method",
              mappedIntegerProperty.getReadMethod());
              
          assertNull("Write method",
              mappedIntegerProperty.getWriteMethod());
  
          assertMethodSignature("Get method",
              "getMappedInteger(java.lang.Integer)",
              mappedIntegerProperty.getGetMethod());
  
          assertMethodSignature("Put method",
              "setMappedInteger(java.lang.Integer,java.lang.Integer)",
              mappedIntegerProperty.getPutMethod());
  
          assertMethodSignature("Remove method",
              "removeMappedInteger(java.lang.Integer)",
              mappedIntegerProperty.getRemoveMethod());
  
          assertMethodSignature("KeySet method",
              "getMappedIntegerKeys()",
              mappedIntegerProperty.getKeySetMethod());
      }
      
      /**
       * Checks the a property is recognized as Mapped even if it
       * does not have specific get/set/remove methods.
       */
      public void testRecognitionOfMappedPropertyWithoutGetPutRemoveMethods(){
           assertMethodSignature("Read method",
              "getMappedBooleans()",
              mappedBooleansProperty.getReadMethod());
              
          assertMethodSignature("Write method",
              "setMappedBooleans(java.util.Map)",
              mappedBooleansProperty.getWriteMethod());
  
          assertNull("Get method",
              mappedBooleansProperty.getGetMethod());
  
          assertNull("Put method",
              mappedBooleansProperty.getPutMethod());
  
          assertNull("Remove method",
              mappedBooleansProperty.getRemoveMethod());
  
          assertNull("KeySet method",
              mappedBooleansProperty.getKeySetMethod());
      }
      
      public void testGetMappedPropertyValue(){
          Object result = mappedStringsProperty.get(instance);
          assertTraceEmpty(
              "getting mapped property value");
              
          assertTrue(result instanceof ReflectedMap);
      }
          
      public void testClear() {
      }
  
      public void testContainsKey() {
      }
  
      public void testContainsValue() {
      }
  
      public void testEntrySet() {
      }
  
      public void testGetEmptyMap() {
          Map map = (Map) mappedBooleansProperty.get(instance);
          Object value = map.get("bar");
          
          assertTrace("getting value from empty map", "getMappedBooleans()");
          assertNull(value);
      }
  
      public void testGetWithSpecificAccessor() {
          instance.getMappedStrings().put("foo", "bar");
          instance.resetTrace();
  
          Map map = (Map) mappedStringsProperty.get(instance);
          Object value = map.get("foo");
  
          assertTrace(
              "getting value with specific getter",
              "getMappedString(String)");
          assertEquals("bar", value);
      }
  
      public void testGetWithDirectAccessor() {
          instance.setMappedBooleans(new HashMap());
          instance.getMappedBooleans().put("foo", Boolean.TRUE);
          instance.resetTrace();
  
          Map map = (Map) mappedBooleansProperty.get(instance);
          Object value = map.get("foo");
  
          assertTrace(
              "getting value with principal getter",
              "getMappedBooleans()");
          assertEquals(Boolean.TRUE, value);
      }
      
      public void testPutWithSpecificAccessor() {
          instance.getMappedStrings().put("foo", "bar");
          instance.resetTrace();
          
          Map map = (Map) mappedStringsProperty.get(instance);
          Object oldValue = map.put("foo", "baz");
          assertTrace(
              "setting value with specific setter",
              "getMappedString(String)",
              "setMappedString(String,String)");
          assertEquals("baz", instance.getMappedStrings().get("foo"));        
          assertEquals("bar", oldValue);        
      }
  
      public void testPutWithDirectAccessor() {
          instance.setMappedBooleans(new HashMap());
          instance.resetTrace();
          
          Map map = (Map) mappedBooleansProperty.get(instance);
          Object oldValue = map.put("foo", Boolean.TRUE);
          assertTrace(
              "setting value with principal setter",
              "getMappedBooleans()");
          assertEquals(Boolean.TRUE, instance.getMappedBooleans().get("foo"));        
          assertNull(oldValue);        
      }
  
      public void testPutEmptyMap() {
          Map map = (Map) mappedBooleansProperty.get(instance);
          Object oldValue = map.put("foo", Boolean.TRUE);
          assertTrace(
              "setting value with initially empty map",
              "getMappedBooleans()",
              "setMappedBooleans(Map)");
          assertEquals(Boolean.TRUE, instance.getMappedBooleans().get("foo"));        
          assertNull(oldValue);        
      }
  
      public void testIsEmpty() {
      }
  
      public void testKeySetWithSpecificAccessor() {
          instance.getMappedStrings().put("foo", "1");
          instance.getMappedStrings().put("bar", "2");
          instance.resetTrace();
          
          Map map = (Map) mappedStringsProperty.get(instance);
          Set keySet = map.keySet();
          assertTrace(
              "getting key set with specific setter",
              "getMappedStringKeys()");
          
          HashSet expected = new HashSet();
          expected.add("foo");
          expected.add("bar");
          
          assertEquals(expected, keySet);        
      }
  
      public void testKeySetWithPrincipalAccessor() {
          instance.setMappedBooleans(new HashMap());
          instance.getMappedBooleans().put("foo", Boolean.TRUE);
          instance.getMappedBooleans().put("bar", Boolean.FALSE);
          instance.resetTrace();
          
          Map map = (Map) mappedBooleansProperty.get(instance);
          Set keySet = map.keySet();
          assertTrace(
              "getting key set with principal setter",
              "getMappedBooleans()");
          
          HashSet expected = new HashSet();
          expected.add("foo");
          expected.add("bar");
          
          assertEquals(expected, keySet);        
      }
  
      public void testPutAll() {
      }
  
      public void testRemove() {
      }
  
      public void testSize() {
      }
  
      public void testValues() {
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/clazz/src/test/org/apache/commons/clazz/reflect/ReflectedSuperclazzInstance.java
  
  Index: ReflectedSuperclazzInstance.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 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 Software Foundation.
   *
   * 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/>.
   */
  package org.apache.commons.clazz.reflect;
  
  /**
   * 
   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
   * @version $Id: ReflectedSuperclazzInstance.java,v 1.1 2002/11/08 14:29:36 dmitri Exp $
   */
  public class ReflectedSuperclazzInstance {
  
      private String baseProperty;
      protected String halfProperty;
      
      /**
       * Returns the baseProperty.
       * Note, that "baseProperty" should be included in the list 
       * of declared properties for ReflectedSuperclazzInstance,
       * as well as the complete list of properties of ReflectedInstance,
       * but the list of declared properties of ReflectedInstance.
       */
      public String getBaseProperty() {
          return baseProperty;
      }
  
      /**
       * Sets the baseProperty.
       * @param baseProperty The baseProperty to set
       */
      public void setBaseProperty(String baseProperty) {
          this.baseProperty = baseProperty;
      }
      
      /**
       * Note that this accessor does not constitue a complete property -
       * there is no read method.  However that read method is introduced
       * by the subclass ReflectedInstance, therefore "halfProperty" will
       * be a declared property of the subclass.
       */
      public void setHalfProperty(String halfProperty){
          this.halfProperty = halfProperty;
      }
      
  
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message