You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by qu...@apache.org on 2003/01/03 08:20:44 UTC

cvs commit: jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel AppData.java Rule.java XmlField.java XmlGroup.java

quintonm    2003/01/02 23:20:44

  Modified:    src/java/org/apache/turbine/services/intake
                        IntakeService.java IntakeTool.java
                        TurbineIntake.java TurbineIntakeService.java
               src/java/org/apache/turbine/services/intake/model
                        BigDecimalField.java BooleanField.java
                        ComboKeyField.java DateStringField.java Field.java
                        FieldFactory.java FileItemField.java
                        FloatField.java Group.java IntegerField.java
                        NumberKeyField.java StringField.java
                        StringKeyField.java
               src/java/org/apache/turbine/services/intake/transform
                        DTDResolver.java XmlToAppData.java
               src/java/org/apache/turbine/services/intake/validator
                        Constraint.java DateStringValidator.java
                        DefaultValidator.java FileValidator.java
                        InitableByConstraintMap.java IntegerValidator.java
                        NumberKeyValidator.java NumberValidator.java
                        ValidationException.java Validator.java
               src/java/org/apache/turbine/services/intake/xmlmodel
                        AppData.java Rule.java XmlField.java XmlGroup.java
  Added:       src/java/org/apache/turbine/services/intake
                        IntakeException.java
               src/java/org/apache/turbine/services/intake/validator
                        BooleanValidator.java InvalidMaskException.java
  Log:
  - Backported changes from the Fulcrum version
  - IntakeException is now the default exception thrown from all public methods.
  - Exception handling improved
  - Henning's change to allow multiple XML definition files.
  - Better logging for error conditions
  - TTSW20 is fixed
  - Javadocs updated
  - New Boolean validator
  - Converted to commons-logging
  - Converted from regexp to ORO
  
  Revision  Changes    Path
  1.4       +52 -66    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/IntakeService.java
  
  Index: IntakeService.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/IntakeService.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IntakeService.java	11 Jul 2002 16:53:28 -0000	1.3
  +++ IntakeService.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -54,15 +54,26 @@
    * <http://www.apache.org/>.
    */
   
  +import java.beans.IntrospectionException;
   import java.lang.reflect.Method;
  +
   import org.apache.turbine.services.intake.model.Group;
  -import org.apache.turbine.util.TurbineException;
   
   /**
    * This service provides access to input processing objects based
    * on an XML specification.
    *
  + * <p>Localization of Intake's error messages can be accomplished
  + * using Turbine's <code>LocalizationTool</code> from a Velocity template
  + * as follows:
  + * <blockquote><code></pre>
  + * $l10n.get($intake.SomeGroup.SomeField.Message)
  + * </pre></code></blockquote>
  + * </p>
  + *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public interface IntakeService
  @@ -78,91 +89,56 @@
       public static final String XML_PATH = "xml.path";
   
       /**
  -     * The default pool capacity.
  +     * The default location of the xml specification.
        */
  -    public static final int DEFAULT_POOL_CAPACITY = 1024;
  +    public static final String XML_PATH_DEFAULT = "WEB-INF/conf/intake.xml";
   
       /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty.
  -     *
  -     * @param groupName the name of the group.
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  +     * The property specifying the location where a serialized version of
  +     * the xml specification can be written for faster restarts..
        */
  -    public Group getGroup(String groupName)
  -        throws TurbineException;
  +    public static final String SERIAL_XML = "serialize.path";
   
       /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty and
  -     * then initialize it using the ParameterParser looking for
  -     * a NEW id.
  -     *
  -     * @param groupName the name of the group.
  -     * @param pp the request parameters that may contain matching keys
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  -     * /
  -    public Group getGroup(String groupName, ParameterParser pp)
  -        throws Exception;
  -
  -    /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty and
  -     * then initialize it using the ParameterParser looking for id.
  -     *
  -     * @param groupName the name of the group.
  -     * @param pp the request parameters that may contain matching keys
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  -     * /
  -    public Group getGroup(String groupName, ParameterParser pp, String id)
  -        throws Exception;
  -    */
  +     * The default location where a serialized version of
  +     * the xml specification can be written for faster restarts..
  +     */
  +    public static final String SERIAL_XML_DEFAULT = "WEB-INF/appData.ser";
   
       /**
  -     * Puts a group back to the pool.
  -     * @param instance the object instance to recycle.
  -     * @return true if the instance was accepted.
  +     * The default pool capacity.
        */
  -    public boolean releaseGroup(Group instance);
  +    public static final int DEFAULT_POOL_CAPACITY = 1024;
   
       /**
  -     * Gets the capacity of the pool for a named group.
  +     * Gets an instance of a named group either from the pool
  +     * or by calling the Factory Service if the pool is empty.
        *
        * @param groupName the name of the group.
  +     * @return a Group instance.
  +     * @throws IntakeException if recycling fails.
        */
  -    public int getCapacity(String groupName);
  +    public Group getGroup(String groupName)
  +            throws IntakeException;
   
       /**
  -     * Sets the capacity of the pool for a named group.
  -     * Note that the pool will be cleared after the change.
  +     * Puts a group back to the pool.
  +     * @param instance the object instance to recycle.
        *
  -     * @param groupName the name of the group.
  -     * @param capacity the new capacity.
  +     * @throws IntakeException The passed group name does not exist.
        */
  -    public void setCapacity(String groupName,
  -                            int capacity);
  +    public void releaseGroup(Group instance)
  +            throws IntakeException;
   
       /**
        * Gets the current size of the pool for a named group.
        *
        * @param groupName the name of the group.
  -     */
  -    public int getSize(String groupName);
  -
  -    /**
  -     * Clears instances of a named group from the pool.
        *
  -     * @param groupName the name of the group.
  -     */
  -    public void clearPool(String groupName);
  -
  -    /**
  -     * Clears all instances from the pool.
  +     * @throws IntakeException The passed group name does not exist.
        */
  -    public void clearPool();
  +    public int getSize(String groupName)
  +            throws IntakeException;
   
       /**
        * Names of all the defined groups.
  @@ -182,7 +158,7 @@
       /**
        * Gets the group name given its key.
        *
  -     * @param the the key.
  +     * @param groupKey the key.
        * @return groupName the name of the group.
        */
       public String getGroupName(String groupKey);
  @@ -193,8 +169,11 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the setter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
  -    public Method getFieldSetter(String className, String propName);
  +    public Method getFieldSetter(String className, String propName)
  +            throws ClassNotFoundException, IntrospectionException;
   
       /**
        * Gets the Method that can be used to get a property value.
  @@ -202,7 +181,14 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the getter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
  -    public Method getFieldGetter(String className, String propName);
  -
  +    public Method getFieldGetter(String className, String propName)
  +            throws ClassNotFoundException, IntrospectionException;
   }
  +
  +
  +
  +
  +
  
  
  
  1.9       +154 -65   jakarta-turbine-2/src/java/org/apache/turbine/services/intake/IntakeTool.java
  
  Index: IntakeTool.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/IntakeTool.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- IntakeTool.java	8 Dec 2002 17:34:35 -0000	1.8
  +++ IntakeTool.java	3 Jan 2003 07:20:43 -0000	1.9
  @@ -58,38 +58,49 @@
   import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.turbine.om.Retrievable;
   import org.apache.turbine.services.intake.model.Group;
   import org.apache.turbine.services.pull.ApplicationTool;
  -import org.apache.turbine.util.Log;
   import org.apache.turbine.util.RunData;
  +import org.apache.turbine.util.TurbineException;
  +import org.apache.turbine.util.ValueParser;
   import org.apache.turbine.util.pool.Recyclable;
   
   /**
  - * A Pull tool to make intake objects available to a template
  + * The main class through which Intake is accessed.
    *
    * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class IntakeTool
  -    implements ApplicationTool, Recyclable
  +        implements ApplicationTool, Recyclable
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(IntakeTool.class);
  +
       public static final String DEFAULT_KEY = "_0";
       private HashMap groups;
  -    private RunData data;
  -    // private boolean allValid;
  -    // private String omToolKey;
  -    // private OMTool omTool;
  +    private ValueParser pp;
  +
  +    HashMap declaredGroups = new HashMap();
  +    StringBuffer allGroupsSB = new StringBuffer(256);
  +    StringBuffer groupSB = new StringBuffer(128);
   
       /** The cache of PullHelpers. **/
  -    private Map pullMap = new HashMap();
  +    private Map pullMap;
   
  +    /**
  +     * Constructor
  +     */
       public IntakeTool()
       {
           String[] groupNames = TurbineIntake.getGroupNames();
  -        groups = new HashMap((int)(1.25*groupNames.length + 1));
  -        pullMap = new HashMap((int)(1.25*groupNames.length + 1));
  -        // omToolKey = TurbineResources.getString("tool.intake.om");
  +        groups = new HashMap((int) (1.25 * groupNames.length + 1));
  +        pullMap = new HashMap((int) (1.25 * groupNames.length + 1));
   
           for (int i = groupNames.length - 1; i >= 0; i--)
           {
  @@ -102,9 +113,9 @@
        */
       public void init(Object runData)
       {
  -        data = (RunData)runData;
  +        this.pp = ((RunData) runData).getParameters();
   
  -        String[] groupKeys = data.getParameters().getStrings("intake-grp");
  +        String[] groupKeys = pp.getStrings("intake-grp");
           String[] groupNames = null;
           if (groupKeys == null || groupKeys.length == 0)
           {
  @@ -125,25 +136,41 @@
               try
               {
                   List foundGroups = TurbineIntake.getGroup(groupNames[i])
  -                    .getObjects(data);
  +                        .getObjects(pp);
   
                   if (foundGroups != null)
                   {
                       Iterator iter = foundGroups.iterator();
                       while (iter.hasNext())
                       {
  -                        Group group = (Group)iter.next();
  +                        Group group = (Group) iter.next();
                           groups.put(group.getObjectKey(), group);
                       }
                   }
               }
  -            catch(Exception e)
  +            catch (Exception e)
               {
  -                Log.error(e);
  +                log.error(e);
               }
           }
       }
   
  +    public void addGroupsToParameters(ValueParser vp)
  +    {
  +        Iterator i = groups.values().iterator();
  +        while (i.hasNext())
  +        {
  +            Group group = (Group) i.next();
  +            if (!declaredGroups.containsKey(group.getIntakeGroupName()))
  +            {
  +                declaredGroups.put(group.getIntakeGroupName(), null);
  +                vp.add("intake-grp", group.getGID());
  +            }
  +            vp.add(group.getGID(), group.getOID());
  +        }
  +        declaredGroups.clear();
  +    }
  +
       /**
        * A convenience method to write out the hidden form fields
        * that notify intake of the relevant groups.  It should be used
  @@ -159,15 +186,11 @@
           Iterator i = groups.values().iterator();
           while (i.hasNext())
           {
  -            declareGroup((Group)i.next(), allGroupsSB);
  +            declareGroup((Group) i.next(), allGroupsSB);
           }
           return allGroupsSB.toString();
       }
   
  -    HashMap declaredGroups = new HashMap();
  -    StringBuffer allGroupsSB = new StringBuffer(256);
  -    StringBuffer groupSB = new StringBuffer(128);
  -
       /**
        * A convenience method to write out the hidden form fields
        * that notify intake of the group.
  @@ -189,9 +212,9 @@
           {
               declaredGroups.put(group.getIntakeGroupName(), null);
               sb.append("<input type=\"hidden\" name=\"")
  -              .append("intake-grp\" value=\"")
  -              .append(group.getGID())
  -              .append("\"></input>\n");
  +                    .append("intake-grp\" value=\"")
  +                    .append(group.getGID())
  +                    .append("\"/>\n");
           }
           group.appendHtmlFormInput(sb);
       }
  @@ -202,7 +225,7 @@
           Iterator i = groups.values().iterator();
           while (i.hasNext())
           {
  -             ((Group)i.next()).resetDeclared();
  +            ((Group) i.next()).resetDeclared();
           }
       }
   
  @@ -220,73 +243,89 @@
        */
       public class PullHelper
       {
  +        /** Name of the group used by the pull helper */
           String groupName;
   
  +        /**
  +         * Private constructor to force use of factory method.
  +         *
  +         * @param groupName
  +         */
           private PullHelper(String groupName)
           {
               this.groupName = groupName;
           }
   
  -      /**
  -       * populates the object with the default values from the XML File
  -       *
  -       * @return a Group object with the default values
  -       */
  -
  +        /**
  +         * Populates the object with the default values from the XML File
  +         *
  +         * @return a Group object with the default values
  +         * @throws IntakeException
  +         */
           public Group getDefault()
  -            throws Exception
  +                throws IntakeException
           {
               return setKey(DEFAULT_KEY);
           }
   
  +        /**
  +         * Calls setKey(key,true)
  +         *
  +         * @param key
  +         * @return an Intake Group
  +         * @throws IntakeException
  +         */
           public Group setKey(String key)
  -            throws Exception
  +                throws IntakeException
           {
               return setKey(key, true);
           }
   
  +        /**
  +         *
  +         * @param key
  +         * @param create
  +         * @return an Intake Group
  +         * @throws IntakeException
  +         */
           public Group setKey(String key, boolean create)
  -            throws Exception
  +                throws IntakeException
           {
               Group g = null;
   
               String inputKey = TurbineIntake.getGroupKey(groupName) + key;
               if (groups.containsKey(inputKey))
               {
  -                g = (Group)groups.get(inputKey);
  +                g = (Group) groups.get(inputKey);
               }
               else if (create)
               {
                   g = TurbineIntake.getGroup(groupName);
                   groups.put(inputKey, g);
  -                g.init(key, data);
  +                g.init(key, pp);
               }
   
               return g;
           }
   
  -
  -      /**
  -       * maps an Intake Group to the values from a Retrievable object.
  -       *
  -       * @param obj       A retrievable object
  -       *
  -       * @return          an Intake Group
  -       *
  -       */
  -
  +        /**
  +         * maps an Intake Group to the values from a Retrievable object.
  +         *
  +         * @param obj A retrievable object
  +         * @return an Intake Group
  +         */
           public Group mapTo(Retrievable obj)
  -            throws Exception
  +                throws IntakeException
           {
               Group g = null;
   
               try
               {
                   String inputKey = TurbineIntake.getGroupKey(groupName)
  -                    + obj.getQueryKey();
  +                        + obj.getQueryKey();
                   if (groups.containsKey(inputKey))
                   {
  -                    g = (Group)groups.get(inputKey);
  +                    g = (Group) groups.get(inputKey);
                   }
                   else
                   {
  @@ -295,44 +334,77 @@
                   }
                   return g.init(obj);
               }
  -            catch(Exception e)
  +            catch (Exception e)
               {
  -                Log.error(e);
  +                log.error(e);
               }
   
               return null;
           }
       }
   
  +    /**
  +     * get a specific group
  +     */
  +    public PullHelper get(String groupName)
  +            throws IntakeException
  +    {
  +        return (PullHelper) pullMap.get(groupName);
  +    }
   
  -    public Object get(String groupName)
  -        throws Exception
  +    /**
  +     * Get a specific group
  +     *
  +     * @param throwExceptions if false, exceptions will be supressed.
  +     * @throws IntakeException could not retrieve group
  +     */
  +    public PullHelper get(String groupName, boolean throwExceptions)
  +            throws IntakeException
       {
  -        return pullMap.get(groupName);
  +        return (PullHelper) pullMap.get(groupName);
       }
   
  +    /**
  +     * Loops through all of the Groups and checks to see if
  +     * the data within the Group is valid.
  +     */
       public boolean isAllValid()
       {
           boolean allValid = true;
           Iterator iter = groups.values().iterator();
           while (iter.hasNext())
           {
  -            Group group = (Group)iter.next();
  +            Group group = (Group) iter.next();
               allValid &= group.isAllValid();
           }
           return allValid;
       }
   
  +    /**
  +     * Get a specific group by name and key.
  +     */
       public Group get(String groupName, String key)
  -        throws Exception
  +            throws IntakeException
       {
  -        return ((PullHelper)get(groupName)).setKey(key);
  +        if (groupName == null)
  +        {
  +            throw new IntakeException("Intake.get: groupName == null");
  +        }
  +        if (key == null)
  +        {
  +            throw new IntakeException("Intake.get: key == null");
  +        }
  +        return ((PullHelper) get(groupName)).setKey(key);
       }
   
  +    /**
  +     * Get a specific group by name and key. Also specify
  +     * whether or not you want to create a new group.
  +     */
       public Group get(String groupName, String key, boolean create)
  -        throws Exception
  +            throws IntakeException
       {
  -        return ((PullHelper)get(groupName)).setKey(key, create);
  +        return ((PullHelper) get(groupName)).setKey(key, create);
       }
   
       /**
  @@ -344,7 +416,15 @@
       {
           groups.remove(group.getObjectKey());
           group.removeFromRequest();
  -        TurbineIntake.releaseGroup(group);
  +
  +        try
  +        {
  +            TurbineIntake.releaseGroup(group);
  +        }
  +        catch (TurbineException se)
  +        {
  +            log.error("Tried to release unknown group " + group.getIntakeGroupName());
  +        }
       }
   
       /**
  @@ -357,7 +437,7 @@
           Object[] allGroups = groups.values().toArray();
           for (int i = allGroups.length - 1; i >= 0; i--)
           {
  -            Group group = (Group)allGroups[i];
  +            Group group = (Group) allGroups[i];
               remove(group);
           }
       }
  @@ -401,19 +481,28 @@
           Iterator iter = groups.values().iterator();
           while (iter.hasNext())
           {
  -            Group g = (Group)iter.next();
  -            TurbineIntake.releaseGroup(g);
  +            Group g = (Group) iter.next();
  +
  +            try
  +            {
  +                TurbineIntake.releaseGroup(g);
  +            }
  +            catch (TurbineException se)
  +            {
  +                log.error("Tried to release unknown group " + g.getIntakeGroupName());
  +            }
           }
   
           groups.clear();
           declaredGroups.clear();
  -        data = null;
  +        pp = null;
   
           disposed = true;
       }
   
       /**
        * Checks whether the recyclable has been disposed.
  +     *
        * @return true, if the recyclable is disposed.
        */
       public boolean isDisposed()
  
  
  
  1.2       +28 -85    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/TurbineIntake.java
  
  Index: TurbineIntake.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/TurbineIntake.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TurbineIntake.java	16 Aug 2001 05:08:55 -0000	1.1
  +++ TurbineIntake.java	3 Jan 2003 07:20:43 -0000	1.2
  @@ -54,10 +54,11 @@
    * <http://www.apache.org/>.
    */
   
  +import java.beans.IntrospectionException;
   import java.lang.reflect.Method;
  -import org.apache.turbine.services.intake.model.Group;
  -import org.apache.turbine.util.TurbineException;
  +
   import org.apache.turbine.services.TurbineServices;
  +import org.apache.turbine.services.intake.model.Group;
   
   /**
    * This is a Facade class for IntakeService.
  @@ -67,6 +68,7 @@
    * the settings in TurbineResources.
    *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public abstract class TurbineIntake
  @@ -77,109 +79,44 @@
        *
        * @param groupName the name of the group.
        * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  +     * @throws IntakeException if recycling fails.
        */
       public static Group getGroup(String groupName)
  -        throws TurbineException
  +            throws IntakeException
       {
  +        if (groupName == null)
  +        {
  +            throw new IntakeException(
  +                    "TurbineIntake.getGroup(groupName) is null");
  +        }
           return getService().getGroup(groupName);
       }
  -    /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty and
  -     * then initialize it using the ParameterParser looking for
  -     * a NEW id.
  -     *
  -     * @param groupName the name of the group.
  -     * @param pp the request parameters that may contain matching keys
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  -     * /
  -    public static Group getGroup(String groupName, ParameterParser pp)
  -        throws Exception
  -    {
  -        return getService().getGroup(groupName, pp);
  -    }
  -
  -    /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty and
  -     * then initialize it using the ParameterParser looking for id.
  -     *
  -     * @param groupName the name of the group.
  -     * @param pp the request parameters that may contain matching keys
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  -     * /
  -    public static Group getGroup(String groupName,
  -                                 ParameterParser pp, String id)
  -        throws Exception
  -    {
  -        return getService().getGroup(groupName, pp, id);
  -    }
  -    */
   
       /**
        * Puts a group back to the pool.
        * @param instance the object instance to recycle.
  -     * @return true if the instance was accepted.
  -     */
  -    public static boolean releaseGroup(Group instance)
  -    {
  -        return getService().releaseGroup(instance);
  -    }
  -
  -    /**
  -     * Gets the capacity of the pool for a named group.
  -     *
  -     * @param groupName the name of the group.
  +     * @throws IntakeException A non existant group was passed
        */
  -    public static int getCapacity(String groupName)
  +    public static void releaseGroup(Group instance)
  +            throws IntakeException
       {
  -        return getService().getCapacity(groupName);
  -    }
  -
  -    /**
  -     * Sets the capacity of the pool for a named group.
  -     * Note that the pool will be cleared after the change.
  -     *
  -     * @param groupName the name of the group.
  -     * @param capacity the new capacity.
  -     */
  -    public static void setCapacity(String groupName, int capacity)
  -    {
  -        getService().setCapacity(groupName, capacity);
  +        getService().releaseGroup(instance);
       }
   
       /**
        * Gets the current size of the pool for a named group.
        *
        * @param groupName the name of the group.
  +     * @return the current pool size
  +     * @throws IntakeException A non existant group was passed
        */
       public static int getSize(String groupName)
  +            throws IntakeException
       {
           return getService().getSize(groupName);
       }
   
       /**
  -     * Clears instances of a named group from the pool.
  -     *
  -     * @param groupName the name of the group.
  -     */
  -    public static void clearPool(String groupName)
  -    {
  -        getService().clearPool(groupName);
  -    }
  -
  -    /**
  -     * Clears all instances from the pool.
  -     */
  -    public static void clearPool()
  -    {
  -        getService().clearPool();
  -    }
  -
  -    /**
        * Names of all the defined groups.
        *
        * @return array of names.
  @@ -203,7 +140,7 @@
       /**
        * Gets the group name given its key.
        *
  -     * @param the the key.
  +     * @param groupKey the key.
        * @return groupName the name of the group.
        */
       public static String getGroupName(String groupKey)
  @@ -217,8 +154,11 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the setter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
       public static Method getFieldSetter(String className, String propName)
  +            throws IntrospectionException, ClassNotFoundException
       {
           return getService().getFieldSetter(className, propName);
       }
  @@ -229,8 +169,11 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the getter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
       public static Method getFieldGetter(String className, String propName)
  +            throws IntrospectionException, ClassNotFoundException
       {
           return getService().getFieldGetter(className, propName);
       }
  @@ -243,8 +186,8 @@
        */
       private static IntakeService getService()
       {
  -        return (IntakeService)TurbineServices
  -            .getInstance().getService(IntakeService.SERVICE_NAME);
  +        return (IntakeService) TurbineServices
  +                .getInstance().getService(IntakeService.SERVICE_NAME);
       }
   
   }
  
  
  
  1.7       +438 -369  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/TurbineIntakeService.java
  
  Index: TurbineIntakeService.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/TurbineIntakeService.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TurbineIntakeService.java	23 Dec 2002 22:52:27 -0000	1.6
  +++ TurbineIntakeService.java	3 Jan 2003 07:20:43 -0000	1.7
  @@ -53,6 +53,8 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    */
  +
  +import java.beans.IntrospectionException;
   import java.beans.PropertyDescriptor;
   import java.io.File;
   import java.io.FileInputStream;
  @@ -63,38 +65,43 @@
   import java.io.OutputStream;
   import java.lang.reflect.Method;
   import java.util.HashMap;
  +import java.util.HashSet;
   import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
   import java.util.Properties;
  +import java.util.Set;
  +import java.util.Vector;
   import javax.servlet.ServletConfig;
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.commons.pool.KeyedObjectPool;
  +import org.apache.commons.pool.KeyedPoolableObjectFactory;
  +import org.apache.commons.pool.impl.StackKeyedObjectPool;
   import org.apache.turbine.Turbine;
  -import org.apache.turbine.om.OMTool;
   import org.apache.turbine.services.InitializationException;
   import org.apache.turbine.services.TurbineBaseService;
   import org.apache.turbine.services.intake.model.Group;
   import org.apache.turbine.services.intake.transform.XmlToAppData;
   import org.apache.turbine.services.intake.xmlmodel.AppData;
   import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
  -import org.apache.turbine.util.Log;
   import org.apache.turbine.util.ServletUtils;
  -import org.apache.turbine.util.TurbineException;
  -import org.apache.turbine.util.pool.BoundedBuffer;
  -import org.apache.turbine.util.pool.Recyclable;
   
   /**
    * This service provides access to input processing objects based
    * on an XML specification.
    *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class TurbineIntakeService
  -    extends TurbineBaseService
  -    implements IntakeService
  +        extends TurbineBaseService
  +        implements IntakeService
   {
  -    /** Array of group names. */
  -    private String[] groupNames;
  +    /** Map of groupNames -> appData elements */
  +    private Map groupNames;
   
       /** The cache of group names. */
       private Map groupNameMap;
  @@ -108,38 +115,32 @@
       /** The cache of property setters. */
       private Map setterMap;
   
  -    /** Keep a OMTool to be able to retrieve objects */
  -    private OMTool omTool;
  -
  -    /** The top element of the object tree */
  -    private AppData appData;
  +    /** AppData -> keyed Pools Map */
  +    private Map keyedPools;
   
  -    /**
  -     * The pool repository, one pool for each class.
  -     */
  -    private HashMap poolRepository = new HashMap();
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(TurbineIntakeService.class);
   
       // a couple integers for a switch statement
       private static final int GETTER = 0;
       private static final int SETTER = 1;
   
       /**
  -     * Constructor.
  +     * Constructor. All Components need a public no argument constructor
  +     * to be a legal Component.
        */
       public TurbineIntakeService()
       {
       }
   
       /**
  -     * Initializes the Intake Service.
  -     * This is a zero parameter variant which queries the Turbine Servlet
  -     * for its config.
  +     * Called the first time the Service is used.
        *
        * @throws InitializationException Something went wrong in the init
        *         stage
  -     */ 
  +     */
       public void init()
  -        throws InitializationException
  +            throws InitializationException
       {
           ServletConfig conf = Turbine.getTurbineServletConfig();
           init(conf);
  @@ -152,83 +153,170 @@
        * @deprecated use init() instead.
        */
       public void init(ServletConfig config)
  -        throws InitializationException
  +            throws InitializationException
       {
  -        Properties props = getProperties();
  -        String xmlPath = props.getProperty(XML_PATH);
  -        if ( xmlPath == null )
  -        {
  -            String pathError =
  -                "Path to intake.xml was not specified.  Check that the" +
  -                " property exists in TR.props and was loaded.";
  -            Log.error(pathError);
  -            throw new InitializationException(pathError);
  +        Vector defaultXmlPathes = new Vector();
  +        defaultXmlPathes.add(XML_PATH_DEFAULT);
  +
  +        List xmlPathes = getConfiguration()
  +                .getVector(XML_PATH, defaultXmlPathes);
  +
  +        Map appDataElements = null;
  +
  +        String serialDataPath = getConfiguration()
  +                .getString(SERIAL_XML, SERIAL_XML_DEFAULT);
  +
  +        if (!serialDataPath.equalsIgnoreCase("none"))
  +        {
  +            serialDataPath = ServletUtils.expandRelative(config, serialDataPath);
           }
  -        //!! need a constant
  -        String appDataPath = "/WEB-INF/appData.ser";
  -        try
  +        else
  +        {
  +            serialDataPath = null;
  +        }
  +
  +        log.debug("Path for serializing: " + serialDataPath);
  +
  +        groupNames = new HashMap();
  +        groupKeyMap = new HashMap();
  +        groupNameMap = new HashMap();
  +        getterMap = new HashMap();
  +        setterMap = new HashMap();
  +        keyedPools = new HashMap();
  +
  +        if (xmlPathes == null)
  +        {
  +            String LOAD_ERROR = "No pathes for XML files were specified. " +
  +                    "Check that the property exists in " +
  +                    "TurbineResources.props and were loaded.";
  +
  +            log.error(LOAD_ERROR);
  +            throw new InitializationException(LOAD_ERROR);
  +        }
  +
  +        Set xmlFiles = new HashSet();
  +
  +        long timeStamp = 0;
  +
  +        for (Iterator it = xmlPathes.iterator(); it.hasNext();)
           {
  -            // If possible, transform paths to be webapp root relative.
  -            xmlPath = ServletUtils.expandRelative(config, xmlPath);
  -            appDataPath = ServletUtils.expandRelative(config, appDataPath);
  -            File serialAppData = new File(appDataPath);
  +            // Files are webapp.root relative
  +            String xmlPath = ServletUtils.expandRelative(config, (String) it.next());
               File xmlFile = new File(xmlPath);
  -            if ( serialAppData.exists()
  -                 && serialAppData.lastModified() > xmlFile.lastModified() )
  +
  +            log.debug("Path for XML File: " + xmlFile);
  +
  +            if (!xmlFile.canRead())
  +            {
  +                String READ_ERR = "Could not read input file " + xmlPath;
  +
  +                log.error(READ_ERR);
  +                throw new InitializationException(READ_ERR);
  +            }
  +
  +            xmlFiles.add(xmlPath);
  +
  +            log.debug("Added " + xmlPath + " as File to parse");
  +
  +            // Get the timestamp of the youngest file to be compared with
  +            // a serialized file. If it is younger than the serialized file,
  +            // then we have to parse the XML anyway.
  +            timeStamp =
  +                    (xmlFile.lastModified() > timeStamp) ? xmlFile.lastModified() : timeStamp;
  +        }
  +
  +        Map serializedMap = loadSerialized(serialDataPath, timeStamp);
  +
  +        if (serializedMap != null)
  +        {
  +            // Use the serialized data as XML groups. Don't parse.
  +            appDataElements = serializedMap;
  +            log.debug("Using the serialized map");
  +        }
  +        else
  +        {
  +            // Parse all the given XML files
  +            appDataElements = new HashMap();
  +
  +            for (Iterator it = xmlFiles.iterator(); it.hasNext();)
               {
  -                InputStream in = null;
  +                String xmlPath = (String) it.next();
  +                AppData appData = null;
  +
  +                log.debug("Now parsing: " + xmlPath);
                   try
                   {
  -                    in = new FileInputStream(serialAppData);
  -                    ObjectInputStream p = new ObjectInputStream(in);
  -                    appData = (AppData)p.readObject();
  +                    XmlToAppData xmlApp = new XmlToAppData();
  +                    appData = xmlApp.parseFile(xmlPath);
                   }
                   catch (Exception e)
                   {
  -                    // We got a corrupt file for some reason
  -                    writeAppData(xmlPath, appDataPath, serialAppData);
  -                }
  -                finally
  -                {
  -                    if (in != null)
  -                    {
  -                        in.close();
  -                    }
  +                    log.error("Could not parse XML file " + xmlPath, e);
  +
  +                    throw new InitializationException("Could not parse XML file " +
  +                            xmlPath, e);
                   }
  +
  +                appDataElements.put(appData, xmlPath);
  +                log.debug("Saving appData for " + xmlPath);
               }
  -            else
  +
  +            saveSerialized(serialDataPath, appDataElements);
  +        }
  +
  +        try
  +        {
  +            for (Iterator it = appDataElements.keySet().iterator(); it.hasNext();)
               {
  -                writeAppData(xmlPath, appDataPath, serialAppData);
  -            }
  +                AppData appData = (AppData) it.next();
  +
  +                String pkg = appData.getBasePackage();
  +
  +                int maxPooledGroups = 0;
  +                List glist = appData.getGroups();
   
  -            groupNames = new String[appData.getGroups().size()];
  -            groupKeyMap = new HashMap();
  -            groupNameMap = new HashMap();
  -            getterMap = new HashMap();
  -            setterMap = new HashMap();
  -            // omTool = new OMTool();
  -            String pkg = appData.getBasePackage();
  -
  -            List glist = appData.getGroups();
  -            for ( int i=glist.size()-1; i>=0; i-- )
  -            {
  -                XmlGroup g = (XmlGroup)glist.get(i);
  -                String groupName = g.getName();
  -                groupNames[i] = groupName;
  -                groupKeyMap.put(groupName, g.getKey());
  -                groupNameMap.put(g.getKey(), groupName);
  -
  -                List classNames = g.getMapToObjects();
  -                Iterator iter2 = classNames.iterator();
  -                while (iter2.hasNext())
  +                String groupPrefix = appData.getGroupPrefix();
  +
  +                for (int i = glist.size() - 1; i >= 0; i--)
                   {
  -                    String className = (String)iter2.next();
  -                    if ( !getterMap.containsKey(className) )
  +                    XmlGroup g = (XmlGroup) glist.get(i);
  +                    String groupName = g.getName();
  +
  +                    boolean registerUnqualified = registerGroup(groupName, g, appData, true);
  +
  +                    if (!registerUnqualified)
  +                    {
  +                        log.info("Ignored redefinition of Group " + groupName
  +                                + " or Key " + g.getKey()
  +                                + " from " + appDataElements.get(appData));
  +                    }
  +
  +                    if (groupPrefix != null)
                       {
  -                        getterMap.put(className, new HashMap());
  -                        setterMap.put(className, new HashMap());
  +                        StringBuffer qualifiedName = new StringBuffer();
  +                        qualifiedName.append(groupPrefix)
  +                                .append(":")
  +                                .append(groupName);
  +
  +                        // Add the fully qualified group name. Do _not_ check for
  +                        // the existence of the key if the unqualified registration succeeded
  +                        // (because then it was added by the registerGroup above).
  +                        if (!registerGroup(qualifiedName.toString(), g, appData, !registerUnqualified))
  +                        {
  +                            log.error("Could not register fully qualified name " + qualifiedName
  +                                    + ", maybe two XML files have the same prefix. Ignoring it.");
  +                        }
                       }
  +
  +                    maxPooledGroups =
  +                            Math.max(maxPooledGroups,
  +                                    Integer.parseInt(g.getPoolCapacity()));
  +
                   }
  +
  +                KeyedPoolableObjectFactory factory =
  +                        new Group.GroupFactory(appData);
  +                keyedPools.put(appData, new StackKeyedObjectPool(factory, maxPooledGroups));
               }
   
               setInit(true);
  @@ -236,298 +324,315 @@
           catch (Exception e)
           {
               throw new InitializationException(
  -                "TurbineIntakeService failed to initialize", e);
  +                    "TurbineIntakeService failed to initialize", e);
           }
       }
   
  -
       /**
  -     * This method writes the appData file into Objects and stores
  -     * the information into this classes appData property
  +     * Registers a given group name in the system
  +     *
  +     * @param groupName The name to register the group under
  +     * @param group The XML Group to register in
  +     * @param appData The app Data object where the group can be found
  +     * @param checkKey Whether to check if the key also exists.
  +     *
  +     * @return true if successful, false if not
        */
  -    private void writeAppData(String xmlPath, String appDataPath, File serialAppData)
  -        throws Exception
  +    private boolean registerGroup(String groupName, XmlGroup group, AppData appData, boolean checkKey)
       {
  -        XmlToAppData xmlApp = new XmlToAppData();
  -        appData = xmlApp.parseFile(xmlPath);
  -        OutputStream out = null;
  -        InputStream in = null;
  -        try
  +        if (groupNames.keySet().contains(groupName))
           {
  -            // write the appData file out
  -            out = new FileOutputStream(serialAppData);
  -            ObjectOutputStream p = new ObjectOutputStream(out);
  -            p.writeObject(appData);
  -            p.flush();
  +            // This name already exists.
  +            return false;
  +        }
   
  -            // read the file back in. for some reason on OSX 10.1
  -            // this is necessary.
  -            in = new FileInputStream(serialAppData);
  -            ObjectInputStream pin = new ObjectInputStream(in);
  -            appData = (AppData)pin.readObject();
  +        boolean keyExists = groupNameMap.keySet().contains(group.getKey());
  +
  +        if (checkKey && keyExists)
  +        {
  +            // The key for this package is already registered for another group
  +            return false;
           }
  -        catch (Exception e)
  +
  +        groupNames.put(groupName, appData);
  +
  +        groupKeyMap.put(groupName, group.getKey());
  +
  +        if (!keyExists)
           {
  -            Log.info(
  -                "Intake initialization could not be serialized " +
  -                "because writing to " + appDataPath + " was not " +
  -                "allowed.  This will require that the xml file be " +
  -                "parsed when restarting the application.");
  +            // This key does not exist. Add it to the hash.
  +            groupNameMap.put(group.getKey(), groupName);
           }
  -        finally
  +
  +        List classNames = group.getMapToObjects();
  +        Iterator iter2 = classNames.iterator();
  +        while (iter2.hasNext())
           {
  -            if (out != null)
  -            {
  -                out.close();
  -            }
  -            if (in != null)
  +            String className = (String) iter2.next();
  +            if (!getterMap.containsKey(className))
               {
  -                in.close();
  +                getterMap.put(className, new HashMap());
  +                setterMap.put(className, new HashMap());
               }
           }
  +        return true;
       }
   
       /**
  -     * An inner class for group specific pools.
  +     * Tries to load a serialized Intake Group file. This
  +     * can reduce the startup time of Turbine.
  +     *
  +     * @param serialDataPath The path of the File to load.
  +     *
  +     * @return A map with appData objects loaded from the file
  +     *          or null if the map could not be loaded.
        */
  -    private class PoolBuffer
  +    private Map loadSerialized(String serialDataPath, long timeStamp)
       {
  -        /**
  -         * A buffer for class instances.
  -         */
  -        private BoundedBuffer pool;
  -
  -        /**
  -         * A cache for recycling methods.
  -         */
  -        private HashMap recyclers;
  -
  -        /**
  -         * Contructs a new pool buffer with a specific capacity.
  -         *
  -         * @param capacity a capacity.
  -         */
  -        public PoolBuffer(int capacity)
  -        {
  -            pool = new BoundedBuffer(capacity);
  -        }
  -
  -        /**
  -         * Polls for an instance from the pool.
  -         *
  -         * @return an instance or null.
  -         */
  -        public Group poll()
  -            throws TurbineException
  -        {
  -            Group instance = (Group)pool.poll();
  -            if ((instance != null) &&
  -                (instance instanceof Recyclable))
  -            {
  -                try
  -                {
  -                    ((Recyclable) instance).recycle();
  -                }
  -                catch (Exception x)
  -                {
  -                    throw new TurbineException("Recycling failed for " +
  -                        instance.getClass().getName(),x);
  -                }
  -            }
  -            return instance;
  +        log.debug("Entered loadSerialized("
  +                + serialDataPath + ", "
  +                + timeStamp + ")");
  +
  +        if (serialDataPath == null)
  +        {
  +            return null;
           }
   
  -        /**
  -         * Offers an instance to the pool.
  -         *
  -         * @param instance an instance.
  -         */
  -        public boolean offer(Group instance)
  +        File serialDataFile = new File(serialDataPath);
  +
  +        if (!serialDataFile.exists())
           {
  -            try
  +            log.info("No serialized file found, parsing XML");
  +            return null;
  +        }
  +
  +        if (serialDataFile.lastModified() <= timeStamp)
  +        {
  +            log.info("serialized file too old, parsing XML");
  +            return null;
  +        }
  +
  +        InputStream in = null;
  +        Map serialData = null;
  +
  +        try
  +        {
  +            in = new FileInputStream(serialDataFile);
  +            ObjectInputStream p = new ObjectInputStream(in);
  +            Object o = p.readObject();
  +
  +            if (o instanceof Map)
               {
  -                ((Recyclable) instance).dispose();
  +                serialData = (Map) o;
               }
  -            catch (Exception x)
  +            else
               {
  -                return false;
  +                // Maybe an old file from intake. Ignore it and try to delete
  +                log.info("serialized object is not an intake map, ignoring");
  +                in.close();
  +                in = null;
  +                serialDataFile.delete(); // Try to delete the file lying around
               }
  -            return pool.offer(instance);
           }
  -
  -        /**
  -         * Returns the capacity of the pool.
  -         *
  -         * @return the capacity.
  -         */
  -        public int capacity()
  +        catch (Exception e)
           {
  -            return pool.capacity();
  -        }
  +            log.error("Serialized File could not be read.", e);
   
  -        /**
  -         * Returns the size of the pool.
  -         *
  -         * @return the size.
  -         */
  -        public int size()
  +            // We got a corrupt file for some reason.
  +            // Null out serialData to be sure
  +            serialData = null;
  +        }
  +        finally
           {
  -            return pool.size();
  +            // Could be null if we opened a file, didn't find it to be a
  +            // Map object and then nuked it away.
  +            try
  +            {
  +                if (in != null)
  +                {
  +                    in.close();
  +                }
  +            }
  +            catch (Exception e)
  +            {
  +                log.error("Exception while closing file", e);
  +            }
           }
  +
  +        log.info("Loaded serialized map object, ignoring XML");
  +        return serialData;
       }
   
       /**
  -     * Gets an instance of a named group either from the pool
  -     * or by calling the Factory Service if the pool is empty.
  +     * Writes a parsed XML map with all the appData groups into a
  +     * file. This will speed up loading time when you restart the
  +     * Intake Service because it will only unserialize this file instead
  +     * of reloading all of the XML files
        *
  -     * @param groupName the name of the group.
  -     * @return a Group instance.
  -     * @throws TurbineException if recycling fails.
  +     * @param serialDataPath  The path of the file to write to
  +     * @param appDataElements A Map containing all of the XML parsed appdata elements
        */
  -    public Group getGroup(String groupName)
  -            throws TurbineException
  +    private void saveSerialized(String serialDataPath, Map appDataElements)
       {
  -        Group instance = (Group)pollInstance(groupName);
  -        if ( instance == null )
  +
  +        log.debug("Entered saveSerialized("
  +                + serialDataPath + ", appDataElements)");
  +
  +        if (serialDataPath == null)
  +        {
  +            return;
  +        }
  +
  +        File serialData = new File(serialDataPath);
  +
  +        try
  +        {
  +            serialData.createNewFile();
  +            serialData.delete();
  +        }
  +        catch (Exception e)
  +        {
  +            log.info("Could not create serialized file " + serialDataPath
  +                    + ", not serializing the XML data");
  +            return;
  +        }
  +
  +        OutputStream out = null;
  +        InputStream in = null;
  +
  +        try
  +        {
  +            // write the appData file out
  +            out = new FileOutputStream(serialDataPath);
  +            ObjectOutputStream pout = new ObjectOutputStream(out);
  +            pout.writeObject(appDataElements);
  +            pout.flush();
  +
  +            // read the file back in. for some reason on OSX 10.1
  +            // this is necessary.
  +            in = new FileInputStream(serialDataPath);
  +            ObjectInputStream pin = new ObjectInputStream(in);
  +            Map dummy = (Map) pin.readObject();
  +
  +            log.debug("Serializing successful");
  +        }
  +        catch (Exception e)
  +        {
  +            log.info("Could not write serialized file to " + serialDataPath
  +                    + ", not serializing the XML data");
  +        }
  +        finally
           {
               try
               {
  -                instance = new Group(appData.getGroup(groupName));
  +                if (out != null)
  +                {
  +                    out.close();
  +                }
  +                if (in != null)
  +                {
  +                    in.close();
  +                }
               }
               catch (Exception e)
               {
  -                throw new TurbineException(e);
  +                log.error("Exception while closing file", e);
               }
           }
  -        return instance;
       }
   
  -
       /**
  -     * Puts a Group back to the pool.
  +     * Gets an instance of a named group either from the pool
  +     * or by calling the Factory Service if the pool is empty.
        *
  -     * @param instance the object instance to recycle.
  -     * @return true if the instance was accepted.
  +     * @param groupName the name of the group.
  +     * @return a Group instance.
  +     * @throws IntakeException if recycling fails.
        */
  -    public boolean releaseGroup(Group instance)
  +    public Group getGroup(String groupName)
  +            throws IntakeException
       {
  -        if (instance != null)
  +        Group group = null;
  +
  +        AppData appData = (AppData) groupNames.get(groupName);
  +
  +        if (groupName == null)
           {
  -            HashMap repository = poolRepository;
  -            String name = instance.getIntakeGroupName();
  -            PoolBuffer pool = (PoolBuffer) repository.get(name);
  -            if (pool == null)
  -            {
  -                pool = new PoolBuffer(instance.getPoolCapacity());
  -                repository = (HashMap) repository.clone();
  -                repository.put(name,pool);
  -                poolRepository = repository;
  -            }
  -            return pool.offer(instance);
  +            throw new IntakeException(
  +                    "Intake TurbineIntakeService.getGroup(groupName) is null");
           }
  -        else
  +        if (appData == null)
           {
  -            return false;
  +            throw new IntakeException(
  +                    "Intake TurbineIntakeService.getGroup(groupName): No XML definition for Group "
  +                    + groupName + " found");
  +        }
  +        try
  +        {
  +            group = (Group) ((KeyedObjectPool) keyedPools.get(appData)).borrowObject(groupName);
           }
  +        catch (Exception e)
  +        {
  +            throw new IntakeException("Could not get group " + groupName, e);
  +        }
  +        return group;
       }
   
       /**
  -     * Gets the capacity of the pool for a named group.
  +     * Puts a Group back to the pool.
        *
  -     * @param name the name of the class.
  +     * @param instance the object instance to recycle.
  +     *
  +     * @throws IntakeException The passed group name does not exist.
        */
  -    public int getCapacity(String name)
  +    public void releaseGroup(Group instance)
  +            throws IntakeException
       {
  -        int capacity = DEFAULT_POOL_CAPACITY;
  -        PoolBuffer pool = (PoolBuffer) poolRepository.get(name);
  -        if ( pool == null )
  +        if (instance != null)
           {
  +            String groupName = instance.getIntakeGroupName();
  +            AppData appData = (AppData) groupNames.get(groupName);
  +
  +            if (appData == null)
  +            {
  +                throw new IntakeException(
  +                        "Intake TurbineIntakeService.releaseGroup(groupName): "
  +                        + "No XML definition for Group " + groupName + " found");
  +            }
  +
               try
               {
  -                capacity = Integer
  -                    .parseInt(appData.getGroup(name).getPoolCapacity());
  +                ((KeyedObjectPool) keyedPools.get(appData)).returnObject(groupName, instance);
  +            }
  +            catch (Exception e)
  +            {
  +                new IntakeException("Could not get group " + groupName, e);
               }
  -            catch (NumberFormatException nfe) {}
  -        }
  -        else
  -        {
  -            capacity = pool.capacity();
           }
  -
  -        return capacity;
  -    }
  -
  -    /**
  -     * Sets the capacity of the pool for a group.
  -     * Note that the pool will be cleared after the change.
  -     *
  -     * @param name the name of the group.
  -     * @param capacity the new capacity.
  -     */
  -    public void setCapacity(String name,
  -                            int capacity)
  -    {
  -        HashMap repository = poolRepository;
  -        repository = repository != null ?
  -            (HashMap) repository.clone() : new HashMap();
  -        repository.put(name,new PoolBuffer(capacity));
  -        poolRepository = repository;
       }
   
       /**
        * Gets the current size of the pool for a group.
        *
  -     * @param name the name of the group.
  -     */
  -    public int getSize(String name)
  -    {
  -        PoolBuffer pool = (PoolBuffer) poolRepository.get(name);
  -        return pool != null ? pool.size() : 0;
  -    }
  -
  -    /**
  -     * Clears instances of a group from the pool.
  +     * @param groupName the name of the group.
        *
  -     * @param name the name of the group.
  +     * @throws IntakeException The passed group name does not exist.
        */
  -    public void clearPool(String name)
  +    public int getSize(String groupName)
  +            throws IntakeException
       {
  -        throw new Error("Not implemented");
  -        /* FIXME!! We need to worry about objects that are checked out
  -
  -        HashMap repository = poolRepository;
  -        if (repository.get(name) != null)
  +        AppData appData = (AppData) groupNames.get(groupName);
  +        if (appData == null)
           {
  -            repository = (HashMap) repository.clone();
  -            repository.remove(name);
  -            poolRepository = repository;
  +            throw new IntakeException(
  +                    "Intake TurbineIntakeService.Size(groupName): No XML definition for Group "
  +                    + groupName + " found");
           }
  -        */
  -    }
   
  -    /**
  -     * Clears all instances from the pool.
  -     */
  -    public void clearPool()
  -    {
  -        throw new Error("Not implemented");
  -        /* FIXME!! We need to worry about objects that are checked out
  -        poolRepository = new HashMap();
  -        */
  -    }
  +        KeyedObjectPool kop = (KeyedObjectPool) keyedPools.get(groupName);
   
  -    /**
  -     * Polls and recycles an object of the named group from the pool.
  -     *
  -     * @param groupName the name of the group.
  -     * @return the object or null.
  -     * @throws TurbineException if recycling fails.
  -     */
  -    private Object pollInstance(String groupName)
  -        throws TurbineException
  -    {
  -        PoolBuffer pool = (PoolBuffer) poolRepository.get(groupName);
  -        return pool != null ? pool.poll() : null;
  +        return kop.getNumActive(groupName)
  +                + kop.getNumIdle(groupName);
       }
   
       /**
  @@ -537,7 +642,7 @@
        */
       public String[] getGroupNames()
       {
  -        return groupNames;
  +        return (String[]) groupNames.keySet().toArray(new String[0]);
       }
   
       /**
  @@ -548,18 +653,18 @@
        */
       public String getGroupKey(String groupName)
       {
  -        return (String)groupKeyMap.get(groupName);
  +        return (String) groupKeyMap.get(groupName);
       }
   
       /**
        * Gets the group name given its key.
        *
  -     * @param the the key.
  +     * @param groupKey the key.
        * @return groupName the name of the group.
        */
       public String getGroupName(String groupKey)
       {
  -        return (String)groupNameMap.get(groupKey);
  +        return (String) groupNameMap.get(groupKey);
       }
   
       /**
  @@ -568,47 +673,29 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the setter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
       public Method getFieldSetter(String className, String propName)
  +            throws ClassNotFoundException, IntrospectionException
       {
  -        Map settersForClassName = (Map)setterMap.get(className);
  -        Method setter = (Method)settersForClassName.get(propName);
  +        Map settersForClassName = (Map) setterMap.get(className);
  +        Method setter = (Method) settersForClassName.get(propName);
   
  -        if ( setter == null )
  +        if (setter == null)
           {
               PropertyDescriptor pd = null;
  -            synchronized(setterMap)
  -            {
  -                try
  -                {
  -                    pd = new PropertyDescriptor(propName,
  -                                                Class.forName(className));
  -                    setter = pd.getWriteMethod();
  -                    ((Map)setterMap.get(className)).put(propName, setter);
  -                    if ( setter == null )
  -                    {
  -                        Log.error("Intake: setter for '" + propName
  -                                  + "' in class '" + className
  -                                  + "' could not be found.");
  -                    }
  -                }
  -                catch (Exception e)
  -                {
  -                    Log.error(e);
  -                }
  -            }
  -            // we have already completed the reflection on the getter, so
  -            // save it so we do not have to repeat
  -            synchronized(getterMap)
  +            synchronized (setterMap)
               {
  -                try
  -                {
  -                    Method getter = pd.getReadMethod();
  -                    ((Map)getterMap.get(className)).put(propName, getter);
  -                }
  -                catch (Exception e)
  -                {
  -                    Log.error(e);
  +                pd = new PropertyDescriptor(propName,
  +                        Class.forName(className));
  +                setter = pd.getWriteMethod();
  +                ((Map) setterMap.get(className)).put(propName, setter);
  +                if (setter == null)
  +                {
  +                    log.error("Intake: setter for '" + propName
  +                            + "' in class '" + className
  +                            + "' could not be found.");
                   }
               }
           }
  @@ -621,47 +708,29 @@
        * @param className the name of the object.
        * @param propName the name of the property.
        * @return the getter.
  +     * @throws ClassNotFoundException
  +     * @throws IntrospectionException
        */
       public Method getFieldGetter(String className, String propName)
  +            throws ClassNotFoundException, IntrospectionException
       {
  -        Map gettersForClassName = (Map)getterMap.get(className);
  -        Method getter = (Method)gettersForClassName.get(propName);
  +        Map gettersForClassName = (Map) getterMap.get(className);
  +        Method getter = (Method) gettersForClassName.get(propName);
   
  -        if ( getter == null )
  +        if (getter == null)
           {
               PropertyDescriptor pd = null;
  -            synchronized(getterMap)
  +            synchronized (getterMap)
               {
  -                try
  -                {
  -                    pd = new PropertyDescriptor(propName,
  -                                                Class.forName(className));
  -                    getter = pd.getReadMethod();
  -                    ((Map)getterMap.get(className)).put(propName, getter);
  -                    if ( getter == null )
  -                    {
  -                        Log.error("Intake: getter for '" + propName
  -                                  + "' in class '" + className
  -                                  + "' could not be found.");
  -                    }
  -                }
  -                catch (Exception e)
  -                {
  -                    Log.error(e);
  -                }
  -            }
  -            // we have already completed the reflection on the setter, so
  -            // save it so we do not have to repeat
  -            synchronized(setterMap)
  -            {
  -                try
  -                {
  -                    Method setter = pd.getWriteMethod();
  -                    ((Map)setterMap.get(className)).put(propName, setter);
  -                }
  -                catch (Exception e)
  -                {
  -                    Log.error(e);
  +                pd = new PropertyDescriptor(propName,
  +                        Class.forName(className));
  +                getter = pd.getReadMethod();
  +                ((Map) getterMap.get(className)).put(propName, getter);
  +                if (getter == null)
  +                {
  +                    log.error("Intake: getter for '" + propName
  +                            + "' in class '" + className
  +                            + "' could not be found.");
                   }
               }
           }
  
  
  
  1.1                  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/IntakeException.java
  
  Index: IntakeException.java
  ===================================================================
  package org.apache.turbine.services.intake;
  
  import org.apache.turbine.util.TurbineException;
  
  /**
   * Base exception thrown by the Intake service.
   *
   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
   * @version $Id: IntakeException.java,v 1.1 2003/01/03 07:20:43 quintonm Exp $
   */
  public class IntakeException extends TurbineException
  {
      /**
       * Constructs a new <code>TurbineException</code> without specified
       * detail message.
       */
      public IntakeException()
      {
      }
  
      /**
       * Constructs a new <code>TurbineException</code> with specified
       * detail message.
       *
       * @param msg The error message.
       */
      public IntakeException(String msg)
      {
          super(msg);
      }
  
      /**
       * Constructs a new <code>TurbineException</code> with specified
       * nested <code>Throwable</code>.
       *
       * @param nested The exception or error that caused this exception
       *               to be thrown.
       */
      public IntakeException(Throwable nested)
      {
          super(nested);
      }
  
      /**
       * Constructs a new <code>TurbineException</code> with specified
       * detail message and nested <code>Throwable</code>.
       *
       * @param msg    The error message.
       * @param nested The exception or error that caused this exception
       *               to be thrown.
       */
      public IntakeException(String msg, Throwable nested)
      {
          super(msg, nested);
      }
  
  }
  
  
  
  1.4       +82 -28    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/BigDecimalField.java
  
  Index: BigDecimalField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/BigDecimalField.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- BigDecimalField.java	11 Jul 2002 16:53:27 -0000	1.3
  +++ BigDecimalField.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -55,70 +55,124 @@
    */
   
   import java.math.BigDecimal;
  +import java.text.DecimalFormatSymbols;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
  +import org.apache.turbine.services.intake.validator.NumberValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.Log;
  -import org.apache.turbine.util.ParameterParser;
   
  -/**  */
  -public class BigDecimalField extends Field
  +/**
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
  + * @version $Id$
  + */
  +public class BigDecimalField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(BigDecimalField.class);
  +
  +    /**
  +     * Constructor.
  +     *
  +     * @param field xml field definition object
  +     * @param group xml group definition object
  +     * @throws IntakeException thrown by superclass
  +     */
       public BigDecimalField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
  -
       /**
  -     * Sets the default value for a BigDecimal
  +     * Sets the default value for a BigDecimal field
        *
  +     * @param prop Parameter for the default values
        */
  -
       protected void setDefaultValue(String prop)
       {
           defaultValue = null;
   
  -        if(prop == null)
  -            return;
  -
  -        try
  -        {
  -            defaultValue = new BigDecimal(prop);
  -        }
  -        catch(RuntimeException e)
  +        if (prop == null)
           {
  -            Log.error("Could not convert "+prop+" into a BigDecimal. ("+name+")");
  +            return;
           }
  +
  +        defaultValue = new BigDecimal(prop);
       }
   
       /**
        * A suitable validator.
        *
  -     * @return "NumberValidator"
  +     * @return A suitable validator
        */
       protected String getDefaultValidator()
       {
  -        return "org.apache.turbine.services.intake.validator.NumberValidator";
  +        return NumberValidator.class.getName();
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            BigDecimal[] ival = new BigDecimal[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            String[] inputs = parser.getStrings(getKey());
  +            BigDecimal[] values = new BigDecimal[inputs.length];
  +            for (int i = 0; i < inputs.length; i++)
               {
  -                ival[i] = new BigDecimal(ss[i]);
  +                if (inputs[i] != null && inputs[i].length() > 0)
  +                {
  +                    values[i] = canonicalizeDecimalInput(inputs[i]);
  +                }
  +                else
  +                {
  +                    values[i] = null;
  +                }
               }
  -            setTestValue(ival);
  +            setTestValue(values);
           }
           else
           {
  -            setTestValue( new BigDecimal(pp.getString(getKey())) );
  +            String s = parser.getString(getKey());
  +            if (s != null && s.length() > 0)
  +            {
  +                setTestValue(canonicalizeDecimalInput(s));
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Canonicalizes an user-inputted <code>BigDecimal</code> string
  +     * to the system's internal format.
  +     *
  +     * @param bigDecimal Text conforming to a <code>BigDecimal</code>
  +     * description for a set of <code>DecimalFormatSymbols</code>.
  +     * @return The canonicalized representation.
  +     */
  +    protected final BigDecimal canonicalizeDecimalInput(String bigDecimal)
  +    {
  +        if (getLocale() != null)
  +        {
  +            DecimalFormatSymbols internal = new DecimalFormatSymbols();
  +            DecimalFormatSymbols user = new DecimalFormatSymbols(getLocale());
  +
  +            if (!internal.equals(user))
  +            {
  +                bigDecimal = bigDecimal.replace(user.getDecimalSeparator(),
  +                        internal.getDecimalSeparator());
  +            }
           }
  +        return new BigDecimal(bigDecimal);
       }
   }
  
  
  
  1.3       +79 -26    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/BooleanField.java
  
  Index: BooleanField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/BooleanField.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BooleanField.java	9 Oct 2001 14:44:38 -0000	1.2
  +++ BooleanField.java	3 Jan 2003 07:20:43 -0000	1.3
  @@ -54,72 +54,125 @@
    * <http://www.apache.org/>.
    */
   
  +import java.text.ParseException;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
  +import org.apache.turbine.services.intake.validator.BooleanValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.Log;
  -import org.apache.turbine.util.ParameterParser;
  -import org.apache.turbine.util.Log;
   
   /**
  - * Base class for Intake generated input processing classes.
  + * Processor for boolean fields.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  -public class BooleanField extends Field
  +public class BooleanField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(BooleanField.class);
  +
       public BooleanField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an FileItemField
  +     * Sets the default value for a Boolean field
  +     *
  +     * @param prop Parameter for the default values
        */
  -    
       protected void setDefaultValue(String prop)
       {
  -        if(prop == null)
  -            return;
  -
  -        try
  -        {
  -            defaultValue = new Boolean(prop);
  -        } 
  -        catch(RuntimeException e) 
  +        if (prop == null)
           {
  -            Log.error("Could not convert "+prop+" into a Boolean. ("+name+")");
  +            return;
           }
  +
  +        defaultValue = new Boolean(prop);
       }
   
       /**
        * A suitable validator.
        *
  -     * @return null
  +     * @return class name of the validator
        */
       protected String getDefaultValidator()
       {
  -        return null;
  +        return BooleanValidator.class.getName();
  +    }
  +
  +    /**
  +     * Sets the value of the field from data in the parser.
  +     */
  +    protected void doSetValue()
  +    {
  +        String boolStringValue = parser.getString(getKey());
  +        Boolean newValue = null;
  +        if (boolStringValue != null)
  +        {
  +            newValue = getBoolean(boolStringValue);
  +        }
  +        setTestValue(newValue);
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Parses a string into a Boolean object.  If the field has a validator
  +     * and the validator is an instance of BooleanValidator, the parse()
  +     * method is used to convert the string into the Boolean.  Otherwise,
  +     * the string value is passed to the constructor to the Boolean
  +     * object.
  +     *
  +     * @param stringValue string to parse
  +     * @return a <code>Boolean</code> object
        */
  -    protected void doSetValue(ParameterParser pp)
  +    private Boolean getBoolean(String stringValue)
       {
  -        setTestValue( pp.getBool(getKey()) );
  +        Boolean result = null;
  +
  +        if( validator != null && validator instanceof BooleanValidator )
  +        {
  +            BooleanValidator bValidator = (BooleanValidator) validator;
  +            try
  +            {
  +                result = bValidator.parse(stringValue);
  +            }
  +            catch (ParseException e)
  +            {
  +                // do nothing.  This should never be thrown since this method will not be
  +                // executed unless the Validator has already been able to parse the
  +                // string value
  +            }
  +        }
  +        else
  +        {
  +            result = new Boolean(stringValue);
  +        }
  +
  +        return result;
       }
   
  +    /**
  +     * Gets the boolean value of the field.  A value of false will be returned
  +     * if the value of the field is null.
  +     *
  +     * @return value of the field.
  +     */
       public boolean booleanValue()
       {
           boolean result = false;
           try
           {
  -            result = ((Boolean)getValue()).booleanValue();
  +            result = ((Boolean) getValue()).booleanValue();
           }
           catch (Exception e)
           {
  -            Log.error(e);
  +            log.error(e);
           }
           return result;
       }
  
  
  
  1.5       +45 -23    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/ComboKeyField.java
  
  Index: ComboKeyField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/ComboKeyField.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ComboKeyField.java	11 Jul 2002 16:53:27 -0000	1.4
  +++ ComboKeyField.java	3 Jan 2003 07:20:43 -0000	1.5
  @@ -54,58 +54,80 @@
    * <http://www.apache.org/>.
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.torque.om.ComboKey;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.Log;
  -import org.apache.turbine.util.ParameterParser;
   
   /**
  - *
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  -public class ComboKeyField extends Field
  +public class ComboKeyField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(ComboKeyField.class);
  +
       public ComboKeyField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an ComboKeyField
  +     * Sets the default value for a ComboKey field
  +     *
  +     * @param prop Parameter for the default values
        */
  -
       protected void setDefaultValue(String prop)
       {
  -        defaultValue = prop;
  +        defaultValue = null;
  +
  +        if (prop == null)
  +        {
  +            return;
  +        }
  +
  +        defaultValue = new ComboKey(prop);
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        try
  +        if (isMultiValued)
           {
  -            if ( isMultiValued  )
  +            String[] ss = parser.getStrings(getKey());
  +            ComboKey[] ival = new ComboKey[ss.length];
  +            for (int i = 0; i < ss.length; i++)
               {
  -                String[] ss = pp.getStrings(getKey());
  -                ComboKey[] ival = new ComboKey[ss.length];
  -                for (int i=0; i<ss.length; i++)
  +                if (ss[i] != null && ss[i].length() != 0)
                   {
                       ival[i] = new ComboKey(ss[i]);
                   }
  -                setTestValue(ival);
  +                else
  +                {
  +                    ival[i] = null;
  +                }
  +            }
  +            setTestValue(ival);
  +        }
  +        else
  +        {
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() != 0)
  +            {
  +                setTestValue(new ComboKey(val));
               }
               else
               {
  -                setTestValue( new ComboKey(pp.getString(getKey())) );
  +                setTestValue(null);
               }
  -        }
  -        catch (Exception e)
  -        {
  -            valid_flag = false;
  -            Log.error(e);
           }
       }
   }
  
  
  
  1.3       +116 -34   jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/DateStringField.java
  
  Index: DateStringField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/DateStringField.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DateStringField.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ DateStringField.java	3 Jan 2003 07:20:43 -0000	1.3
  @@ -57,9 +57,13 @@
   import java.text.DateFormat;
   import java.text.ParseException;
   import java.util.Date;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.validator.DateStringValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.ParameterParser;
  +import org.apache.turbine.util.TurbineRuntimeException;
   
   /**
    * Field for date inputs as free form text.  The parsing of date strings
  @@ -67,17 +71,24 @@
    * any validator will be (or extend) DateStringValidator.
    *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
  + * @version $Id$
    */
  -public class DateStringField extends Field
  +public class DateStringField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(DateStringField.class);
  +
       private DateFormat df = null;
   
       public DateStringField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
   
  -        if ( validator == null )
  +        if (validator == null || !(validator instanceof DateStringValidator))
           {
               df = DateFormat.getInstance();
               df.setLenient(true);
  @@ -85,66 +96,137 @@
       }
   
       /**
  -     * A suitable validator.
  +     * Sets the default value for a DateString field
        *
  -     * @return "DateStringValidator"
  +     * @param prop Parameter for the default values
  +     * @throws TurbineRuntimeException the date string could not be parsed.
        */
  -    protected String getDefaultValidator()
  +    protected void setDefaultValue(String prop)
       {
  -        return "org.apache.turbine.services.intake.validator.DateStringValidator";
  -    }
  -
  +        defaultValue = null;
   
  +        if (prop == null)
  +        {
  +            return;
  +        }
   
  -    private Date getDate(String dateString)
  -    {
  -        Date date = null;
           try
           {
  -            // FIXME: Canonicalize user-entered date strings.
  -            if ( df == null ) // guarantees validator != null
  -            {
  -                date = ((DateStringValidator)validator).parse(dateString);
  -            }
  -            else
  -            {
  -                date = df.parse(dateString);
  -            }
  +            defaultValue = getDate(prop);
           }
           catch (ParseException e)
           {
  -            //ignore, return null
  +            throw new TurbineRuntimeException("Could not parse " + prop +
  +                    " into a valid Date", e);
           }
  -        return date;
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * A suitable validator.
  +     *
  +     * @return "DateStringValidator"
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected String getDefaultValidator()
       {
  -        if ( isMultiValued  )
  +        return DateStringValidator.class.getName();
  +    }
  +
  +    /**
  +     * Sets the value of the field from data in the parser.
  +     */
  +    protected void doSetValue()
  +    {
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  +            String[] ss = parser.getStrings(getKey());
               Date[] dates = new Date[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            for (int i = 0; i < ss.length; i++)
               {
  -                dates[i] = getDate(ss[i]);
  +                if (ss[i] != null && ss[i].length() != 0)
  +                {
  +                    try
  +                    {
  +                        dates[i] = getDate(ss[i]);
  +                    }
  +                    catch (ParseException e)
  +                    {
  +                        // do nothing.  By the time this method is called, the validator will
  +                        // have already ensured that the string can be parsed.
  +                    }
  +                }
  +                else
  +                {
  +                    dates[i] = null;
  +                }
               }
               setTestValue(dates);
           }
           else
           {
  -            setTestValue( getDate(pp.getString(getKey())) );
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() != 0)
  +            {
  +                try
  +                {
  +                    setTestValue(getDate(val));
  +                }
  +                catch (ParseException e)
  +                {
  +                    // do nothing.  By the time this method is called, the validator will
  +                    // have already ensured that the string can be parsed.
  +                }
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
           }
       }
   
       /**
  -     * Sets the default value for an ComboKeyField
  +     * Parses a test date string using the Validator if is exists and
  +     * is an instance of DateStringValidator.  Otherwise, DateFormat.parse()
  +     * is used.
  +     * @param dateString The string date to parse
  +     * @return A <code>Date</code> object
  +     * @throws ParseException The date could not be parsed.
        */
  +    private Date getDate(String dateString)
  +            throws ParseException
  +    {
  +        Date date = null;
  +        // FIXME: Canonicalize user-entered date strings.
  +        if (validator != null && validator instanceof DateStringValidator)
  +        {
  +            date = ((DateStringValidator) validator).parse(dateString);
  +        }
  +        else
  +        {
  +            date = df.parse(dateString);
  +        }
  +        return date;
  +    }
   
  -    protected void setDefaultValue(String prop)
  +    public String toString()
       {
  -        defaultValue = prop;
  +        String s = null;
  +        Object value = getValue();
  +        if (value == null)
  +        {
  +            s = "";
  +        }
  +        else if (value instanceof String)
  +        {
  +            s = (String) value;
  +        }
  +        else if (validator != null && validator instanceof DateStringValidator)
  +        {
  +            s = ((DateStringValidator) validator).format((Date) value);
  +        }
  +        else
  +        {
  +            s = df.format((Date) value);
  +        }
  +        return s;
       }
   }
  
  
  
  1.4       +338 -143  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/Field.java
  
  Index: Field.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/Field.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Field.java	11 Jul 2002 16:53:27 -0000	1.3
  +++ Field.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -54,23 +54,34 @@
    * <http://www.apache.org/>.
    */
   
  +import java.lang.reflect.InvocationTargetException;
   import java.lang.reflect.Method;
  +import java.util.Locale;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.turbine.om.Retrievable;
  +import org.apache.turbine.services.TurbineServices;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.TurbineIntake;
  +import org.apache.turbine.services.intake.validator.DefaultValidator;
   import org.apache.turbine.services.intake.validator.InitableByConstraintMap;
   import org.apache.turbine.services.intake.validator.ValidationException;
   import org.apache.turbine.services.intake.validator.Validator;
   import org.apache.turbine.services.intake.xmlmodel.Rule;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.Log;
  +import org.apache.turbine.services.localization.Localization;
  +import org.apache.turbine.services.localization.LocalizationService;
   import org.apache.turbine.util.ParameterParser;
  -import org.apache.turbine.util.RunData;
  -import org.apache.turbine.util.TurbineException;
  +import org.apache.turbine.util.SystemError;
  +import org.apache.turbine.util.ValueParser;
   
   /**
    * Base class for Intake generated input processing classes.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:dlr@finemaltcoding.com>Daniel Rall</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    * @version $Id$
    */
   public abstract class Field
  @@ -79,34 +90,81 @@
       private static final String VALUE_IF_ABSENT_KEY = "_vifa_";
   
       // the following are set from the xml file and are permanent (final)
  +
  +    /** Name of the field. */
       protected final String name;
  +
  +    /** Key used to identify the field in the parser */
       protected final String key;
  +
  +    /** Display name of the field to be used on data entry forms... */
       protected String displayName;
  +
  +    /** Class name of the object to which the field is mapped */
       protected final String mapToObject;
  +
  +    /** Used to validate the contents of the field */
       protected Validator validator;
  +
  +    /** Getter method in the mapped object used to populate the field */
       protected final Method getter;
  +
  +    /** Setter method in the mapped object used to store the value of field */
       protected final Method setter;
  +
  +    /** Error message set on the field if required and not set by parser */
       protected final String ifRequiredMessage;
  +
  +    /** Does this field accept multiple values? */
       protected final boolean isMultiValued;
  +
  +    /** Group to which the field belongs */
       protected final Group group;
  +
  +    /** Is this field always required?  This is only set through the XML file */
       protected boolean alwaysRequired;
  +
  +    /** Value of the field if an error occurs while getting the value from the mapped object */
       protected Object onError;
  +
  +    /** Default value of the field */
       protected Object defaultValue;
   
       // these are reset when the Field is returned to the pool
  -    protected boolean set_flag;
  -    protected boolean valid_flag;
  +
  +    /** Has the field has been set from the parser? */
  +    protected boolean setFlag;
  +
  +    /** Has the field passed the validation test? */
  +    protected boolean validFlag;
  +
  +    /** Does the field require a value? */
       protected boolean required;
  +
  +    /** Has the field has been set from the parser? */
       protected boolean initialized;
  +
  +    /** Error message, is any, resulting from validation */
       protected String message;
  +
  +    /** Mapped object used to set the initial field value */
       protected Retrievable retrievable;
   
  +    private Locale locale;
  +    /** String value of the field */
  +    private String stringValue;
  +    /** String valuess of the field if isMultiValued=true */
  +    private String[] stringValues;
  +    /** Stores the value of the field from the Retrievable object */
       private Object validValue;
  +    /** Stores the value of the field from the parser */
       private Object testValue;
  -    private Object[] valArray; // for reflection
  -
  -    /** The object containing the request data */
  -    protected RunData data;
  +    /** Used to pass testValue to the setter mathod through reflection */
  +    private Object[] valArray;
  +    /** The object containing the field data. */
  +    protected ValueParser parser;
  +    /** Logging */
  +    private static Log log = LogFactory.getLog(Field.class);
   
       /**
        * Constructs a field based on data in the xml specification
  @@ -114,55 +172,102 @@
        *
        * @param field a <code>XmlField</code> value
        * @param group a <code>Group</code> value
  -     * @exception Exception if an error occurs
  +     * @throws IntakeException indicates the validator was not valid or
  +     * could not be loaded.
  +     * @throws SystemError only occurs is the Validation object does not
  +     * extend InitableByConstraintMap
        */
  -    public Field(XmlField field, Group group)
  -        throws Exception
  +    public Field(XmlField field, Group group) throws IntakeException
       {
           this.group = group;
           key = field.getKey();
           name = field.getName();
           displayName = field.getDisplayName();
  -        isMultiValued  = field.isMultiValued();
  -        setDefaultValue(field.getDefaultValue());
  -        String className = field.getValidator();
  -        if ( className == null && field.getRules().size() > 0 )
  +        isMultiValued = field.isMultiValued();
  +        try
  +        {
  +            setDefaultValue(field.getDefaultValue());
  +        }
  +        catch (RuntimeException e)
  +        {
  +            log.error("Could not set default value of " +
  +                    this.getDisplayName() + " to " + field.getDefaultValue(), e);
  +        }
  +        String validatorClassName = field.getValidator();
  +        if (validatorClassName == null && field.getRules().size() > 0)
           {
  -            className = getDefaultValidator();
  +            validatorClassName = getDefaultValidator();
           }
  -        else if ( className != null && className.indexOf('.') == -1 )
  +        else if (validatorClassName != null && validatorClassName.indexOf('.') == -1)
           {
  -            className = "org.apache.turbine.services.intake.validator."
  -                + className;
  +            validatorClassName = "org.apache.turbine.services.intake.validator."
  +                    + validatorClassName;
           }
   
  -        if ( className != null )
  +        if (validatorClassName != null)
           {
  -            validator = (Validator)Class.forName(className).newInstance();
  +            try
  +            {
  +                validator = (Validator) Class.forName(validatorClassName).newInstance();
  +            }
  +            catch (InstantiationException e)
  +            {
  +                throw new IntakeException("Could not create new instance of Validator(" + validatorClassName + ")", e);
  +            }
  +            catch (IllegalAccessException e)
  +            {
  +                throw new IntakeException("Could not create new instance of Validator(" + validatorClassName + ")", e);
  +            }
  +            catch (ClassNotFoundException e)
  +            {
  +                throw new IntakeException("Could not load Validator class(" + validatorClassName + ")", e);
  +            }
               // this should always be true for now
               // (until bean property initialization is implemented)
  -            if ( validator instanceof InitableByConstraintMap )
  +            if (validator instanceof InitableByConstraintMap)
               {
  -                ((InitableByConstraintMap)validator).init(field.getRuleMap());
  +                ((InitableByConstraintMap) validator).init(field.getRuleMap());
  +            }
  +            else
  +            {
  +                throw new SystemError("All Validation objects must be subclasses of InitableByConstraintMap");
               }
  -
           }
   
           // field may have been declared as always required in the xml spec
  -        Rule reqRule = (Rule)field.getRuleMap().get("required");
  -        if ( reqRule != null )
  +        Rule reqRule = (Rule) field.getRuleMap().get("required");
  +        if (reqRule != null)
           {
               alwaysRequired = new Boolean(reqRule.getValue()).booleanValue();
           }
   
  +        // map the getter and setter methods
           mapToObject = field.getMapToObject();
           String propName = field.getMapToProperty();
           Method tmpGetter = null;
           Method tmpSetter = null;
  -        if ( mapToObject != null && mapToObject.length() != 0)
  +        if (mapToObject != null && mapToObject.length() != 0 && propName != null && propName.length() != 0)
           {
  -            tmpGetter = TurbineIntake.getFieldGetter(mapToObject, propName);
  -            tmpSetter = TurbineIntake.getFieldSetter(mapToObject, propName);
  +            try
  +            {
  +                tmpGetter = TurbineIntake.getFieldGetter(mapToObject, propName);
  +            }
  +            catch (Exception e)
  +            {
  +                log.error("IntakeService could not map the getter for field " + this.getDisplayName() +
  +                        " in group " + this.group.getIntakeGroupName() + " to the property " +
  +                        propName + " in object " + mapToObject, e);
  +            }
  +            try
  +            {
  +                tmpSetter = TurbineIntake.getFieldSetter(mapToObject, propName);
  +            }
  +            catch (Exception e)
  +            {
  +                log.error("IntakeService could not map the setter for field " + this.getDisplayName() +
  +                        " in group " + this.group.getIntakeGroupName() + " to the property " +
  +                        propName + " in object " + mapToObject, e);
  +            }
           }
           getter = tmpGetter;
           setter = tmpSetter;
  @@ -171,38 +276,50 @@
           valArray = new Object[1];
       }
   
  -
       /**
        * Method called when this field (the group it belongs to) is
        * pulled from the pool.  The request data is searched to determine
  -     * if a value has been supplied for this field.  if so, the value
  +     * if a value has been supplied for this field.  If so, the value
        * is validated.
        *
  -     * @param data a <code>RunData</code> value
  +     * @param pp a <code>ValueParser</code> value
        * @return a <code>Field</code> value
  -     * @exception TurbineException if an error occurs
  +     * @throws IntakeException this exception is only thrown by subclasses
  +     * overriding this implementation.
        */
  -    public Field init(RunData data)
  -        throws TurbineException
  +    public Field init(ValueParser pp)
  +            throws IntakeException
       {
  -        this.data = data;
  -        valid_flag = true;
  +        this.parser = pp;
  +        validFlag = true;
   
  -        ParameterParser pp = data.getParameters();
  -        if ( pp.containsKey(getKey()) && pp.getString(getKey()) != null )
  +        // If the parser is for a HTTP request, use the request it's
  +        // associated with to grok the locale.
  +        if (TurbineServices.getInstance()
  +                .isRegistered(LocalizationService.SERVICE_NAME))
           {
  -            set_flag = true;
  -            if (validate(pp))
  +            if (pp instanceof ParameterParser)
  +            {
  +                this.locale = Localization.getLocale
  +                        (((ParameterParser) pp).getRequest());
  +            }
  +            else
               {
  -                // iv.reconcileNotValid(pp);
  +                this.locale = Localization.getLocale((String) null);
               }
           }
  -        else if ( pp.containsKey(getValueIfAbsent()) &&
  -                  pp.getString(getValueIfAbsent()) != null )
  +
  +        if (pp.containsKey(getKey()))
  +        {
  +            setFlag = true;
  +            validate();
  +        }
  +        else if (pp.containsKey(getValueIfAbsent()) &&
  +                pp.getString(getValueIfAbsent()) != null)
           {
               pp.add(getKey(), pp.getString(getValueIfAbsent()));
  -            set_flag = true;
  -            validate(pp);
  +            setFlag = true;
  +            validate();
           }
   
           initialized = true;
  @@ -220,20 +337,39 @@
        */
       public Field init(Retrievable obj)
       {
  -        if ( !initialized )
  +        if (!initialized)
           {
  -            valid_flag = true;
  +            validFlag = true;
           }
           retrievable = obj;
           return this;
       }
   
  +    /**
  +     * Returns the <code>Locale</code> used when localizing data for
  +     * this field, or <code>null</code> if unknown.
  +     *
  +     * @return Where to localize for.
  +     */
  +    protected Locale getLocale()
  +    {
  +        return locale;
  +    }
   
  +    /**
  +     * Produces the fully qualified class name of the default validator.
  +     *
  +     * @return class name of the default validator
  +     */
       protected String getDefaultValidator()
       {
  -        return "org.apache.turbine.services.intake.validator.DefaultValidator";
  +        return DefaultValidator.class.getName();
       }
   
  +    /**
  +     * Gets the Validator object for this field.
  +     * @return a <code>Validator</code> object
  +     */
       public Validator getValidator()
       {
           return validator;
  @@ -241,6 +377,7 @@
   
       /**
        * Flag to determine whether the field has been declared as required.
  +     *
        * @return value of required.
        */
       public boolean isRequired()
  @@ -249,10 +386,13 @@
       }
   
       /**
  -     * Set whether this field is required to have a value.
  +     * Set whether this field is required to have a value.  If the field
  +     * is already required due to a setting in the XML file, this method
  +     * can not set it to false.
  +     *
        * @param v  Value to assign to required.
        */
  -    public void setRequired(boolean  v)
  +    public void setRequired(boolean v)
       {
           setRequired(v, ifRequiredMessage);
       }
  @@ -261,14 +401,14 @@
        * Set the value of required.
        *
        * @param v a <code>boolean</code> value
  -     * @param message, override the value from intake.xml
  +     * @param message override the value from intake.xml
        */
  -    public void setRequired(boolean  v, String message)
  +    public void setRequired(boolean v, String message)
       {
           this.required = v;
  -        if (v && !set_flag)
  +        if (v && !setFlag)
           {
  -            valid_flag=false;
  +            validFlag = false;
               this.message = message;
           }
       }
  @@ -279,10 +419,9 @@
        */
       public void removeFromRequest()
       {
  -        data.getParameters().remove(getKey());
  +        parser.remove(getKey());
       }
   
  -
       /**
        * Disposes the object after use. The method is called
        * when the Group is returned to its pool.
  @@ -290,14 +429,17 @@
        */
       public void dispose()
       {
  -        data = null;
  +        parser = null;
           initialized = false;
  -        set_flag = false;
  -        valid_flag = false;
  +        setFlag = false;
  +        validFlag = false;
           required = false;
           message = null;
           retrievable = null;
   
  +        locale = null;
  +        stringValue = null;
  +        stringValues = null;
           validValue = null;
           testValue = null;
           valArray[0] = null;
  @@ -305,18 +447,12 @@
   
       /**
        * Get the key used to identify the field.
  +     *
        * @return the query data key.
        */
       public String getKey()
       {
  -        if ( group == null )
  -        {
  -            return key;
  -        }
  -        else
  -        {
  -            return group.getObjectKey() + key;
  -        }
  +        return (group == null) ? key : group.getObjectKey() + key;
       }
   
       /**
  @@ -338,7 +474,7 @@
        */
       public boolean isValid()
       {
  -        return valid_flag;
  +        return validFlag;
       }
   
       /**
  @@ -349,13 +485,13 @@
        */
       public boolean isSet()
       {
  -        return set_flag;
  +        return setFlag;
       }
   
       /**
        * Get the display name of the field. Useful for building
        * data entry forms. Returns name of field if no display
  -     * name has been assigned to the field by xml input file
  +     * name has been assigned to the field by xml input file.
        *
        * @return a <code>String</code> value
        */
  @@ -382,11 +518,7 @@
        */
       public String getMessage()
       {
  -        if ( message == null )
  -        {
  -            return EMPTY;
  -        }
  -        return message;
  +        return (message == null) ? EMPTY : message;
       }
   
       /**
  @@ -395,32 +527,36 @@
       public void setMessage(String message)
       {
           this.message = message;
  -        valid_flag = false;
  +        validFlag = false;
  +    }
  +
  +    /**
  +     * @deprecated Call validate() instead (with no parameters).
  +     */
  +    protected boolean validate(ValueParser pp)
  +    {
  +        return validate();
       }
   
       /**
        * Compares request data with constraints and sets the valid flag.
        */
  -    protected boolean validate(ParameterParser pp)
  -        //    throws TurbineException
  +    protected boolean validate()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            // this definition of not set might need refined.  But
  -            // not sure the situation will arise.
  -            if ( ss.length == 0 || (ss.length == 1 && ss[0].length() == 0) )
  -            {
  -                set_flag = false;
  -            }
  +            stringValues = parser.getStrings(getKey());
   
  -            if ( validator != null )
  +            if (validator != null)
               {
  -                for (int i=0; i<ss.length; i++)
  +                // set the test value as a String[] which might be replaced by
  +                // the correct type if the input is valid.
  +                setTestValue(parser.getStrings(getKey()));
  +                for (int i = 0; i < stringValues.length; i++)
                   {
                       try
                       {
  -                        validator.assertValidity(ss[i]);
  +                        validator.assertValidity(stringValues[i]);
                       }
                       catch (ValidationException ve)
                       {
  @@ -429,56 +565,57 @@
                   }
               }
   
  -            if ( set_flag && valid_flag )
  +            if (validFlag)
               {
  -                doSetValue(pp);
  +                doSetValue();
               }
   
           }
           else
           {
  -            String s = pp.getString(getKey());
  -            if ( s.length() == 0 )
  +            stringValue = parser.getString(getKey());
  +            if (validator != null)
               {
  -                set_flag = false;
  -            }
  +                // set the test value as a String which might be replaced by
  +                // the correct type if the input is valid.
  +                setTestValue(parser.getString(getKey()));
   
  -            if ( validator != null )
  -            {
                   try
                   {
  -                    validator.assertValidity(s);
  -
  -                    if ( set_flag )
  -                    {
  -                        doSetValue(pp);
  -                    }
  +                    validator.assertValidity(stringValue);
  +                    doSetValue();
                   }
                   catch (ValidationException ve)
                   {
                       setMessage(ve.getMessage());
                   }
               }
  -            else if ( set_flag )
  +            else
               {
  -                doSetValue(pp);
  +                doSetValue();
               }
           }
   
  -        return valid_flag;
  +        return validFlag;
       }
   
       /**
  -     * Compares request data with constraints and sets the valid flag.
  -     * To be implemented in subclasses
  +     * Set the default Value.
        */
  -    protected abstract void doSetValue(ParameterParser pp);
  +    protected abstract void setDefaultValue(String prop);
   
       /**
  -     * Set the default Value
  +     * @deprecated Use doSetValue() instead (with no parameters).
        */
  -    protected abstract void setDefaultValue(String prop);
  +    protected void doSetValue(ValueParser pp)
  +    {
  +        doSetValue();
  +    }
   
  +    /**
  +     * Sets the value of the field from data in the parser.
  +     */
  +    protected abstract void doSetValue();
   
       /**
        * Set the value used as a default, in the event the field
  @@ -498,14 +635,14 @@
        * be used as the initial value.
        *
        * @return an <code>Object</code> value
  -     * @exception Exception if an error occurs
  +     * @exception IntakeException indicates the value could not be
  +     * returned from the mapped object
        */
  -    public Object getInitialValue()
  -        throws Exception
  +    public Object getInitialValue() throws IntakeException
       {
  -        if ( validValue == null)
  +        if (validValue == null)
           {
  -            if ( retrievable != null )
  +            if (retrievable != null)
               {
                   getProperty(retrievable);
               }
  @@ -542,7 +679,7 @@
        * will be returned as is, unless it is so badly formed that the
        * validation could not parse it.  In most cases the test value
        * is returned even though invalid, so that it can be returned to
  -     * the user to make modifications.  if the test value is not set
  +     * the user to make modifications.  If the test value is not set
        * the initial value is returned.
        *
        * @return an <code>Object</code> value
  @@ -554,17 +691,18 @@
           {
               val = getInitialValue();
           }
  -        catch (Exception e)
  +        catch (IntakeException e)
           {
  -            Log.error(e);
  +            log.error("Could not get intial value of " + this.getDisplayName() +
  +                    " in group " + this.group.getIntakeGroupName(), e);
           }
   
  -        if ( getTestValue() != null )
  +        if (getTestValue() != null)
           {
               val = getTestValue();
           }
   
  -        if ( val == null )
  +        if (val == null)
           {
               val = onError;
           }
  @@ -579,23 +717,44 @@
        */
       public String toString()
       {
  -        if ( getValue() != null )
  +        String res = EMPTY;
  +
  +        if (stringValue != null)
           {
  -            return getValue().toString();
  +            res = stringValue;
           }
  -        else
  +        else if (getValue() != null)
           {
  -            return EMPTY;
  +            res = getValue().toString();
           }
  +        return res;
       }
   
       /**
        * Loads the valid value from a bean
  +     *
  +     * @throws IntakeException indicates a problem during the execution of the
  +     * object's getter method
        */
       public void getProperty(Object obj)
  -        throws Exception
  +            throws IntakeException
       {
  -        validValue = getter.invoke(obj, null);
  +        try
  +        {
  +            validValue = getter.invoke(obj, null);
  +        }
  +        catch (IllegalAccessException e)
  +        {
  +            throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
  +        }
  +        catch (IllegalArgumentException e)
  +        {
  +            throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
  +        }
  +        catch (InvocationTargetException e)
  +        {
  +            throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
  +        }
       }
   
       /**
  @@ -609,39 +768,75 @@
   
       /**
        * Calls a setter method on obj, if this field has been set.
  -     * @exception throws a TurbineException if called and the input
  -     * was not valid.
  +     *
  +     * @throws IntakeException indicates a problem during the execution of the
  +     * object's setter method
        */
  -    public void setProperty(Object obj)
  -        // public void setProperty($appData.BasePackage$field.MapToObject obj)
  -        throws TurbineException
  +    public void setProperty(Object obj) throws IntakeException
       {
           if (!isValid())
           {
  -            throw new TurbineException(
  -                                       "Attempted to assign an invalid input.");
  +            throw new IntakeException(
  +                    "Attempted to assign an invalid input.");
           }
           if (isSet())
           {
  +            valArray[0] = getTestValue();
               try
               {
  -                valArray[0] = getTestValue();
                   setter.invoke(obj, valArray);
               }
  -            catch ( Exception e)
  +            catch (IllegalAccessException e)
  +            {
  +                throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
  +            }
  +            catch (IllegalArgumentException e)
  +            {
  +                throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
  +            }
  +            catch (InvocationTargetException e)
               {
  -                throw new TurbineException("An exception prevented the" +
  -                                           " setting property "+name+" of " + obj + " to " +
  -                                           valArray[0], e);
  +                throwSetGetException("setter", obj, this.getDisplayName(), this.group.getIntakeGroupName(), e);
               }
           }
       }
   
       /**
  +     * Used to throw an IntakeException when an error occurs execuing the get/set method
  +     * of the mapped persistent object.
  +     *
  +     * @param type Type of method. (setter/getter)
  +     * @param fieldName Name of the field
  +     * @param groupName Name of the group
  +     * @param e Exception that was thrown
  +     * @throws IntakeException New exception with formatted message
  +     */
  +    private void throwSetGetException(String type, Object obj, String fieldName, String groupName, Exception e)
  +            throws IntakeException
  +    {
  +        throw new IntakeException("Could not execute " + type + " method for " +
  +                fieldName + " in group " + groupName + " on " + obj.getClass().getName(), e);
  +
  +    }
  +
  +    /**
        * Get the default Value
  +     *
  +     * @return the default value
        */
       public Object getDefaultValue()
       {
           return defaultValue;
       }
  +
  +    /**
  +     * Gets the name of the field.
  +     *
  +     * @return name of the field as specified in the XML file.
  +     */
  +    public String getName()
  +    {
  +        return name;
  +    }
  +
   }
  
  
  
  1.5       +76 -72    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FieldFactory.java
  
  Index: FieldFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FieldFactory.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- FieldFactory.java	11 Jul 2002 13:21:40 -0000	1.4
  +++ FieldFactory.java	3 Jan 2003 07:20:43 -0000	1.5
  @@ -56,13 +56,15 @@
   
   import java.util.HashMap;
   import java.util.Map;
  +
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.TurbineException;
   
   /**
    * Creates Field objects.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public abstract class FieldFactory
  @@ -74,101 +76,101 @@
           fieldCtors = new HashMap();
   
           fieldCtors.put("int", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new IntegerField(f, g);
  -                }
  +                return new IntegerField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("boolean", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new BooleanField(f, g);
  -                }
  +                return new BooleanField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("String", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new StringField(f, g);
  -                }
  +                return new StringField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("BigDecimal", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new BigDecimalField(f, g);
  -                }
  +                return new BigDecimalField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("NumberKey", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new NumberKeyField(f, g);
  -                }
  +                return new NumberKeyField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("ComboKey", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new ComboKeyField(f, g);
  -                }
  +                return new ComboKeyField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("StringKey", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new StringKeyField(f, g);
  -                }
  +                return new StringKeyField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("FileItem", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new FileItemField(f, g);
  -                }
  +                return new FileItemField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("DateString", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                 public Field getInstance(XmlField f, Group g)
  -                     throws Exception
  -                 {
  -                     return new DateStringField(f, g);
  -                 }
  +                return new DateStringField(f, g);
               }
  -                       );
  +        }
  +        );
           fieldCtors.put("float", new FieldFactory.FieldCtor()
  +        {
  +            public Field getInstance(XmlField f, Group g)
  +                    throws IntakeException
               {
  -                public Field getInstance(XmlField f, Group g)
  -                    throws Exception
  -                {
  -                    return new FloatField(f, g);
  -                }
  +                return new FloatField(f, g);
               }
  -                       );
  +        }
  +        );
           return fieldCtors;
       }
   
       private static abstract class FieldCtor
       {
  -        public Field getInstance(XmlField f, Group g) throws Exception
  +        public Field getInstance(XmlField f, Group g) throws IntakeException
           {
               return null;
           }
  @@ -178,24 +180,26 @@
        * Creates a Field object appropriate for the type specified
        * in the xml file.
        *
  -     * @param f a <code>XmlField</code> value
  +     * @param xmlField a <code>XmlField</code> value
        * @return a <code>Field</code> value
  +     * @throws IntakeException indicates that an unknown type was specified for a field.
        */
  -    public static final Field getInstance(XmlField f, Group g)
  -        throws Exception
  +    public static final Field getInstance(XmlField xmlField, Group xmlGroup)
  +            throws IntakeException
       {
           FieldCtor fieldCtor = null;
           Field field = null;
  -        String type = f.getType();
  +        String type = xmlField.getType();
   
  -        fieldCtor = (FieldCtor)fieldCtors.get(type);
  -        if ( fieldCtor == null)
  +        fieldCtor = (FieldCtor) fieldCtors.get(type);
  +        if (fieldCtor == null)
           {
  -            throw new TurbineException("Unsupported type: " + type);
  +            throw new IntakeException("An Unsupported type has been specified for " +
  +                    xmlField.getName() + " in group " + xmlGroup.getIntakeGroupName() + " type = " + type);
           }
           else
           {
  -            field = fieldCtor.getInstance(f, g);
  +            field = fieldCtor.getInstance(xmlField, xmlGroup);
           }
   
           return field;
  
  
  
  1.4       +67 -43    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FileItemField.java
  
  Index: FileItemField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FileItemField.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- FileItemField.java	11 Jul 2002 16:53:27 -0000	1.3
  +++ FileItemField.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -54,44 +54,59 @@
    * <http://www.apache.org/>.
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.validator.FileValidator;
   import org.apache.turbine.services.intake.validator.ValidationException;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   import org.apache.turbine.util.ParameterParser;
  -import org.apache.turbine.util.RunData;
  -import org.apache.turbine.util.TurbineException;
  +import org.apache.turbine.util.TurbineRuntimeException;
  +import org.apache.turbine.util.ValueParser;
   import org.apache.turbine.util.upload.FileItem;
   
   /**
  - *
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  -public class FileItemField extends Field
  +public class FileItemField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(FileItemField.class);
   
       public FileItemField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an FileItemField
  +     * It is not possible to set the default value for this field type.  Calling this
  +     * method with a non-null parameter will result in a TurbineRuntimeException
  +     *
  +     * @throws TurbineRuntimeException
        */
  -
       protected void setDefaultValue(String prop)
       {
  -        defaultValue = prop;
  +        if (prop != null)
  +        {
  +            throw new TurbineRuntimeException("Default values are not valid for " + this.getClass().getName());
  +        }
  +
  +        defaultValue = null;
       }
   
       /**
        * A suitable validator.
        *
  -     * @return "FileValidator"
  +     * @return A suitable validator
        */
       protected String getDefaultValidator()
       {
  -        return "org.apache.turbine.services.intake.validator.FileValidator";
  +        return FileValidator.class.getName();
       }
   
       /**
  @@ -100,21 +115,29 @@
        * if a value has been supplied for this field.  if so, the value
        * is validated.
        *
  -     * @param data a <code>RunData</code> value
  +     * @param vp a <code>ValueParser</code> value
        * @return a <code>Field</code> value
  -     * @exception TurbineException if an error occurs
  +     * @exception IntakeException if an error occurs
        */
  -    public Field init(RunData data)
  -        throws TurbineException
  +    public Field init(ValueParser vp)
  +            throws IntakeException
       {
  -        this.data = data;
  -        valid_flag = true;
  +        try
  +        {
  +            super.parser = (ParameterParser) vp;
  +        }
  +        catch (ClassCastException e)
  +        {
  +            throw new IntakeException(
  +                    "FileItemFields can only be used with ParameterParser");
  +        }
  +
  +        validFlag = true;
   
  -        ParameterParser pp = data.getParameters();
  -        if ( pp.containsKey(getKey()) )
  +        if (parser.containsKey(getKey()))
           {
  -            set_flag = true;
  -            validate(pp);
  +            setFlag = true;
  +            validate();
           }
   
           initialized = true;
  @@ -124,26 +147,26 @@
       /**
        * Compares request data with constraints and sets the valid flag.
        */
  -    protected boolean validate(ParameterParser pp)
  -        //    throws TurbineException
  +    protected boolean validate()
       {
  -        if ( isMultiValued  )
  +        ParameterParser pp = (ParameterParser) super.parser;
  +        if (isMultiValued)
           {
               FileItem[] ss = pp.getFileItems(getKey());
               // this definition of not set might need refined.  But
               // not sure the situation will arise.
  -            if ( ss.length == 0 )
  +            if (ss.length == 0)
               {
  -                set_flag = false;
  +                setFlag = false;
               }
   
  -            if ( validator != null )
  +            if (validator != null)
               {
  -                for (int i=0; i<ss.length; i++)
  +                for (int i = 0; i < ss.length; i++)
                   {
                       try
                       {
  -                        ((FileValidator)validator).assertValidity(ss[i]);
  +                        ((FileValidator) validator).assertValidity(ss[i]);
                       }
                       catch (ValidationException ve)
                       {
  @@ -152,29 +175,29 @@
                   }
               }
   
  -            if ( set_flag && valid_flag )
  +            if (setFlag && validFlag)
               {
  -                doSetValue(pp);
  +                doSetValue();
               }
   
           }
           else
           {
               FileItem s = pp.getFileItem(getKey());
  -            if ( s == null || s.getSize() == 0 )
  +            if (s == null || s.getSize() == 0)
               {
  -                set_flag = false;
  +                setFlag = false;
               }
   
  -            if ( validator != null )
  +            if (validator != null)
               {
                   try
                   {
  -                    ((FileValidator)validator).assertValidity(s);
  +                    ((FileValidator) validator).assertValidity(s);
   
  -                    if ( set_flag )
  +                    if (setFlag)
                       {
  -                        doSetValue(pp);
  +                        doSetValue();
                       }
                   }
                   catch (ValidationException ve)
  @@ -182,21 +205,22 @@
                       setMessage(ve.getMessage());
                   }
               }
  -            else if ( set_flag )
  +            else if (setFlag)
               {
  -                doSetValue(pp);
  +                doSetValue();
               }
           }
   
  -        return valid_flag;
  +        return validFlag;
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        ParameterParser pp = (ParameterParser) super.parser;
  +        if (isMultiValued)
           {
               setTestValue(pp.getFileItems(getKey()));
           }
  
  
  
  1.3       +45 -29    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FloatField.java
  
  Index: FloatField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/FloatField.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- FloatField.java	7 Jun 2002 21:37:02 -0000	1.2
  +++ FloatField.java	3 Jan 2003 07:20:43 -0000	1.3
  @@ -54,78 +54,94 @@
    * <http://www.apache.org/>.
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
  +import org.apache.turbine.services.intake.validator.NumberValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   
  -import org.apache.turbine.util.Log;
  -import org.apache.turbine.util.ParameterParser;
  -
   /**
  - * Creates Field objects.
  + * Creates Float Field objects.
    *
    * @author <a href="mailto:r.wekker@rubicon-bv.com>Ronald Wekker</a>
  + * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  - 
  -public class FloatField extends Field
  +
  +public class FloatField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(FloatField.class);
   
       public FloatField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an Float
  +     * Sets the default value for an Float Field
  +     *
  +     * @param prop Parameter for the default values
        */
  -    
       protected void setDefaultValue(String prop)
       {
           defaultValue = null;
   
  -        if(prop == null)
  +        if (prop == null)
           {
               return;
           }
   
  -        try
  -        {
  -            defaultValue = new Float(prop);
  -        } 
  -        catch(Exception e) 
  -        {
  -            Log.error("Could not convert "+prop+" into an Float. ("+name+")");
  -        }
  +        defaultValue = new Float(prop);
       }
   
       /**
        * A suitable validator.
        *
  -     * @return "FloatValidator"
  +     * @return A suitable validator
        */
       protected String getDefaultValidator()
       {
  -        return "org.apache.turbine.services.intake.validator.NumberValidator";
  +        return NumberValidator.class.getName();
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            float[] ival = new float[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            String[] ss = parser.getStrings(getKey());
  +            Float[] ival = new Float[ss.length];
  +            for (int i = 0; i < ss.length; i++)
               {
  -                ival[i] = Float.parseFloat(ss[i]);
  +                if (ss[i] != null && ss[i].length() > 0)
  +                {
  +                    ival[i] = new Float(ss[i]);
  +                }
  +                else
  +                {
  +                    ival[i] = null;
  +                }
               }
               setTestValue(ival);
           }
           else
           {
  -            setTestValue(new Float(pp.getString(getKey())));
  +            String s = parser.getString(getKey());
  +            if (s != null && s.length() > 0)
  +            {
  +                setTestValue(new Float(s));
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
           }
       }
   }
  
  
  
  1.3       +163 -115  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/Group.java
  
  Index: Group.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/Group.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Group.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ Group.java	3 Jan 2003 07:20:43 -0000	1.3
  @@ -59,22 +59,28 @@
   import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;
   import org.apache.turbine.om.Retrievable;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.TurbineIntake;
  +import org.apache.turbine.services.intake.xmlmodel.AppData;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
  -import org.apache.turbine.util.ParameterParser;
  -import org.apache.turbine.util.RunData;
   import org.apache.turbine.util.TurbineException;
  -import org.apache.turbine.util.pool.Recyclable;
  +import org.apache.turbine.util.ValueParser;
   
   /**
    * Holds a group of Fields
    *
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class Group
  -    implements Recyclable
   {
       public static final String EMPTY = "";
   
  @@ -83,6 +89,15 @@
        */
       public static final String NEW = "_0";
   
  +    private static final Log log;
  +    private static final boolean isDebugEnabled;
  +
  +    static
  +    {
  +        log = LogFactory.getLog(Group.class);
  +        isDebugEnabled = log.isDebugEnabled();
  +    }
  +
       /**
        * The key used to represent this group in a parameter.
        * This key is usually a prefix as part of a field key.
  @@ -123,7 +138,7 @@
       /**
        * The object containing the request data
        */
  -    protected RunData data;
  +    protected ValueParser pp;
   
       /**
        * A flag to help prevent duplicate hidden fields declaring this group.
  @@ -136,10 +151,9 @@
        * be instantiated otherwise.
        *
        * @param group a <code>XmlGroup</code> value
  -     * @exception Exception if an error occurs in other classes
  +     * @exception IntakeException if an error occurs in other classes
        */
  -    public Group(XmlGroup group)
  -        throws Exception
  +    public Group(XmlGroup group) throws IntakeException
       {
           gid = group.getKey();
           name = group.getName();
  @@ -147,19 +161,19 @@
   
           List inputFields = group.getFields();
           int size = inputFields.size();
  -        fields = new HashMap((int)(1.25*size + 1));
  -        mapToObjectFields = new HashMap((int)(1.25*size + 1));
  +        fields = new HashMap((int) (1.25 * size + 1));
  +        mapToObjectFields = new HashMap((int) (1.25 * size + 1));
           fieldsArray = new Field[size];
  -        for (int i=size-1; i>=0; i--)
  +        for (int i = size - 1; i >= 0; i--)
           {
  -            XmlField f = (XmlField)inputFields.get(i);
  +            XmlField f = (XmlField) inputFields.get(i);
               Field field = FieldFactory.getInstance(f, this);
  -            fieldsArray[i]= field;
  +            fieldsArray[i] = field;
               fields.put(f.getName(), field);
   
               // map fields by their mapToObject
  -            List tmpFields = (List)mapToObjectFields.get(f.getMapToObject());
  -            if ( tmpFields == null )
  +            List tmpFields = (List) mapToObjectFields.get(f.getMapToObject());
  +            if (tmpFields == null)
               {
                   tmpFields = new ArrayList(size);
                   mapToObjectFields.put(f.getMapToObject(), tmpFields);
  @@ -169,46 +183,44 @@
   
           // Change the mapToObjectFields values to Field[]
           Iterator keys = mapToObjectFields.keySet().iterator();
  -        while ( keys.hasNext() )
  +        while (keys.hasNext())
           {
               Object key = keys.next();
  -            List tmpFields = (List)mapToObjectFields.get(key);
  +            List tmpFields = (List) mapToObjectFields.get(key);
               mapToObjectFields.put(key,
  -                tmpFields.toArray(new Field[tmpFields.size()]));
  +                    tmpFields.toArray(new Field[tmpFields.size()]));
           }
       }
   
       /**
  -     * Initializes the default Group with parameters from RunData.
  +     * Initializes the default Group using parameters.
        *
  -     * @param data a <code>RunData</code> value
  +     * @param pp a <code>ValueParser</code> value
        * @return this Group
        */
  -    public Group init(RunData data) throws TurbineException
  +    public Group init(ValueParser pp) throws TurbineException
       {
  -        return init(NEW, data);
  +        return init(NEW, pp);
       }
   
       /**
        * Initializes the Group with parameters from RunData
        * corresponding to key.
        *
  -     * @param data a <code>RunData</code> value
  +     * @param pp a <code>ValueParser</code> value
        * @return this Group
        */
  -    public Group init(String key, RunData data)
  -        throws TurbineException
  +    public Group init(String key, ValueParser pp) throws IntakeException
       {
           this.oid = key;
  -        this.data = data;
  -        for (int i=fieldsArray.length-1; i>=0; i--)
  +        this.pp = pp;
  +        for (int i = fieldsArray.length - 1; i >= 0; i--)
           {
  -            fieldsArray[i].init(data);
  +            fieldsArray[i].init(pp);
           }
           return this;
       }
   
  -
       /**
        * Initializes the group with properties from an object.
        *
  @@ -220,12 +232,12 @@
           this.oid = obj.getQueryKey();
   
           Class cls = obj.getClass();
  -        while ( cls != null )
  +        while (cls != null)
           {
  -            Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
  -            if ( flds != null )
  +            Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
  +            if (flds != null)
               {
  -                for (int i=flds.length-1; i>=0; i--)
  +                for (int i = flds.length - 1; i >= 0; i--)
                   {
                       flds[i].init(obj);
                   }
  @@ -237,7 +249,6 @@
           return this;
       }
   
  -
       /**
        * Gets a list of the names of the fields stored in this object.
        *
  @@ -246,14 +257,13 @@
       public String[] getFieldNames()
       {
           String nameList[] = new String[fieldsArray.length];
  -        for(int i = 0; i < nameList.length; i++)
  +        for (int i = 0; i < nameList.length; i++)
           {
               nameList[i] = fieldsArray[i].name;
           }
           return nameList;
       }
   
  -
       /**
        * Return the name given to this group.  The long name is to
        * avoid conflicts with the get(String key) method.
  @@ -310,21 +320,20 @@
       /**
        * Describe <code>getObjects</code> method here.
        *
  -     * @param pp a <code>ParameterParser</code> value
  +     * @param pp a <code>ValueParser</code> value
        * @return an <code>ArrayList</code> value
  -     * @exception TurbineException if an error occurs
  +     * @exception IntakeException if an error occurs
        */
  -    public ArrayList getObjects(RunData data)
  -        throws TurbineException
  +    public ArrayList getObjects(ValueParser pp) throws IntakeException
       {
           ArrayList objs = null;
  -        String[] oids = data.getParameters().getStrings(gid);
  +        String[] oids = pp.getStrings(gid);
           if (oids != null)
           {
               objs = new ArrayList(oids.length);
  -            for (int i=oids.length-1; i>=0; i--)
  +            for (int i = oids.length - 1; i >= 0; i--)
               {
  -                objs.add( TurbineIntake.getGroup(name).init(oids[i], data) );
  +                objs.add(TurbineIntake.getGroup(name).init(oids[i], pp));
               }
           }
           return objs;
  @@ -333,18 +342,19 @@
       /**
        * Get the Field .
        * @return Field.
  +     * @throws IntakeException indicates the field could not be found.
        */
       public Field get(String fieldName)
  -        throws TurbineException
  +            throws IntakeException
       {
           if (fields.containsKey(fieldName))
           {
  -            return (Field)fields.get(fieldName);
  +            return (Field) fields.get(fieldName);
           }
           else
           {
  -            throw new TurbineException ("Intake Field name: " + fieldName +
  -                                        " not found!");
  +            throw new IntakeException("Intake Field name: " + fieldName +
  +                    " not found!");
           }
       }
   
  @@ -356,28 +366,35 @@
       public boolean isAllValid()
       {
           boolean valid = true;
  -        for (int i=fieldsArray.length-1; i>=0; i--)
  +        for (int i = fieldsArray.length - 1; i >= 0; i--)
           {
               valid &= fieldsArray[i].isValid();
  +            if (isDebugEnabled && !fieldsArray[i].isValid())
  +            {
  +                log.debug("Group(" + oid + "): " + name + "; Field: "
  +                        + fieldsArray[i].name + "; value=" +
  +                        fieldsArray[i].getValue() + " is invalid!");
  +            }
           }
           return valid;
       }
   
       /**
        * Calls a setter methods on obj, for fields which have been set.
  -     * @exception throws up any exceptions resulting from failure to
  -     * check input validity.
  +     *
  +     * @param obj Object to be set with the values from the group.
  +     * @throws IntakeException indicates that a failure occurred while
  +     * executing the setter methods of the mapped object.
        */
  -    public void setProperties(Object obj)
  -        throws TurbineException
  +    public void setProperties(Object obj) throws IntakeException
       {
           Class cls = obj.getClass();
  -        while ( cls != null )
  +        while (cls != null)
           {
  -            Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
  -            if ( flds != null )
  +            Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
  +            if (flds != null)
               {
  -                for (int i=flds.length-1; i>=0; i--)
  +                for (int i = flds.length - 1; i >= 0; i--)
                   {
                       flds[i].setProperty(obj);
                   }
  @@ -388,20 +405,56 @@
       }
   
       /**
  +     * Calls a setter methods on obj, for fields which pass validity tests.
  +     * In most cases one should call Intake.isAllValid() and then if that
  +     * test passes call setProperties.  Use this method when some data is
  +     * known to be invalid, but you still want to set the object properties
  +     * that are valid.
  +     */
  +    public void setValidProperties(Object obj)
  +    {
  +        Class cls = obj.getClass();
  +        while (cls != null)
  +        {
  +            Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
  +            if (flds != null)
  +            {
  +                for (int i = flds.length - 1; i >= 0; i--)
  +                {
  +                    try
  +                    {
  +                        flds[i].setProperty(obj);
  +                    }
  +                    catch (Exception e)
  +                    {
  +                        // just move on to next field
  +                    }
  +                }
  +            }
  +
  +            cls = cls.getSuperclass();
  +        }
  +    }
  +
  +    /**
        * Calls getter methods on objects that are known to Intake
        * so that field values in forms can be initialized from
        * the values contained in the intake tool.
  +     *
  +     * @param obj Object that will be used to as a source of data for
  +     * setting the values of the fields within the group.
  +     * @throws IntakeException indicates that a failure occurred while
  +     * executing the setter methods of the mapped object.
        */
  -    public void getProperties(Object obj)
  -        throws Exception
  +    public void getProperties(Object obj) throws IntakeException
       {
           Class cls = obj.getClass();
           while (cls != null)
           {
  -            Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
  -            if( flds != null )
  +            Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
  +            if (flds != null)
               {
  -                for (int i=flds.length-1; i>=0; i--)
  +                for (int i = flds.length - 1; i >= 0; i--)
                   {
                       flds[i].getProperty(obj);
                   }
  @@ -417,21 +470,23 @@
        */
       public void removeFromRequest()
       {
  -        ParameterParser pp = data.getParameters();
  -        String[] groups = pp.getStrings(gid);
  -        if ( groups != null )
  +        if (pp != null)
           {
  -            pp.remove(gid);
  -            for (int i=0; i<groups.length; i++)
  +            String[] groups = pp.getStrings(gid);
  +            if (groups != null)
               {
  -                if ( groups[i] != null && !groups[i].equals(oid) )
  +                pp.remove(gid);
  +                for (int i = 0; i < groups.length; i++)
                   {
  -                    pp.add(gid,groups[i]);
  +                    if (groups[i] != null && !groups[i].equals(oid))
  +                    {
  +                        pp.add(gid, groups[i]);
  +                    }
  +                }
  +                for (int i = fieldsArray.length - 1; i >= 0; i--)
  +                {
  +                    fieldsArray[i].removeFromRequest();
                   }
  -            }
  -            for (int i=fieldsArray.length-1; i>=0; i--)
  -            {
  -                fieldsArray[i].removeFromRequest();
               }
           }
       }
  @@ -464,61 +519,54 @@
        */
       public void appendHtmlFormInput(StringBuffer sb)
       {
  -        if ( !isDeclared )
  +        if (!isDeclared)
           {
               isDeclared = true;
               sb.append("<input type=\"hidden\" name=\"")
  -              .append(gid)
  -              .append("\" value=\"")
  -              .append(oid)
  -              .append("\"></input>");
  +                    .append(gid)
  +                    .append("\" value=\"")
  +                    .append(oid)
  +                    .append("\"/>\n");
           }
       }
   
  -    // ****************** Recyclable implementation ************************
  +    // ********** PoolableObjectFactory implementation ******************
   
  -    private boolean disposed;
  -
  -    /**
  -     * Recycles the object for a new client. Recycle methods with
  -     * parameters must be added to implementing object and they will be
  -     * automatically called by pool implementations when the object is
  -     * taken from the pool for a new client. The parameters must
  -     * correspond to the parameters of the constructors of the object.
  -     * For new objects, constructors can call their corresponding recycle
  -     * methods whenever applicable.
  -     * The recycle methods must call their super.
  -     */
  -    public void recycle()
  +    public static class GroupFactory
  +            extends BaseKeyedPoolableObjectFactory
       {
  -        disposed = false;
  -    }
  +        private AppData appData;
   
  -    /**
  -     * Disposes the object after use. The method is called
  -     * when the object is returned to its pool.
  -     * The dispose method must call its super.
  -     */
  -    public void dispose()
  -    {
  -        oid = null;
  -        data = null;
  -        for (int i=fieldsArray.length-1; i>=0; i--)
  +        public GroupFactory(AppData appData)
           {
  -            fieldsArray[i].dispose();
  +            this.appData = appData;
           }
  -        isDeclared = false;
   
  -        disposed = true;
  -    }
  +        /**
  +         * Creates an instance that can be returned by the pool.
  +         * @return an instance that can be returned by the pool.
  +         * @throws IntakeException indicates that the group could not be retreived
  +         */
  +        public Object makeObject(Object key) throws IntakeException
  +        {
  +            return new Group(appData.getGroup((String) key));
  +        }
   
  -    /**
  -     * Checks whether the recyclable has been disposed.
  -     * @return true, if the recyclable is disposed.
  -     */
  -    public boolean isDisposed()
  -    {
  -        return disposed;
  +        /**
  +         * Uninitialize an instance to be returned to the pool.
  +         * @param obj the instance to be passivated
  +         */
  +        public void passivateObject(Object key, Object obj)
  +        {
  +            Group group = (Group) obj;
  +            group.oid = null;
  +            group.pp = null;
  +            for (int i = group.fieldsArray.length - 1; i >= 0; i--)
  +            {
  +                group.fieldsArray[i].dispose();
  +            }
  +            group.isDeclared = false;
  +        }
       }
   }
   
  
  
  
  1.4       +43 -27    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/IntegerField.java
  
  Index: IntegerField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/IntegerField.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IntegerField.java	11 Jul 2002 16:53:27 -0000	1.3
  +++ IntegerField.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -54,72 +54,88 @@
    * <http://www.apache.org/>.
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
  +import org.apache.turbine.services.intake.validator.IntegerValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.Log;
  -import org.apache.turbine.util.ParameterParser;
   
   /**
  - *
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  -public class IntegerField extends Field
  +public class IntegerField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(IntegerField.class);
   
       public IntegerField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an Integer
  +     * Sets the default value for an Integer Field
  +     *
  +     * @param prop Parameter for the default values
        */
  -
       protected void setDefaultValue(String prop)
       {
           defaultValue = null;
   
  -        if(prop == null)
  -            return;
  -
  -        try
  -        {
  -            defaultValue = new Integer(prop);
  -        }
  -        catch(Exception e)
  +        if (prop == null)
           {
  -            Log.error("Could not convert "+prop+" into an Integer. ("+name+")");
  +            return;
           }
  +
  +        defaultValue = new Integer(prop);
       }
   
       /**
        * A suitable validator.
        *
  -     * @return "IntegerValidator"
  +     * @return A suitable validator
        */
       protected String getDefaultValidator()
       {
  -        return "org.apache.turbine.services.intake.validator.IntegerValidator";
  +        return IntegerValidator.class.getName();
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            int[] ival = new int[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            String[] ss = parser.getStrings(getKey());
  +            Integer[] ival = new Integer[ss.length];
  +            for (int i = 0; i < ss.length; i++)
               {
  -                ival[i] = Integer.parseInt(ss[i]);
  +                if (ss[i] != null && ss[i].length() != 0)
  +                {
  +                    ival[i] = new Integer(ss[i]);
  +                }
  +                else
  +                {
  +                    ival[i] = null;
  +                }
               }
               setTestValue(ival);
           }
           else
           {
  -            setTestValue(new Integer(pp.getString(getKey())));
  +            Integer newValue = null;
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() > 0)
  +            {
  +                newValue = new Integer(val);
  +            }
  +            setTestValue(newValue);
           }
       }
   }
  
  
  
  1.4       +56 -30    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/NumberKeyField.java
  
  Index: NumberKeyField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/NumberKeyField.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- NumberKeyField.java	11 Jul 2002 07:18:12 -0000	1.3
  +++ NumberKeyField.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -54,68 +54,94 @@
    * <http://www.apache.org/>.
    */
   
  -import java.util.Vector;
  +import java.math.BigDecimal;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.torque.om.NumberKey;
  -import org.apache.torque.om.ObjectKey;
  -import org.apache.turbine.services.intake.xmlmodel.Rule;
  +import org.apache.turbine.services.intake.IntakeException;
  +import org.apache.turbine.services.intake.validator.NumberKeyValidator;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
  -import org.apache.turbine.util.ParameterParser;
  -import org.apache.turbine.util.Log;
   
  -/**  */
  -public class NumberKeyField extends Field
  +/**
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
  + * @version $Id$
  + */
  +public class NumberKeyField
  +        extends BigDecimalField
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(NumberKeyField.class);
  +
       public NumberKeyField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
  +    /**
  +     * Sets the default value for a NumberKey field
  +     *
  +     * @param prop Parameter for the default values
  +     */
       protected void setDefaultValue(String prop)
       {
  -        if(prop == null)
  -            return;
  -
  -        try
  -        {
  -            defaultValue = new NumberKey(prop);
  -        }
  -        catch(RuntimeException e)
  +        if (prop == null)
           {
  -            Log.error("Could not convert "+prop+" into a NumberKey. ("+name+")");
  +            return;
           }
  -    }
   
  +        defaultValue = new NumberKey(prop);
  +    }
   
       /**
        * A suitable validator.
        *
  -     * @return "NumberKeyValidator"
  +     * @return A suitable validator
        */
       protected String getDefaultValidator()
       {
  -        return
  -            "org.apache.turbine.services.intake.validator.NumberKeyValidator";
  +        return NumberKeyValidator.class.getName();
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            NumberKey[] ival = new NumberKey[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            String[] inputs = parser.getStrings(getKey());
  +            NumberKey[] values = new NumberKey[inputs.length];
  +            for (int i = 0; i < inputs.length; i++)
               {
  -                ival[i] = new NumberKey(ss[i]);
  +                if (inputs[i] != null && inputs[i].length() > 0)
  +                {
  +                    values[i] = new NumberKey(
  +                            canonicalizeDecimalInput(inputs[i]));
  +                }
  +                else
  +                {
  +                    values[i] = null;
  +                }
               }
  -            setTestValue(ival);
  +            setTestValue(values);
           }
           else
           {
  -            setTestValue( new NumberKey(pp.getString(getKey())) );
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() > 0)
  +            {
  +                BigDecimal bd = canonicalizeDecimalInput(val);
  +                setTestValue(new NumberKey(bd));
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
           }
       }
   
  
  
  
  1.3       +80 -18    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/StringField.java
  
  Index: StringField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/StringField.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- StringField.java	9 Oct 2001 14:44:38 -0000	1.2
  +++ StringField.java	3 Jan 2003 07:20:43 -0000	1.3
  @@ -54,45 +54,75 @@
    * <http://www.apache.org/>.
    */
   
  -import org.apache.turbine.util.ParameterParser;
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   
   /**
  - * Base class for Intake generated input processing classes.
  + * Text field.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
  -public class StringField extends Field
  +public class StringField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(StringField.class);
  +
       public StringField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
       }
   
       /**
  -     * Sets the default value for an StringField
  +     * Sets the default value for a String field
  +     *
  +     * @param prop Parameter for the default values
        */
  -    
  +
       protected void setDefaultValue(String prop)
       {
           defaultValue = prop;
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  -            setTestValue(ss);
  +            String[] ss = parser.getStrings(getKey());
  +            String[] sval = new String[ss.length];
  +            for (int i = 0; i < ss.length; i++)
  +            {
  +                if (ss[i] != null && ss[i].length() != 0)
  +                {
  +                    sval[i] = ss[i];
  +                }
  +                else
  +                {
  +                    sval[i] = null;
  +                }
  +            }
  +            setTestValue(sval);
           }
           else
           {
  -            setTestValue(pp.getString(getKey()));
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() > 0)
  +            {
  +                setTestValue(val);
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
           }
       }
   
  @@ -100,13 +130,45 @@
        * Set the value of required.
        * @param v  Value to assign to required.
        */
  -    public void setRequired(boolean  v, String message)
  +    public void setRequired(boolean v, String message)
       {
           this.required = v;
  -        if (v && (!set_flag || ((String)getTestValue()).length() == 0) )
  +        if (v)
           {
  -            valid_flag=false;
  -            this.message = message;
  +            if (isMultiValued)
  +            {
  +                String[] ss = (String[]) getTestValue();
  +                if (ss == null || ss.length == 0)
  +                {
  +                    validFlag = false;
  +                    this.message = message;
  +                }
  +                else
  +                {
  +                    boolean set = false;
  +                    for (int i = 0; i < ss.length; i++)
  +                    {
  +                        if (ss[i] != null && ss[i].length() > 0)
  +                        {
  +                            set = true;
  +                        }
  +                    }
  +                    if (!set)
  +                    {
  +                        validFlag = false;
  +                        this.message = message;
  +                    }
  +                }
  +            }
  +            else
  +            {
  +                if (!setFlag || ((String) getTestValue()).length() == 0)
  +                {
  +                    validFlag = false;
  +                    this.message = message;
  +                }
  +            }
  +
           }
       }
   }
  
  
  
  1.5       +45 -25    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/StringKeyField.java
  
  Index: StringKeyField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/model/StringKeyField.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- StringKeyField.java	11 Jul 2002 07:18:12 -0000	1.4
  +++ StringKeyField.java	3 Jan 2003 07:20:43 -0000	1.5
  @@ -54,58 +54,78 @@
    * <http://www.apache.org/>.
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.torque.om.StringKey;
  -import org.apache.turbine.util.ParameterParser;
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   
  -/**  */
  -public class StringKeyField extends Field
  +/**
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
  + * @version $Id$
  + */
  +public class StringKeyField
  +        extends Field
   {
  +    /** Used for logging */
  +    private static Log log = LogFactory.getLog(StringKeyField.class);
  +
       public StringKeyField(XmlField field, Group group)
  -        throws Exception
  +            throws IntakeException
       {
           super(field, group);
  -
       }
   
       /**
  -     * Sets the default value for an StringKeyField
  +     * Sets the default value for a String field
  +     *
  +     * @param prop Parameter for the default values
        */
  -
       protected void setDefaultValue(String prop)
       {
  -        defaultValue = new StringKey(prop);
  -    }
  +        if (prop == null)
  +        {
  +            return;
  +        }
   
  -    /**
  -     * A suitable validator.
  -     *
  -     * @return "DefaultValidator"
  -     */
  -    protected String getDefaultValidator()
  -    {
  -        return
  -            "org.apache.turbine.services.intake.validator.DefaultValidator";
  +        defaultValue = new StringKey(prop);
       }
   
       /**
  -     * converts the parameter to the correct Object.
  +     * Sets the value of the field from data in the parser.
        */
  -    protected void doSetValue(ParameterParser pp)
  +    protected void doSetValue()
       {
  -        if ( isMultiValued  )
  +        if (isMultiValued)
           {
  -            String[] ss = pp.getStrings(getKey());
  +            String[] ss = parser.getStrings(getKey());
               StringKey[] ival = new StringKey[ss.length];
  -            for (int i=0; i<ss.length; i++)
  +            for (int i = 0; i < ss.length; i++)
               {
  -                ival[i] = new StringKey(ss[i]);
  +                if (ss[i] != null && ss[i].length() != 0)
  +                {
  +                    ival[i] = new StringKey(ss[i]);
  +                }
  +                else
  +                {
  +                    ival[i] = null;
  +                }
               }
               setTestValue(ival);
           }
           else
           {
  -            setTestValue( new StringKey(pp.getString(getKey())) );
  +            String val = parser.getString(getKey());
  +            if (val != null && val.length() != 0)
  +            {
  +                setTestValue(new StringKey(val));
  +            }
  +            else
  +            {
  +                setTestValue(null);
  +            }
           }
       }
   
  
  
  
  1.2       +39 -19    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/transform/DTDResolver.java
  
  Index: DTDResolver.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/transform/DTDResolver.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DTDResolver.java	16 Aug 2001 05:08:57 -0000	1.1
  +++ DTDResolver.java	3 Jan 2003 07:20:43 -0000	1.2
  @@ -25,13 +25,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -57,6 +57,10 @@
   import java.io.IOException;
   import java.io.InputStream;
   import java.net.URL;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +
   import org.xml.sax.EntityResolver;
   import org.xml.sax.InputSource;
   
  @@ -67,12 +71,19 @@
    * Bug 4337703</a>
    *
    * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    * @version $Id$
    */
   public class DTDResolver implements EntityResolver
   {
  -    /** InputSource for database.dtd */
  -    InputSource databaseDTD = null;
  +    private static final String WEB_SITE_DTD =
  +            "http://jakarta.apache.org/turbine/dtd/intake.dtd";
  +
  +    /** InputSource for <code>database.dtd</code>. */
  +    private InputSource databaseDTD = null;
  +
  +    /** Logging */
  +    private static Log log = LogFactory.getLog(DTDResolver.class);
   
       /**
        * constructor
  @@ -81,11 +92,11 @@
       {
           try
           {
  -            InputStream dtdStream = 
  -                getClass().getResourceAsStream("intake.dtd");
  -            
  +            InputStream dtdStream =
  +                    getClass().getResourceAsStream("intake.dtd");
  +
               // getResource was buggy on many systems including Linux,
  -            // OSX, and some versions of windows in jdk1.3.  
  +            // OSX, and some versions of windows in jdk1.3.
               // getResourceAsStream works on linux, maybe others?
               if (dtdStream != null)
               {
  @@ -105,26 +116,35 @@
        */
       public InputSource resolveEntity(String publicId, String systemId)
       {
  -        if (databaseDTD != null &&
  -            "http://jakarta.apache.org/turbine/dtd/intake.dtd".equals(systemId))
  +        if (databaseDTD != null && WEB_SITE_DTD.equals(systemId))
           {
  -            System.out.println("Resolver: used intake.dtd");
  +            String pkg = getClass().getName()
  +                    .substring(0, getClass().getName().lastIndexOf("."));
  +
  +            log.info("Resolver: used intake.dtd from " +
  +                    pkg + " package ");
  +
               return databaseDTD;
           }
  +        else if (systemId == null)
  +        {
  +            log.info("Resolver: used intake.dtd from Jakarta Web site");
  +            return getInputSource(WEB_SITE_DTD);
  +        }
           else
           {
  -            System.out.println("Resolver: used " + systemId);
  +            log.info("Resolver: used System DTD for " + systemId);
               return getInputSource(systemId);
           }
       }
   
       /**
  -     * get an InputSource for an URL String
  +     * Retrieves a XML input source for the specified URL.
        *
  -     * @param urlString
  -     * @return an InputSource for the URL String
  +     * @param urlString The URL of the input source.
  +     * @return <code>InputSource</code> for the URL.
        */
  -    public InputSource getInputSource(String urlString)
  +    private InputSource getInputSource(String urlString)
       {
           try
           {
  
  
  
  1.4       +65 -49    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/transform/XmlToAppData.java
  
  Index: XmlToAppData.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/transform/XmlToAppData.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XmlToAppData.java	11 Jul 2002 16:53:27 -0000	1.3
  +++ XmlToAppData.java	3 Jan 2003 07:20:43 -0000	1.4
  @@ -56,13 +56,21 @@
   
   import java.io.BufferedReader;
   import java.io.FileReader;
  +import java.io.IOException;
  +import javax.xml.parsers.ParserConfigurationException;
  +import javax.xml.parsers.SAXParser;
  +import javax.xml.parsers.SAXParserFactory;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.turbine.services.intake.xmlmodel.AppData;
   import org.apache.turbine.services.intake.xmlmodel.Rule;
   import org.apache.turbine.services.intake.xmlmodel.XmlField;
   import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
  -import org.apache.xerces.parsers.SAXParser;
  +
   import org.xml.sax.Attributes;
   import org.xml.sax.InputSource;
  +import org.xml.sax.SAXException;
   import org.xml.sax.SAXParseException;
   import org.xml.sax.helpers.DefaultHandler;
   
  @@ -71,64 +79,59 @@
    * xml schema file and creates and AppData java structure.
    * It uses apache Xerces to do the xml parsing.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class XmlToAppData extends DefaultHandler
   {
  +    /** Logging */
  +    private static Log log = LogFactory.getLog(XmlToAppData.class);
  +
       private AppData app;
       private XmlGroup currGroup;
       private XmlField currField;
       private Rule currRule;
       private String currElement;
   
  -    /**
  -     * Default custructor
  -     */
  -    public XmlToAppData()
  +    private static SAXParserFactory saxFactory;
  +
  +    static
       {
  -        app = new AppData();
  +        saxFactory = SAXParserFactory.newInstance();
  +        saxFactory.setValidating(true);
       }
   
  -
       /**
  -     * Parse and xml input file and returns a newly
  -     * created and populated AppData structure
  +     * Creates a new instance of the Intake XML Parser
        */
  -    public AppData parseFile(String xmlFile)
  -        throws Exception
  +    public XmlToAppData()
       {
  -        return parseFile(xmlFile, false);
  +        app = new AppData();
       }
   
       /**
  -     * Parse and xml input file and returns a newly
  -     * created and populated AppData structure
  +     * Parses a XML input file and returns a newly created and
  +     * populated AppData structure.
  +     *
  +     * @param xmlFile The input file to parse.
  +     * @return AppData populated by <code>xmlFile</code>.
  +     * @throws ParserConfigurationException
  +     * @throws SAXException
  +     * @throws IOException
        */
  -    public AppData parseFile(String xmlFile, boolean skipValidation)
  -        throws Exception
  +    public AppData parseFile(String xmlFile)
  +            throws ParserConfigurationException, SAXException, IOException
       {
  -        SAXParser parser = new SAXParser();
  -
  -        // set the Resolver for the database DTD
  -        DTDResolver dtdResolver = new DTDResolver();
  -        parser.setEntityResolver(dtdResolver);
  +        SAXParser parser = saxFactory.newSAXParser();
   
  -        // We don't use an external content handler - we use this object
  -        parser.setContentHandler(this);
  -        parser.setErrorHandler(this);
  -
  -        // Validate the input file
  -        parser.setFeature(
  -            "http://apache.org/xml/features/validation/dynamic", true);
  -        parser.setFeature("http://xml.org/sax/features/validation", true);
  -
  -        FileReader fr = new FileReader (xmlFile);
  -        BufferedReader br = new BufferedReader (fr);
  +        FileReader fr = new FileReader(xmlFile);
  +        BufferedReader br = new BufferedReader(fr);
           try
           {
  -            InputSource is = new InputSource (br);
  -            parser.parse(is);
  +            InputSource is = new InputSource(br);
  +            parser.parse(is, this);
           }
           finally
           {
  @@ -138,7 +141,15 @@
           return app;
       }
   
  -
  +    /**
  +     * EntityResolver implementation. Called by the XML parser
  +     *
  +     * @return an InputSource for the database.dtd file
  +     */
  +    public InputSource resolveEntity(String publicId, String systemId)
  +    {
  +        return new DTDResolver().resolveEntity(publicId, systemId);
  +    }
   
       /**
        * Handles opening elements of the xml file.
  @@ -165,7 +176,6 @@
           }
       }
   
  -
       /**
        * Handles the character data, which we are using to specify the
        * error message.
  @@ -173,12 +183,15 @@
       public void characters(char[] mesgArray, int start, int length)
       {
           String cdata = new String(mesgArray, start, length).trim();
  -        if ( "rule".equals(currElement) && cdata.length() > 0)
  +        if ("rule".equals(currElement) && cdata.length() > 0)
           {
               currRule.setMessage(cdata);
           }
  -        if ( "required-message".equals(currElement) && cdata.length() > 0)
  +        if ("required-message".equals(currElement) && cdata.length() > 0)
           {
  +            log.warn("The required-message element is deprecated!  "+
  +                    "You should update your intake.xml file to use the "+
  +                    "'required' rule instead.");
               currField.setIfRequiredMessage(cdata);
           }
       }
  @@ -190,9 +203,10 @@
        */
       public void warning(SAXParseException spe)
       {
  -        System.out.println("Warning Line: " + spe.getLineNumber() +
  -                           " Row: " + spe.getColumnNumber() +
  -                           " Msg: " + spe.getMessage());
  +        log.warn("Parser Exception: " +
  +                "Line " + spe.getLineNumber() +
  +                " Row: " + spe.getColumnNumber() +
  +                " Msg: " + spe.getMessage());
       }
   
       /**
  @@ -202,9 +216,10 @@
        */
       public void error(SAXParseException spe)
       {
  -        System.out.println("Error Line: " + spe.getLineNumber() +
  -                           " Row: " + spe.getColumnNumber() +
  -                           " Msg: " + spe.getMessage());
  +        log.error("Parser Exception: " +
  +                "Line " + spe.getLineNumber() +
  +                " Row: " + spe.getColumnNumber() +
  +                " Msg: " + spe.getMessage());
       }
   
       /**
  @@ -214,8 +229,9 @@
        */
       public void fatalError(SAXParseException spe)
       {
  -        System.out.println("Fatal Error Line: " + spe.getLineNumber() +
  -                           " Row: " + spe.getColumnNumber() +
  -                           " Msg: " + spe.getMessage());
  +        log.fatal("Parser Exception: " +
  +                "Line " + spe.getLineNumber() +
  +                " Row: " + spe.getColumnNumber() +
  +                " Msg: " + spe.getMessage());
       }
   }
  
  
  
  1.2       +7 -7      jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/Constraint.java
  
  Index: Constraint.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/Constraint.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Constraint.java	16 Aug 2001 05:08:58 -0000	1.1
  +++ Constraint.java	3 Jan 2003 07:20:44 -0000	1.2
  @@ -25,13 +25,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -64,11 +64,11 @@
    * value="255"
    * message="Value cannot be longer than 255 characters."
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
    * @version $Id$
    */
   public interface Constraint
  -{ 
  +{
       /**
        * Get the name of the constraint.
        */
  
  
  
  1.2       +70 -37    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/DateStringValidator.java
  
  Index: DateStringValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/DateStringValidator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DateStringValidator.java	11 Jul 2002 13:21:40 -0000	1.1
  +++ DateStringValidator.java	3 Jan 2003 07:20:44 -0000	1.2
  @@ -1,6 +1,5 @@
   package org.apache.turbine.services.intake.validator;
   
  -
   /* ====================================================================
    * The Apache Software License, Version 1.1
    *
  @@ -54,15 +53,16 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    */
  -import java.util.Date;
  -import java.util.Map;
  -import java.util.List;
  -import java.util.ArrayList;
  +
   import java.text.DateFormat;
  -import java.text.SimpleDateFormat;
   import java.text.ParseException;
  -import org.apache.turbine.util.TurbineException;
  +import java.text.SimpleDateFormat;
  +import java.util.ArrayList;
  +import java.util.Date;
  +import java.util.List;
  +import java.util.Map;
   
  +import org.apache.turbine.services.intake.IntakeException;
   
   /**
    * Validates numbers with the following constraints in addition to those
  @@ -81,13 +81,16 @@
    * <td>false</td></tr>
    * </table>
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class DateStringValidator
  -    extends DefaultValidator
  +        extends DefaultValidator
   {
  -    private static final String DEFAULT_DATE_MESSAGE = "Date could not be parsed";
  +    private static final String DEFAULT_DATE_MESSAGE =
  +            "Date could not be parsed";
  +
       private List dateFormats;
       private String dateFormatMessage;
       private boolean flexible;
  @@ -95,7 +98,7 @@
       private SimpleDateFormat sdf;
   
       public DateStringValidator(Map paramMap)
  -        throws TurbineException
  +            throws IntakeException
       {
           this();
           init(paramMap);
  @@ -107,12 +110,12 @@
       }
   
       public void init(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           super.init(paramMap);
           dateFormats = new ArrayList(5);
   
  -        Constraint constraint = (Constraint)paramMap.get("format");
  +        Constraint constraint = (Constraint) paramMap.get("format");
   
           if (constraint != null)
           {
  @@ -121,13 +124,13 @@
           }
   
           int i = 1;
  -        constraint = (Constraint)paramMap.get("format" + i);
  +        constraint = (Constraint) paramMap.get("format" + i);
   
           while (constraint != null)
           {
               dateFormats.add(constraint.getValue());
               setDateFormatMessage(constraint.getMessage());
  -            constraint = (Constraint)paramMap.get("format" + (++i));
  +            constraint = (Constraint) paramMap.get("format" + (++i));
           }
   
           if (dateFormatMessage == null || dateFormatMessage.equals(""))
  @@ -135,14 +138,14 @@
               dateFormatMessage = DEFAULT_DATE_MESSAGE;
           }
   
  -        constraint = (Constraint)paramMap.get("flexible");
  +        constraint = (Constraint) paramMap.get("flexible");
   
           if (constraint != null)
           {
               flexible = Boolean.valueOf(constraint.getValue()).booleanValue();
           }
   
  -        if ((dateFormats.size() == 0) || (flexible))
  +        if (dateFormats.size() == 0 || flexible)
           {
               df = DateFormat.getInstance();
               df.setLenient(true);
  @@ -163,7 +166,7 @@
        * testValue did not pass the validation tests.
        */
       protected void doAssertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           try
           {
  @@ -179,9 +182,12 @@
       /**
        * Parses the String s according to the rules/formats for this
        * validator.
  +     *
  +     * @throws ParseException indicates that the string could not be
  +     * parsed into a date.
        */
       public Date parse(String s)
  -        throws ParseException
  +            throws ParseException
       {
           Date date = null;
   
  @@ -190,9 +196,9 @@
               throw new ParseException("Input string was null", -1);
           }
   
  -        for (int i = 0; i < dateFormats.size(); i++)
  +        for (int i = 0; i < dateFormats.size() && date == null; i++)
           {
  -            sdf.applyPattern((String)dateFormats.get(i));
  +            sdf.applyPattern((String) dateFormats.get(i));
   
               try
               {
  @@ -203,26 +209,49 @@
                   // ignore
               }
   
  -            if (date != null)
  -            {
  -                break;
  -            }
           }
   
  -        if ((date == null) && (df != null))
  +        if (date == null && df != null)
           {
               date = df.parse(s);
           }
   
  +        // if the date still has not been parsed at this point, throw
  +        // a ParseException.
  +        if( date == null )
  +        {
  +            throw new ParseException("Could not parse the date", 0);
  +        }
  +
           return date;
       }
   
  +    /**
  +     * Formats a date into a String.  The format used is from
  +     * the first format rule found for the field.
  +     *
  +     * @param date the Date object to convert into a string.
  +     * @return formatted date
  +     */
  +    public String format(Date date)
  +    {
  +        String s = null;
  +        if (date != null)
  +        {
  +            sdf.applyPattern((String) dateFormats.get(0));
  +            s = sdf.format(date);
  +        }
  +        return s;
  +    }
  +
  +
       // ************************************************************
       // **                Bean accessor methods                   **
       // ************************************************************
   
       /**
        * Get the value of minLengthMessage.
  +     *
        * @return value of minLengthMessage.
        */
       public String getDateFormatMessage()
  @@ -235,18 +264,19 @@
        * So the last setMessage call with valid data wins.  But later calls
        * with null or empty string will not affect a previous valid setting.
        *
  -     * @param v  Value to assign to minLengthMessage.
  +     * @param message  Value to assign to minLengthMessage.
        */
  -    public void setDateFormatMessage(String v)
  +    public void setDateFormatMessage(String message)
       {
  -        if ((v != null) && (!v.equals("")))
  +        if (message != null && !message.equals(""))
           {
  -            dateFormatMessage = v;
  +            dateFormatMessage = message;
           }
       }
   
       /**
        * Get the value of dateFormats.
  +     *
        * @return value of dateFormats.
        */
       public List getDateFormats()
  @@ -256,15 +286,17 @@
   
       /**
        * Set the value of dateFormats.
  -     * @param v  Value to assign to dateFormats.
  +     *
  +     * @param formats  Value to assign to dateFormats.
        */
  -    public void setDateFormats(List v)
  +    public void setDateFormats(List formats)
       {
  -        this.dateFormats = v;
  +        this.dateFormats = formats;
       }
   
       /**
        * Get the value of flexible.
  +     *
        * @return value of flexible.
        */
       public boolean isFlexible()
  @@ -274,10 +306,11 @@
   
       /**
        * Set the value of flexible.
  -     * @param v  Value to assign to flexible.
  +     *
  +     * @param flexible  Value to assign to flexible.
        */
  -    public void setFlexible(boolean v)
  +    public void setFlexible(boolean flexible)
       {
  -        this.flexible = v;
  +        this.flexible = flexible;
       }
   }
  
  
  
  1.3       +128 -60   jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/DefaultValidator.java
  
  Index: DefaultValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/DefaultValidator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultValidator.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ DefaultValidator.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -55,8 +55,14 @@
    */
   
   import java.util.Map;
  -import org.apache.regexp.RE;
  -import org.apache.turbine.util.TurbineException;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.oro.text.regex.MalformedPatternException;
  +import org.apache.oro.text.regex.Pattern;
  +import org.apache.oro.text.regex.Perl5Compiler;
  +import org.apache.oro.text.regex.Perl5Matcher;
  +import org.apache.turbine.services.intake.IntakeException;
   
   /**
    * A validator that will compare a testValue against the following
  @@ -72,14 +78,22 @@
    * This validator can serve as the base class for more specific validators
    *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class DefaultValidator
  -    implements Validator, InitableByConstraintMap
  +        implements Validator, InitableByConstraintMap
   {
       protected boolean required;
       protected String requiredMessage;
  -    protected RE mask;
  +
  +    /** The matching mask String as supplied by the XML input */
  +    protected String maskString;
  +
  +    /** The compiled perl5 Regular expression from the ORO Perl5Compiler */
  +    protected Pattern maskPattern;
  +
  +    /** The message to report if the mask constraint is not satisfied */
       protected String maskMessage;
       protected int minLength;
       protected String minLengthMessage;
  @@ -88,8 +102,23 @@
   
       protected String message;
   
  +    /** perl5 compiler, needed for setting up the masks */
  +    private Perl5Compiler patternCompiler = new Perl5Compiler();
  +
  +    /** perl5 matcher */
  +    private Perl5Matcher patternMatcher = new Perl5Matcher();
  +
  +    /** Logging */
  +    private Log log = LogFactory.getLog(this.getClass());
  +
  +    /**
  +     * Constructor
  +     *
  +     * @param paramMap
  +     * @throws InvalidMaskException
  +     */
       public DefaultValidator(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           init(paramMap);
       }
  @@ -98,52 +127,56 @@
       {
       }
   
  -
  -
       /**
        * Extract the relevant parameters from the constraints listed
        * in <rule> tags within the intake.xml file.
        *
        * @param paramMap a <code>Map</code> of <code>Rule</code>'s
        * containing constraints on the input.
  -     * @exception TurbineException if an error occurs
  +     * @exception InvalidMaskException An invalid mask was specified for one of the rules
        */
       public void init(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
  -        mask = null;
  +        // Init Mask stuff
  +        maskString = null;
  +        maskPattern = null;
           maskMessage = null;
  +
  +        // Init minLength stuff
           minLength = 0;
           minLengthMessage = null;
  +
  +        // Init maxLength stuff
           maxLength = 0;
           maxLengthMessage = null;
   
  -        Constraint constraint = (Constraint)paramMap.get("mask");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("mask");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               setMask(param);
               maskMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("minLength");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("minLength");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               minLength = Integer.parseInt(param);
               minLengthMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("maxLength");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("maxLength");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               maxLength = Integer.parseInt(param);
               maxLengthMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("required");
  -        if ( constraint == null )
  +        constraint = (Constraint) paramMap.get("required");
  +        if (constraint == null)
           {
               required = false;
           }
  @@ -186,17 +219,17 @@
        * testValue did not pass the validation tests.
        */
       public void assertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           message = null;
   
  -        if ( (!required && minLength == 0)
  -             && ( testValue == null || testValue.length() == 0) )
  +        if ((!required && minLength == 0)
  +                && (testValue == null || testValue.length() == 0))
           {
               return;
           }
  -        else if ( required
  -                  && ( testValue == null || testValue.length() == 0))
  +        else if (required
  +                && (testValue == null || testValue.length() == 0))
           {
               message = requiredMessage;
               throw new ValidationException(requiredMessage);
  @@ -205,17 +238,27 @@
           // allow subclasses first chance at validation
           doAssertValidity(testValue);
   
  -        if ( mask != null && !mask.match(testValue) )
  +        if (maskPattern != null)
           {
  -            message = maskMessage;
  -            throw new ValidationException(maskMessage);
  +            boolean patternMatch =
  +                    patternMatcher.matches(testValue, maskPattern);
  +
  +            log.debug("Trying to match " + testValue
  +                    + " to pattern " + maskString);
  +
  +            if (!patternMatch)
  +            {
  +                message = maskMessage;
  +                throw new ValidationException(maskMessage);
  +            }
           }
  -        if ( minLength > 0 && testValue.length() < minLength )
  +
  +        if (minLength > 0 && testValue.length() < minLength)
           {
               message = minLengthMessage;
               throw new ValidationException(minLengthMessage);
           }
  -        if ( maxLength > 0 && testValue.length() > maxLength )
  +        if (maxLength > 0 && testValue.length() > maxLength)
           {
               message = maxLengthMessage;
               throw new ValidationException(maxLengthMessage);
  @@ -229,19 +272,21 @@
        */
       public String getMessage()
       {
  -        if ( message == null )
  +        if (message == null)
           {
               return "";
           }
           return message;
       }
   
  -
       /**
        * Method to allow subclasses to add additional validation
  +     *
  +     * @param testValue Value to validate
  +     * @throws ValidationException validation failed
        */
       protected void doAssertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
       }
   
  @@ -251,6 +296,7 @@
   
       /**
        * Get the value of required.
  +     *
        * @return value of required.
        */
       public boolean isRequired()
  @@ -260,15 +306,17 @@
   
       /**
        * Set the value of required.
  -     * @param v  Value to assign to required.
  +     *
  +     * @param required  Value to assign to required.
        */
  -    public void setRequired(boolean  v)
  +    public void setRequired(boolean required)
       {
  -        this.required = v;
  +        this.required = required;
       }
   
       /**
        * Get the value of requiredMessage.
  +     *
        * @return value of requiredMessage.
        */
       public String getRequiredMessage()
  @@ -278,41 +326,52 @@
   
       /**
        * Set the value of requiredMessage.
  -     * @param v  Value to assign to requiredMessage.
  +     *
  +     * @param message  Value to assign to requiredMessage.
        */
  -    public void setRequiredMessage(String  v)
  +    public void setRequiredMessage(String message)
       {
  -        this.requiredMessage = v;
  +        this.requiredMessage = message;
       }
   
       /**
        * Get the value of mask.
  +     *
        * @return value of mask.
        */
       public String getMask()
       {
  -        return mask.toString();
  +        return maskString;
       }
   
       /**
        * Set the value of mask.
  -     * @param v  Value to assign to mask.
  +     *
  +     * @param mask  Value to assign to mask.
  +     * @throws InvalidMaskException the mask could not be compiled.
        */
  -    public void setMask(String  v)
  -        throws TurbineException
  +    public void setMask(String mask)
  +            throws InvalidMaskException
       {
  +        maskString = mask;
  +
  +        // Fixme. We should make this configureable by the XML file -- hps
  +        int maskOptions = Perl5Compiler.DEFAULT_MASK;
  +
           try
           {
  -            mask = new RE(v);
  +            log.debug("Compiling pattern " + maskString);
  +            maskPattern = patternCompiler.compile(maskString, maskOptions);
           }
  -        catch (org.apache.regexp.RESyntaxException e)
  +        catch (MalformedPatternException mpe)
           {
  -            throw new TurbineException(e);
  +            throw new InvalidMaskException("Could not compile pattern " + maskString, mpe);
           }
       }
   
       /**
        * Get the value of maskMessage.
  +     *
        * @return value of maskMessage.
        */
       public String getMaskMessage()
  @@ -322,15 +381,17 @@
   
       /**
        * Set the value of maskMessage.
  -     * @param v  Value to assign to maskMessage.
  +     *
  +     * @param message  Value to assign to maskMessage.
        */
  -    public void setMaskMessage(String  v)
  +    public void setMaskMessage(String message)
       {
  -        this.maskMessage = v;
  +        this.maskMessage = message;
       }
   
       /**
        * Get the value of minLength.
  +     *
        * @return value of minLength.
        */
       public int getMinLength()
  @@ -340,15 +401,17 @@
   
       /**
        * Set the value of minLength.
  -     * @param v  Value to assign to minLength.
  +     *
  +     * @param length  Value to assign to minLength.
        */
  -    public void setMinLength(int  v)
  +    public void setMinLength(int length)
       {
  -        this.minLength = v;
  +        this.minLength = length;
       }
   
       /**
        * Get the value of minLengthMessage.
  +     *
        * @return value of minLengthMessage.
        */
       public String getMinLengthMessage()
  @@ -358,15 +421,17 @@
   
       /**
        * Set the value of minLengthMessage.
  -     * @param v  Value to assign to minLengthMessage.
  +     *
  +     * @param message  Value to assign to minLengthMessage.
        */
  -    public void setMinLengthMessage(String  v)
  +    public void setMinLengthMessage(String message)
       {
  -        this.minLengthMessage = v;
  +        this.minLengthMessage = message;
       }
   
       /**
        * Get the value of maxLength.
  +     *
        * @return value of maxLength.
        */
       public int getMaxLength()
  @@ -376,15 +441,17 @@
   
       /**
        * Set the value of maxLength.
  -     * @param v  Value to assign to maxLength.
  +     *
  +     * @param length  Value to assign to maxLength.
        */
  -    public void setMaxLength(int  v)
  +    public void setMaxLength(int length)
       {
  -        this.maxLength = v;
  +        this.maxLength = length;
       }
   
       /**
        * Get the value of maxLengthMessage.
  +     *
        * @return value of maxLengthMessage.
        */
       public String getMaxLengthMessage()
  @@ -394,10 +461,11 @@
   
       /**
        * Set the value of maxLengthMessage.
  -     * @param v  Value to assign to maxLengthMessage.
  +     *
  +     * @param message  Value to assign to maxLengthMessage.
        */
  -    public void setMaxLengthMessage(String  v)
  +    public void setMaxLengthMessage(String message)
       {
  -        this.maxLengthMessage = v;
  +        this.maxLengthMessage = message;
       }
   }
  
  
  
  1.3       +57 -47    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/FileValidator.java
  
  Index: FileValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/FileValidator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- FileValidator.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ FileValidator.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -55,8 +55,8 @@
    */
   
   import java.util.Map;
  -import org.apache.regexp.RE;
  -import org.apache.turbine.util.TurbineException;
  +
  +import org.apache.turbine.services.intake.IntakeException;
   import org.apache.turbine.util.upload.FileItem;
   
   /**
  @@ -65,7 +65,6 @@
    * <table>
    * <tr><th>Name</th><th>Valid Values</th><th>Default Value</th></tr>
    * <tr><td>required</td><td>true|false</td><td>false</td></tr>
  - * <tr><td>mask</td><td>regexp</td><td>&nbsp;</td></tr>
    * <tr><td>minLength</td><td>integer</td><td>0</td></tr>
    * <tr><td>maxLength</td><td>integer</td><td>&nbsp;</td></tr>
    * </table>
  @@ -73,15 +72,14 @@
    * This validator can serve as the base class for more specific validators
    *
    * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class FileValidator
  -    implements Validator, InitableByConstraintMap
  +        implements Validator, InitableByConstraintMap
   {
       protected boolean required;
       protected String requiredMessage;
  -    protected RE mask;
  -    protected String maskMessage;
       protected int minLength;
       protected String minLengthMessage;
       protected int maxLength;
  @@ -90,7 +88,7 @@
       protected String message;
   
       public FileValidator(Map paramMap)
  -        throws TurbineException
  +            throws IntakeException
       {
           init(paramMap);
       }
  @@ -99,41 +97,41 @@
       {
       }
   
  -
       /**
        * Extract the relevant parameters from the constraints listed
        * in <rule> tags within the intake.xml file.
        *
        * @param paramMap a <code>Map</code> of <code>Rule</code>'s
        * containing constraints on the input.
  -     * @exception TurbineException if an error occurs
        */
       public void init(Map paramMap)
  -        throws TurbineException
       {
  +        // Init minLength stuff
           minLength = 0;
           minLengthMessage = null;
  +
  +        // Init maxLength stuff
           maxLength = 0;
           maxLengthMessage = null;
   
  -        Constraint constraint = (Constraint)paramMap.get("minLength");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("minLength");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               minLength = Integer.parseInt(param);
               minLengthMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("maxLength");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("maxLength");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               maxLength = Integer.parseInt(param);
               maxLengthMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("required");
  -        if ( constraint == null )
  +        constraint = (Constraint) paramMap.get("required");
  +        if (constraint == null)
           {
               required = false;
           }
  @@ -175,12 +173,11 @@
        * @exception ValidationException always thrown.
        */
       public void assertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           throw new ValidationException("this validation is not implemented");
       }
   
  -
       /**
        * Determine whether a testValue meets the criteria specified
        * in the constraints defined for this validator
  @@ -190,17 +187,17 @@
        * testValue did not pass the validation tests.
        */
       public void assertValidity(FileItem testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           message = null;
   
  -        if ( (!required && minLength == 0)
  -             && ( testValue == null || testValue.getSize() == 0) )
  +        if ((!required && minLength == 0)
  +                && (testValue == null || testValue.getSize() == 0))
           {
               return;
           }
  -        else if ( required
  -                  && ( testValue == null || testValue.getSize() == 0))
  +        else if (required
  +                && (testValue == null || testValue.getSize() == 0))
           {
               message = requiredMessage;
               throw new ValidationException(requiredMessage);
  @@ -209,12 +206,12 @@
           // allow subclasses first chance at validation
           doAssertValidity(testValue);
   
  -        if ( minLength > 0 && testValue.getSize() < minLength )
  +        if (minLength > 0 && testValue.getSize() < minLength)
           {
               message = minLengthMessage;
               throw new ValidationException(minLengthMessage);
           }
  -        if ( maxLength > 0 && testValue.getSize() > maxLength )
  +        if (maxLength > 0 && testValue.getSize() > maxLength)
           {
               message = maxLengthMessage;
               throw new ValidationException(maxLengthMessage);
  @@ -228,19 +225,21 @@
        */
       public String getMessage()
       {
  -        if ( message == null )
  +        if (message == null)
           {
               return "";
           }
           return message;
       }
   
  -
       /**
        * Method to allow subclasses to add additional validation
  +     *
  +     * @param testValue <code>FileItem</code> to validate
  +     * @throws ValidationException validation failed
        */
       protected void doAssertValidity(FileItem testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
       }
   
  @@ -250,6 +249,7 @@
   
       /**
        * Get the value of required.
  +     *
        * @return value of required.
        */
       public boolean isRequired()
  @@ -259,11 +259,12 @@
   
       /**
        * Set the value of required.
  -     * @param v  Value to assign to required.
  +     *
  +     * @param required  Value to assign to required.
        */
  -    public void setRequired(boolean  v)
  +    public void setRequired(boolean required)
       {
  -        this.required = v;
  +        this.required = required;
       }
   
       /**
  @@ -277,15 +278,17 @@
   
       /**
        * Set the value of requiredMessage.
  -     * @param v  Value to assign to requiredMessage.
  +     *
  +     * @param message  Value to assign to requiredMessage.
        */
  -    public void setRequiredMessage(String  v)
  +    public void setRequiredMessage(String message)
       {
  -        this.requiredMessage = v;
  +        this.requiredMessage = message;
       }
   
       /**
        * Get the value of minLength.
  +     *
        * @return value of minLength.
        */
       public int getMinLength()
  @@ -295,15 +298,17 @@
   
       /**
        * Set the value of minLength.
  -     * @param v  Value to assign to minLength.
  +     *
  +     * @param length  Value to assign to minLength.
        */
  -    public void setMinLength(int  v)
  +    public void setMinLength(int length)
       {
  -        this.minLength = v;
  +        this.minLength = length;
       }
   
       /**
        * Get the value of minLengthMessage.
  +     *
        * @return value of minLengthMessage.
        */
       public String getMinLengthMessage()
  @@ -313,15 +318,17 @@
   
       /**
        * Set the value of minLengthMessage.
  -     * @param v  Value to assign to minLengthMessage.
  +     *
  +     * @param message  Value to assign to minLengthMessage.
        */
  -    public void setMinLengthMessage(String  v)
  +    public void setMinLengthMessage(String message)
       {
  -        this.minLengthMessage = v;
  +        this.minLengthMessage = message;
       }
   
       /**
        * Get the value of maxLength.
  +     *
        * @return value of maxLength.
        */
       public int getMaxLength()
  @@ -331,15 +338,17 @@
   
       /**
        * Set the value of maxLength.
  -     * @param v  Value to assign to maxLength.
  +     *
  +     * @param length  Value to assign to maxLength.
        */
  -    public void setMaxLength(int  v)
  +    public void setMaxLength(int length)
       {
  -        this.maxLength = v;
  +        this.maxLength = length;
       }
   
       /**
        * Get the value of maxLengthMessage.
  +     *
        * @return value of maxLengthMessage.
        */
       public String getMaxLengthMessage()
  @@ -349,10 +358,11 @@
   
       /**
        * Set the value of maxLengthMessage.
  -     * @param v  Value to assign to maxLengthMessage.
  +     *
  +     * @param message  Value to assign to maxLengthMessage.
        */
  -    public void setMaxLengthMessage(String  v)
  +    public void setMaxLengthMessage(String message)
       {
  -        this.maxLengthMessage = v;
  +        this.maxLengthMessage = message;
       }
   }
  
  
  
  1.2       +6 -5      jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/InitableByConstraintMap.java
  
  Index: InitableByConstraintMap.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/InitableByConstraintMap.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InitableByConstraintMap.java	16 Aug 2001 05:08:59 -0000	1.1
  +++ InitableByConstraintMap.java	3 Jan 2003 07:20:44 -0000	1.2
  @@ -55,13 +55,14 @@
    */
   
   import java.util.Map;
  -import org.apache.turbine.util.TurbineException;
  +
  +import org.apache.turbine.services.intake.IntakeException;
   
   /**
    * This interface marks a bean/class that can have its properties set
    * by values in a Map.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
    * @version $Id$
    */
   public interface InitableByConstraintMap
  @@ -72,8 +73,8 @@
        *
        * @param inputParameters a <code>Map</code> of <code>Constraint</code>'s
        * containing rules and error messages.
  -     * @exception TurbineException if an error occurs
  +     * @exception InvalidMaskException one of the mask rules is invalid
        */
       public void init(Map inputParameters)
  -        throws TurbineException;
  +            throws InvalidMaskException;
   }
  
  
  
  1.4       +23 -18    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/IntegerValidator.java
  
  Index: IntegerValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/IntegerValidator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IntegerValidator.java	16 Jul 2002 16:10:22 -0000	1.3
  +++ IntegerValidator.java	3 Jan 2003 07:20:44 -0000	1.4
  @@ -55,7 +55,8 @@
    */
   
   import java.util.Map;
  -import org.apache.turbine.util.TurbineException;
  +
  +import org.apache.turbine.services.intake.IntakeException;
   
   /**
    * Validates numbers with the following constraints in addition to those
  @@ -71,11 +72,11 @@
    * <td>Entry was not a valid number</td></tr>
    * </table>
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
    * @version $Id$
    */
   public class IntegerValidator
  -    extends NumberValidator
  +        extends NumberValidator
   {
       private static String INVALID_NUMBER = "Entry was not a valid integer";
   
  @@ -83,7 +84,7 @@
       private int maxValue;
   
       public IntegerValidator(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           this();
           init(paramMap);
  @@ -100,16 +101,16 @@
           minValue = Integer.MIN_VALUE;
           maxValue = Integer.MAX_VALUE;
   
  -        Constraint constraint = (Constraint)paramMap.get("minValue");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("minValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               minValue = Integer.parseInt(param);
               minValueMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("maxValue");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("maxValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               maxValue = Integer.parseInt(param);
  @@ -131,7 +132,7 @@
        * testValue did not pass the validation tests.
        */
       protected void doAssertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           int i = 0;
           try
  @@ -144,12 +145,12 @@
               throw new ValidationException(invalidNumberMessage);
           }
   
  -        if ( i < minValue )
  +        if (i < minValue)
           {
               message = minValueMessage;
               throw new ValidationException(minValueMessage);
           }
  -        if ( i > maxValue )
  +        if (i > maxValue)
           {
               message = maxValueMessage;
               throw new ValidationException(maxValueMessage);
  @@ -163,6 +164,7 @@
   
       /**
        * Get the value of minValue.
  +     *
        * @return value of minValue.
        */
       public int getMinValue()
  @@ -172,15 +174,17 @@
   
       /**
        * Set the value of minValue.
  -     * @param v  Value to assign to minValue.
  +     *
  +     * @param value  Value to assign to minValue.
        */
  -    public void setMinValue(int  v)
  +    public void setMinValue(int value)
       {
  -        this.minValue = v;
  +        this.minValue = value;
       }
   
       /**
        * Get the value of maxValue.
  +     *
        * @return value of maxValue.
        */
       public int getMaxValue()
  @@ -190,10 +194,11 @@
   
       /**
        * Set the value of maxValue.
  -     * @param v  Value to assign to maxValue.
  +     *
  +     * @param value  Value to assign to maxValue.
        */
  -    public void setMaxValue(int  v)
  +    public void setMaxValue(int value)
       {
  -        this.maxValue = v;
  +        this.maxValue = value;
       }
   }
  
  
  
  1.5       +22 -16    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/NumberKeyValidator.java
  
  Index: NumberKeyValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/NumberKeyValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- NumberKeyValidator.java	16 Jul 2002 16:10:22 -0000	1.4
  +++ NumberKeyValidator.java	3 Jan 2003 07:20:44 -0000	1.5
  @@ -55,8 +55,9 @@
    */
   
   import java.util.Map;
  +
   import org.apache.torque.om.NumberKey;
  -import org.apache.turbine.util.TurbineException;
  +import org.apache.turbine.services.intake.IntakeException;
   
   /**
    * Validates numbers with the following constraints in addition to those
  @@ -72,11 +73,12 @@
    * <td>Entry was not a valid number</td></tr>
    * </table>
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class NumberKeyValidator
  -    extends NumberValidator
  +        extends NumberValidator
   {
       private static String INVALID_NUMBER = "Entry was not valid.";
   
  @@ -84,7 +86,7 @@
       private NumberKey maxValue;
   
       public NumberKeyValidator(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           this();
           init(paramMap);
  @@ -101,16 +103,16 @@
           minValue = null;
           maxValue = null;
   
  -        Constraint constraint = (Constraint)paramMap.get("minValue");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("minValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               minValue = new NumberKey(param);
               minValueMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("maxValue");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("maxValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               maxValue = new NumberKey(param);
  @@ -132,7 +134,7 @@
        * testValue did not pass the validation tests.
        */
       protected void doAssertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           NumberKey nk = null;
           try
  @@ -144,12 +146,12 @@
               message = invalidNumberMessage;
               throw new ValidationException(invalidNumberMessage);
           }
  -        if ( minValue != null && nk.compareTo(minValue) < 0 )
  +        if (minValue != null && nk.compareTo(minValue) < 0)
           {
               message = minValueMessage;
               throw new ValidationException(minValueMessage);
           }
  -        if ( maxValue != null && nk.compareTo(maxValue) > 0 )
  +        if (maxValue != null && nk.compareTo(maxValue) > 0)
           {
               message = maxValueMessage;
               throw new ValidationException(maxValueMessage);
  @@ -163,6 +165,7 @@
   
       /**
        * Get the value of minValue.
  +     *
        * @return value of minValue.
        */
       public NumberKey getMinValue()
  @@ -172,15 +175,17 @@
   
       /**
        * Set the value of minValue.
  +     *
        * @param v  Value to assign to minValue.
        */
  -    public void setMinValue(NumberKey  v)
  +    public void setMinValue(NumberKey v)
       {
           this.minValue = v;
       }
   
       /**
        * Get the value of maxValue.
  +     *
        * @return value of maxValue.
        */
       public NumberKey getMaxValue()
  @@ -190,10 +195,11 @@
   
       /**
        * Set the value of maxValue.
  -     * @param v  Value to assign to maxValue.
  +     *
  +     * @param value  Value to assign to maxValue.
        */
  -    public void setMaxValue(NumberKey  v)
  +    public void setMaxValue(NumberKey value)
       {
  -        this.maxValue = v;
  +        this.maxValue = value;
       }
   }
  
  
  
  1.5       +45 -35    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/NumberValidator.java
  
  Index: NumberValidator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/NumberValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- NumberValidator.java	16 Jul 2002 16:10:22 -0000	1.4
  +++ NumberValidator.java	3 Jan 2003 07:20:44 -0000	1.5
  @@ -56,7 +56,6 @@
   
   import java.math.BigDecimal;
   import java.util.Map;
  -import org.apache.turbine.util.TurbineException;
   
   /**
    * Validates numbers with the following constraints in addition to those
  @@ -72,11 +71,12 @@
    * <td>Entry was not a valid number</td></tr>
    * </table>
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class NumberValidator
  -    extends DefaultValidator
  +        extends DefaultValidator
   {
       private static String INVALID_NUMBER = "Entry was not a valid number";
   
  @@ -87,7 +87,7 @@
       protected String invalidNumberMessage;
   
       public NumberValidator(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           this();
           init(paramMap);
  @@ -100,14 +100,14 @@
   
       /**
        * Extract the relevant parameters from the constraints listed
  -     * in <input-param> tags within the intake.xml file.
  +     * in <rule> tags within the intake.xml file.
        *
  -     * @param inputParameters a <code>Map</code> of <code>InputParam</code>'s
  +     * @param paramMap a <code>Map</code> of <code>rule</code>'s
        * containing constraints on the input.
  -     * @exception TurbineException if an error occurs
  +     * @exception InvalidMaskException an invalid mask was specified
        */
       public void init(Map paramMap)
  -        throws TurbineException
  +            throws InvalidMaskException
       {
           super.init(paramMap);
   
  @@ -116,15 +116,15 @@
   
           doInit(paramMap);
   
  -        Constraint constraint = (Constraint)paramMap.get("notANumberMessage");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("notANumberMessage");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
  -            if ( param != null && param.length() != 0 )
  +            if (param != null && param.length() != 0)
               {
                   invalidNumberMessage = param;
               }
  -            else if ( constraint.getMessage().length() != 0 )
  +            else if (constraint.getMessage().length() != 0)
               {
                   invalidNumberMessage = constraint.getMessage();
               }
  @@ -136,16 +136,16 @@
           minValue = null;
           maxValue = null;
   
  -        Constraint constraint = (Constraint)paramMap.get("minValue");
  -        if ( constraint != null )
  +        Constraint constraint = (Constraint) paramMap.get("minValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               minValue = new BigDecimal(param);
               minValueMessage = constraint.getMessage();
           }
   
  -        constraint = (Constraint)paramMap.get("maxValue");
  -        if ( constraint != null )
  +        constraint = (Constraint) paramMap.get("maxValue");
  +        if (constraint != null)
           {
               String param = constraint.getValue();
               maxValue = new BigDecimal(param);
  @@ -167,7 +167,7 @@
        * testValue did not pass the validation tests.
        */
       protected void doAssertValidity(String testValue)
  -        throws ValidationException
  +            throws ValidationException
       {
           BigDecimal bd = null;
           try
  @@ -180,12 +180,12 @@
               throw new ValidationException(invalidNumberMessage);
           }
   
  -        if ( minValue != null && bd.compareTo(minValue) < 0 )
  +        if (minValue != null && bd.compareTo(minValue) < 0)
           {
               message = minValueMessage;
               throw new ValidationException(minValueMessage);
           }
  -        if ( maxValue != null && bd.compareTo(maxValue) > 0 )
  +        if (maxValue != null && bd.compareTo(maxValue) > 0)
           {
               message = maxValueMessage;
               throw new ValidationException(maxValueMessage);
  @@ -198,6 +198,7 @@
   
       /**
        * Get the value of minValue.
  +     *
        * @return value of minValue.
        */
       public BigDecimal getMinValueAsBigDecimal()
  @@ -207,15 +208,17 @@
   
       /**
        * Set the value of minValue.
  -     * @param v  Value to assign to minValue.
  +     *
  +     * @param value  Value to assign to minValue.
        */
  -    public void setMinValue(BigDecimal  v)
  +    public void setMinValue(BigDecimal value)
       {
  -        this.minValue = v;
  +        this.minValue = value;
       }
   
       /**
        * Get the value of minValueMessage.
  +     *
        * @return value of minValueMessage.
        */
       public String getMinValueMessage()
  @@ -225,15 +228,17 @@
   
       /**
        * Set the value of minValueMessage.
  -     * @param v  Value to assign to minValueMessage.
  +     *
  +     * @param message  Value to assign to minValueMessage.
        */
  -    public void setMinValueMessage(String  v)
  +    public void setMinValueMessage(String message)
       {
  -        this.minValueMessage = v;
  +        this.minValueMessage = message;
       }
   
       /**
        * Get the value of maxValue.
  +     *
        * @return value of maxValue.
        */
       public BigDecimal getMaxValueAsBigDecimal()
  @@ -243,15 +248,17 @@
   
       /**
        * Set the value of maxValue.
  -     * @param v  Value to assign to maxValue.
  +     *
  +     * @param value  Value to assign to maxValue.
        */
  -    public void setMaxValue(BigDecimal  v)
  +    public void setMaxValue(BigDecimal value)
       {
  -        this.maxValue = v;
  +        this.maxValue = value;
       }
   
       /**
        * Get the value of maxValueMessage.
  +     *
        * @return value of maxValueMessage.
        */
       public String getMaxValueMessage()
  @@ -261,15 +268,17 @@
   
       /**
        * Set the value of maxValueMessage.
  -     * @param v  Value to assign to maxValueMessage.
  +     *
  +     * @param message  Value to assign to maxValueMessage.
        */
  -    public void setMaxValueMessage(String  v)
  +    public void setMaxValueMessage(String message)
       {
  -        this.maxValueMessage = v;
  +        this.maxValueMessage = message;
       }
   
       /**
        * Get the value of invalidNumberMessage.
  +     *
        * @return value of invalidNumberMessage.
        */
       public String getInvalidNumberMessage()
  @@ -278,12 +287,13 @@
       }
   
       /**
  +     *
        * Set the value of invalidNumberMessage.
  -     * @param v  Value to assign to invalidNumberMessage.
  +     * @param message  Value to assign to invalidNumberMessage.
        */
  -    public void setInvalidNumberMessage(String  v)
  +    public void setInvalidNumberMessage(String message)
       {
  -        this.invalidNumberMessage = v;
  +        this.invalidNumberMessage = message;
       }
   
   }
  
  
  
  1.2       +12 -30    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/ValidationException.java
  
  Index: ValidationException.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/ValidationException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ValidationException.java	16 Aug 2001 05:08:59 -0000	1.1
  +++ ValidationException.java	3 Jan 2003 07:20:44 -0000	1.2
  @@ -1,5 +1,7 @@
   package org.apache.turbine.services.intake.validator;
   
  +import org.apache.turbine.services.intake.IntakeException;
  +
   /* ====================================================================
    * The Apache Software License, Version 1.1
    *
  @@ -25,13 +27,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -56,15 +58,14 @@
   
   /**
    * An Exception to mark a failed validation
  - * 
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + *
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class ValidationException
  -    extends Exception
  +        extends IntakeException
   {
  -    private String message;
  -
       /**
        * Creates a new <code>ValidationException</code> instance.
        *
  @@ -72,25 +73,6 @@
        */
       public ValidationException(String message)
       {
  -        setMessage(message);
  -    }
  -    
  -    /**
  -     * Get the value of message.
  -     * @return value of message.
  -     */
  -    public String getMessage() 
  -    {
  -        return message;
  -    }
  -    
  -    /**
  -     * Set the value of message.
  -     * @param v  Value to assign to message.
  -     */
  -    public void setMessage(String  v) 
  -    {
  -        this.message = v;
  +        super(message);
       }
  -    
   }
  
  
  
  1.3       +3 -4      jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/Validator.java
  
  Index: Validator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/Validator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Validator.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ Validator.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -54,11 +54,10 @@
    * <http://www.apache.org/>.
    */
   
  -
   /**
    * Validator api.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
    * @version $Id$
    */
   public interface Validator
  @@ -81,7 +80,7 @@
        * testValue did not pass the validation tests.
        */
       public void assertValidity(String testValue)
  -        throws ValidationException;
  +            throws ValidationException;
   
       /**
        * Get the last error message resulting from invalid input.
  
  
  
  1.1                  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/BooleanValidator.java
  
  Index: BooleanValidator.java
  ===================================================================
  package org.apache.turbine.services.intake.validator;
  
  import java.util.Map;
  import java.util.Vector;
  import java.util.Iterator;
  import java.math.BigDecimal;
  import java.text.ParseException;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" 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",
   *    "Apache Turbine", nor may "Apache" appear in their name, 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/>.
   */
  
  /**
   * Validator for boolean field types.<br><br>
   *
   * Values are validated by attemting to match the value to
   * a list of strings for true and false values.  The string
   * values are compared without reguard to case.<br>
   *
   * Valid values for Boolean.TRUE:
   * <ul>
   * <li>TRUE</li>
   * <li>T</li>
   * <li>YES</li>
   * <li>Y</li>
   * <li>1</li>
   * </ul>
   * Valid values for Boolean.FALSE:
   * <ul>
   * <li>FALSE</li>
   * <li>F</li>
   * <li>NO</li>
   * <li>N</li>
   * <li>0</li>
   * </ul>
   *
   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
   * @version $Id: BooleanValidator.java,v 1.1 2003/01/03 07:20:44 quintonm Exp $
   */
  public class BooleanValidator
          extends DefaultValidator
  {
      /** Default error message if the boolean can not be parsed. */
      private static final String INVALID_BOOLEAN = "Not a boolean value";
  
      /** String values which would evaluate to Boolean.TRUE */
      private static Vector trueValues;
  
      /** String values which would evaluate to Boolean.FALSE */
      private static Vector falseValues;
  
      static
      {
          trueValues = new Vector();
          trueValues.add("TRUE");
          trueValues.add("T");
          trueValues.add("YES");
          trueValues.add("Y");
          trueValues.add("1");
  
          falseValues = new Vector();
          falseValues.add("FALSE");
          falseValues.add("F");
          falseValues.add("NO");
          falseValues.add("N");
          falseValues.add("0");
      }
  
      public BooleanValidator()
      {
      }
  
      public BooleanValidator(Map paramMap)
              throws InvalidMaskException
      {
          super(paramMap);
      }
  
  
      /**
       * Determine whether a testValue meets the criteria specified
       * in the constraints defined for this validator
       *
       * @param testValue a <code>String</code> to be tested
       * @exception ValidationException containing an error message if the
       * testValue did not pass the validation tests.
       */
      protected void doAssertValidity(String testValue)
              throws ValidationException
      {
          try
          {
              parse(testValue);
          }
          catch (ParseException e)
          {
              throw new ValidationException(INVALID_BOOLEAN);
          }
      }
  
      /**
       * Parses a srting value into a Boolean object.
       *
       * @param stringValue the value to parse
       * @return a <code>Boolean</a> object
       */
      public Boolean parse( String stringValue )
              throws ParseException
      {
          Boolean result = null;
          for( Iterator iter = trueValues.iterator(); iter.hasNext() && result == null; )
          {
              String trueValue = (String) iter.next();
              if( trueValue.equalsIgnoreCase( stringValue))
              {
                  result = Boolean.TRUE;
              }
          }
  
          for( Iterator iter = falseValues.iterator(); iter.hasNext() && result == null; )
          {
              String falseValue = (String) iter.next();
              if( falseValue.equalsIgnoreCase( stringValue))
              {
                  result = Boolean.FALSE;
              }
          }
  
          if( result == null )
          {
              throw new ParseException( stringValue +
                      " could not be converted to a Boolean", 0);
          }
  
          return result;
      }
  
  
  }
  
  
  
  1.1                  jakarta-turbine-2/src/java/org/apache/turbine/services/intake/validator/InvalidMaskException.java
  
  Index: InvalidMaskException.java
  ===================================================================
  package org.apache.turbine.services.intake.validator;
  
  import org.apache.turbine.services.intake.IntakeException;
  
  /**
   * An Exception indidate an invalid field mask.
   *
   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
   * @version $Id: InvalidMaskException.java,v 1.1 2003/01/03 07:20:44 quintonm Exp $
   */
  public class InvalidMaskException
          extends IntakeException
  {
      /**
       * Creates a new <code>InvalidMaskException</code> instance.
       *
       * @param message describing the reason validation failed.
       */
      public InvalidMaskException(String message)
      {
          super(message);
      }
  
      /**
       * Creates a new <code>InvalidMaskException</code> instance.
       *
       * @param cause Cause of the exception
       * @param message describing the reason validation failed.
       */
      public InvalidMaskException(String message, Throwable cause)
      {
          super(message, cause);
      }
  }
  
  
  
  1.3       +95 -33    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/AppData.java
  
  Index: AppData.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/AppData.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AppData.java	9 Oct 2001 14:14:30 -0000	1.2
  +++ AppData.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -25,13 +25,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -57,21 +57,30 @@
   import java.util.ArrayList;
   import java.util.Iterator;
   import java.util.List;
  +
  +import org.apache.turbine.services.intake.IntakeException;
  +
   import org.xml.sax.Attributes;
   
   /**
    * A class for holding application data structures.
    *
    * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    * @version $Id$
    */
   public class AppData
  -    implements java.io.Serializable
  +        implements java.io.Serializable
   {
  -
  +    /** List of groups */
       private List inputs;
  +
  +    /** Package that will be used for all mapTo objects */
       private String basePackage;
   
  +    /** Prefix string that will be used to qualify &lt;prefix&gt;:&lt;intakegroup&gt; names */
  +    private String groupPrefix;
  +
       /**
        * Default Constructor
        */
  @@ -83,28 +92,35 @@
       /**
        * Imports the top level element from an XML specification
        */
  -    public void loadFromXML (Attributes attrib)
  +    public void loadFromXML(Attributes attrib)
       {
           String basePkg = attrib.getValue("basePackage");
  -        if ( basePkg == null )
  +        if (basePkg == null)
           {
               setBasePackage("");
           }
           else
  -        {            
  -            if ( basePkg.charAt(basePkg.length()-1) != '.' ) 
  +        {
  +            if (basePkg.charAt(basePkg.length() - 1) != '.')
               {
  -                setBasePackage(basePkg + '.');                
  +                setBasePackage(basePkg + '.');
               }
               else
               {
                   setBasePackage(basePkg);
               }
           }
  +
  +        setGroupPrefix(attrib.getValue("groupPrefix"));
       }
   
       /**
  -     * Return a collection of input sections (<group>)
  +     * Return a collection of input sections (&lt;group&gt;).
  +     * The names of the groups returned here are only unique
  +     * to this AppData object and not qualified with the groupPrefix.
  +     * This method is used in the IntakeService to register all the
  +     * groups with and without prefix in the service.
  +     *
        */
       public List getGroups()
       {
  @@ -112,22 +128,47 @@
       }
   
       /**
  -     * Get a XmlGroup with the given name.
  +     * Get a XmlGroup with the given name. It finds both
  +     * qualified and unqualified names in this package.
        *
        * @param groupName a <code>String</code> value
        * @return a <code>XmlGroup</code> value
  +     * @throws IntakeException indicates that the groupName was null
        */
       public XmlGroup getGroup(String groupName)
  +            throws IntakeException
       {
  -        XmlGroup group = null;
  -        Iterator iter = inputs.iterator();
  -        do 
  +        if (groupName == null)
  +        {
  +            throw new IntakeException(
  +                    "Intake AppData.getGroup(groupName) is null");
  +        }
  +
  +        String groupPrefix = getGroupPrefix();
  +
  +        for (Iterator it = inputs.iterator(); it.hasNext();)
           {
  -            group = (XmlGroup)iter.next();
  -    
  -        } while (!group.getName().equals(groupName));
  -        
  -        return group;
  +            XmlGroup group = (XmlGroup) it.next();
  +
  +            if (group.getName().equals(groupName))
  +            {
  +                return group;
  +            }
  +            if (groupPrefix != null)
  +            {
  +                StringBuffer qualifiedGroupName = new StringBuffer();
  +
  +                qualifiedGroupName.append(groupPrefix)
  +                        .append(":")
  +                        .append(group.getName());
  +
  +                if (qualifiedGroupName.toString().equals(groupName))
  +                {
  +                    return group;
  +                }
  +            }
  +        }
  +        return null;
       }
   
       /**
  @@ -152,29 +193,50 @@
           inputs.add(input);
       }
   
  -    
       /**
        * Get the base package String that will be appended to
        * any mapToObjects
        *
        * @return value of basePackage.
        */
  -    public String getBasePackage() 
  +    public String getBasePackage()
       {
           return basePackage;
       }
  -    
  +
       /**
  -     * Get the base package String that will be appended to
  +     * Set the base package String that will be appended to
        * any mapToObjects
        *
        * @param v  Value to assign to basePackage.
        */
  -    public void setBasePackage(String  v) 
  +    public void setBasePackage(String v)
       {
           this.basePackage = v;
       }
  -    
  +
  +    /**
  +     * Get the prefix String that will be used to qualify
  +     * intake groups when using multiple XML files
  +     *
  +     * @return value of groupPrefix
  +     */
  +    public String getGroupPrefix()
  +    {
  +        return groupPrefix;
  +    }
  +
  +    /**
  +     * Set the prefix String that will be used to qualify
  +     * intake groups when using multiple XML files
  +     *
  +     * @param groupPrefix  Value to assign to basePackage.
  +     */
  +    public void setGroupPrefix(String groupPrefix)
  +    {
  +        this.groupPrefix = groupPrefix;
  +    }
  +
       /**
        * Creats a string representation of this AppData.
        * The representation is given in xml format.
  @@ -183,12 +245,12 @@
       {
           StringBuffer result = new StringBuffer();
   
  -        result.append ("<input-data>\n");
  -        for (Iterator iter = inputs.iterator() ; iter.hasNext() ;)
  +        result.append("<input-data>\n");
  +        for (Iterator iter = inputs.iterator(); iter.hasNext();)
           {
  -            result.append (iter.next());
  +            result.append(iter.next());
           }
  -        result.append ("</input-data>");
  +        result.append("</input-data>");
           return result.toString();
  -  }
  +    }
   }
  
  
  
  1.3       +11 -9     jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/Rule.java
  
  Index: Rule.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/Rule.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Rule.java	11 Jul 2002 16:53:27 -0000	1.2
  +++ Rule.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -55,16 +55,17 @@
    */
   
   import org.apache.turbine.services.intake.validator.Constraint;
  +
   import org.xml.sax.Attributes;
   
   /**
    * A Class for holding data about a constraint on a property.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
    * @version $Id$
    */
   public class Rule
  -    implements Constraint, java.io.Serializable
  +        implements Constraint, java.io.Serializable
   {
       private String name;
       private String value;
  @@ -81,7 +82,7 @@
       /**
        * Imports a column from an XML specification
        */
  -    public void loadFromXML (Attributes attrib)
  +    public void loadFromXML(Attributes attrib)
       {
           setName(attrib.getValue("name"));
           setValue(attrib.getValue("value"));
  @@ -94,6 +95,7 @@
       {
           name = newName;
       }
  +
       /**
        * Get the name of the parameter
        */
  @@ -109,6 +111,7 @@
       {
           value = newValue;
       }
  +
       /**
        * Get the value of the parameter
        */
  @@ -157,9 +160,8 @@
       {
           StringBuffer result = new StringBuffer(100);
   
  -        result.append("<rule name=\""+name+"\"")
  -              .append(" value=\""+value+"\"");
  -
  +        result.append("<rule name=\"" + name + "\"")
  +                .append(" value=\"" + value + "\"");
   
           if (message == null)
           {
  @@ -168,8 +170,8 @@
           else
           {
               result.append(">")
  -                  .append(message)
  -                  .append("</rule>\n");
  +                    .append(message)
  +                    .append("</rule>\n");
           }
   
           return result.toString();
  
  
  
  1.3       +59 -176   jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/XmlField.java
  
  Index: XmlField.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/XmlField.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XmlField.java	9 Oct 2001 14:44:39 -0000	1.2
  +++ XmlField.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -25,13 +25,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -54,32 +54,32 @@
    * <http://www.apache.org/>.
    */
   
  -import java.util.HashMap;
  -import java.util.Map;
  -import java.util.List;
  +import java.io.Serializable;
   import java.util.ArrayList;
  +import java.util.HashMap;
   import java.util.Iterator;
  -import org.apache.turbine.util.StringUtils;
  +import java.util.List;
  +import java.util.Map;
  +
  +import org.apache.commons.lang.StringUtils;
  +
   import org.xml.sax.Attributes;
   
   /**
    * A Class for holding data about a property used in an Application.
    *
  - * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
  + * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  + * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    * @version $Id$
    */
   public class XmlField
  -    implements java.io.Serializable
  +        implements Serializable
   {
  -    private static final String DEFAULT_VALIDATOR = 
  -        "org.apache.turbine.services.intake.validator.DefaultValidator";
  -
  -    private String baseClass;
       private String name;
       private String key;
       private String type;
       private String displayName;
  -    private String onError;
       private String multiValued;
       private XmlGroup parent;
       private List rules;
  @@ -90,59 +90,6 @@
       private String validator;
       private String defaultValue;
   
  -    private static HashMap defaultOnErrors;
  -    private static HashMap convertHash;
  -    private static HashMap convertArrayHash;
  -
  -    // static
  -    {
  -        populateDefaults();
  -    }
  - 
  -    private static void populateDefaults()
  -    {
  -        defaultOnErrors = new HashMap(15);
  -        convertHash = new HashMap(15);
  -        convertArrayHash = new HashMap(15);
  -
  -        defaultOnErrors.put("boolean", "false");
  -        defaultOnErrors.put("byte", "-1");
  -        defaultOnErrors.put("short", "-1");
  -        defaultOnErrors.put("int", "-1");
  -        defaultOnErrors.put("long", "-1");
  -        defaultOnErrors.put("float", "-1.0f");
  -        defaultOnErrors.put("double", "-1.0");
  -        defaultOnErrors.put("BigDecimal", "new BigDecimal(\"-1.0\")");
  -        // defaultOnErrors.put("BigInteger", "new BigInteger(\"-1\")");
  -
  -        convertHash.put("boolean", "getBoolean");
  -        convertHash.put("byte", "getByte");
  -        convertHash.put("short", "getShort");
  -        convertHash.put("int", "getInt");
  -        convertHash.put("long", "getLong");
  -        convertHash.put("float", "getFloat");
  -        convertHash.put("double", "getDouble");
  -        convertHash.put("Date", "getDate");
  -        convertHash.put("BigDecimal", "getBigDecimal");
  -        // convertHash.put("BigInteger", "getBigInteger");
  -
  -        convertHash.put("boolean[]", 
  -                        "Boolean.valueOf(stringValue[i]).booleanValue()");
  -        convertArrayHash.put("byte[]", 
  -                             "Byte.valueOf(stringValue[i]).byteValue()");
  -        convertArrayHash.put("short[]", 
  -                             "Short.valueOf(stringValue[i]).shortValue()");
  -        convertArrayHash.put("int[]", "Integer.parseInt(stringValue[i])");
  -        convertArrayHash.put("long[]", "Long.parseLong(stringValue[i])");
  -        convertArrayHash.put("float[]", 
  -                             "Float.valueOf(stringValue[i]).floatValue()");
  -        convertArrayHash.put("double[]", 
  -                             "Double.valueOf(stringValue[i]).doubleValue()");
  -        convertArrayHash.put("Date[]", "FIXME!!");
  -        convertArrayHash.put("BigDecimal[]", "new BigDecimal(stringValue[i])");
  -        // convertHash.put("BigInteger", "new BigInteger(stringValue)");
  -    }    
  -
       /**
        * Default Constructor
        */
  @@ -152,7 +99,6 @@
           ruleMap = new HashMap();
       }
   
  -
       /**
        * Creates a new column and set the name
        */
  @@ -166,32 +112,29 @@
       /**
        * Imports a column from an XML specification
        */
  -    public void loadFromXML (Attributes attrib)
  +    public void loadFromXML(Attributes attrib)
       {
  -        setBaseClass(attrib.getValue("baseClass"));
           setName(attrib.getValue("name"));
           key = attrib.getValue("key");
           type = attrib.getValue("type");
           displayName = attrib.getValue("displayName");
  -        //setOnError(attrib.getValue("onError"));
           setMultiValued(attrib.getValue("multiValued"));
   
           String mapObj = attrib.getValue("mapToObject");
  -        if ( mapObj != null && mapObj.length() != 0 ) 
  +        if (mapObj != null && mapObj.length() != 0)
           {
  -            setMapToObject(mapObj);            
  +            setMapToObject(mapObj);
           }
   
  -        String mapProp = attrib.getValue("mapToProperty");        
  -        if ( mapProp != null ) 
  +        String mapProp = attrib.getValue("mapToProperty");
  +        if (mapProp != null)
           {
  -            setMapToProperty(mapProp);            
  +            setMapToProperty(mapProp);
           }
           setValidator(attrib.getValue("validator"));
           setDefaultValue(attrib.getValue("defaultValue"));
       }
   
  -
       /**
        * Get the name of the property
        */
  @@ -205,7 +148,7 @@
        */
       public String getName()
       {
  -        return StringUtils.removeUnderScores(name);
  +        return StringUtils.replace(name, "_", "");
       }
   
       /**
  @@ -239,6 +182,7 @@
       {
           key = newKey;
       }
  +
       /**
        * Get the parameter key of the property
        */
  @@ -260,53 +204,10 @@
        */
       public String getType()
       {
  -        /*
  -          if ( isMultiValued() ) 
  -          {
  -          return type + "[]";    
  -          } 
  -        */  
           return type;
       }
   
       /**
  -     * Set the base class of the field
  -     */
  -    public void setBaseClass(String newBaseClass)
  -    {
  -        baseClass = newBaseClass;
  -    }
  -
  -    /**
  -     * Get the base class of the field
  -     */
  -    public String getBaseClass()
  -    {
  -        return baseClass;
  -    }
  -
  -    /* *
  -     * Set the value of the property, if a conversion error occurs.
  -     * /
  -     public void setOnError(String newOnError)
  -     {
  -     onError = newOnError;
  -     }
  -
  -     /**
  -     * Get the value of the property, if a conversion error occurs.
  -     * /
  -     public String getOnError()
  -     {
  -     if ( onError == null && defaultOnErrors.containsKey(getType()) ) 
  -     {
  -     onError = (String)defaultOnErrors.get(getType());
  -     }
  -     return onError;
  -     }
  -    */
  -
  -    /**
        * Set whether this class can have multiple values
        */
       public void setMultiValued(String newMultiValued)
  @@ -319,7 +220,7 @@
        */
       public boolean isMultiValued()
       {
  -        if ( multiValued != null && multiValued.equals("true") )
  +        if (multiValued != null && multiValued.equals("true"))
           {
               return true;
           }
  @@ -328,10 +229,12 @@
   
       /**
        * Set the name of the object that takes this input
  +     *
  +     * @param objectName name of the class.
        */
  -    public void setMapToObject(String obj)
  +    public void setMapToObject(String objectName)
       {
  -        mapToObject = obj;
  +        mapToObject = objectName;
       }
   
       /**
  @@ -344,6 +247,8 @@
   
       /**
        * Set the property method that takes this input
  +     *
  +     * @param prop Name of the property to which the field will be mapped.
        */
       public void setMapToProperty(String prop)
       {
  @@ -355,7 +260,7 @@
        */
       public String getMapToProperty()
       {
  -        if ( mapToProperty == null ) 
  +        if (mapToProperty == null)
           {
               return getName();
           }
  @@ -380,9 +285,11 @@
       {
           return validator;
       }
  -    
  +
       /**
  -     * Set the default Value
  +     * Set the default Value.
  +     *
  +     * @param prop The parameter to use as default value.
        */
       public void setDefaultValue(String prop)
       {
  @@ -390,51 +297,34 @@
       }
   
       /**
  -     * Get the default Value
  +     * Get the default Value.
  +     *
  +     * @return The default value for this field.
        */
       public String getDefaultValue()
       {
           return defaultValue;
       }
  -    
  +
       /**
        * The name of the field making sure the first letter is lowercase.
        *
        * @return a <code>String</code> value
  +     * @deprecated No replacement
        */
       public String getVariable()
       {
  -        String firstChar = getName().substring(0,1).toLowerCase();
  +        String firstChar = getName().substring(0, 1).toLowerCase();
           return firstChar + getName().substring(1);
       }
   
  -    public String getPPMethod()
  -    {
  -        String result = null;
  -        if ( convertHash.containsKey(getType())) 
  -        {
  -            result = (String)convertHash.get(getType());    
  -        }
  -        return result;
  -    }        
  -
  -    public String getArrayConvert()
  -    {
  -        String result = null;
  -        if ( convertArrayHash.containsKey(getType())) 
  -        {
  -            result = (String)convertArrayHash.get(getType());    
  -        }
  -        return result;
  -    }        
  -
       /**
        * Set the parent XmlGroup of the property
        */
       public void setGroup(XmlGroup parent)
       {
           this.parent = parent;
  -        if ( mapToObject != null && mapToObject.length() != 0 ) 
  +        if (mapToObject != null && mapToObject.length() != 0)
           {
               mapToObject = parent.getAppData().getBasePackage() + mapToObject;
           }
  @@ -452,16 +342,16 @@
        * Get the value of ifRequiredMessage.
        * @return value of ifRequiredMessage.
        */
  -    public String getIfRequiredMessage() 
  +    public String getIfRequiredMessage()
       {
           return ifRequiredMessage;
       }
  -    
  +
       /**
        * Set the value of ifRequiredMessage.
        * @param v  Value to assign to ifRequiredMessage.
        */
  -    public void setIfRequiredMessage(String  v) 
  +    public void setIfRequiredMessage(String v)
       {
           this.ifRequiredMessage = v;
       }
  @@ -518,66 +408,59 @@
       public String toString()
       {
           StringBuffer result = new StringBuffer();
  -        result.append(" <field name=\""+name+"\"");
  -        result.append(" key=\""+key+"\"");
  -        result.append(" type=\""+type+"\"");
  +        result.append(" <field name=\"" + name + "\"");
  +        result.append(" key=\"" + key + "\"");
  +        result.append(" type=\"" + type + "\"");
   
           if (displayName != null)
           {
  -            result.append(" displayName=\""+displayName+"\"");
  -        }
  -        if (onError != null)
  -        {
  -            result.append(" onError=\""+onError+"\"");
  +            result.append(" displayName=\"" + displayName + "\"");
           }
           if (mapToObject != null)
           {
  -            result.append(" mapToObject=\""+mapToObject+"\"");
  +            result.append(" mapToObject=\"" + mapToObject + "\"");
           }
           if (mapToProperty != null)
           {
  -            result.append(" mapToProperty=\""+mapToProperty+"\"");
  +            result.append(" mapToProperty=\"" + mapToProperty + "\"");
           }
           if (validator != null)
           {
  -            result.append(" validator=\""+validator+"\"");
  +            result.append(" validator=\"" + validator + "\"");
           }
           if (defaultValue != null)
           {
  -            result.append(" defaultValue=\""+defaultValue+"\"");
  +            result.append(" defaultValue=\"" + defaultValue + "\"");
           }
   
  -
  -        if ( rules.size() == 0 )
  +        if (rules.size() == 0)
           {
               result.append(" />\n");
           }
           else
           {
               result.append(">\n");
  -            for (Iterator i = rules.iterator() ; i.hasNext() ;)
  +            for (Iterator i = rules.iterator(); i.hasNext();)
               {
                   result.append(i.next());
               }
               result.append("</field>\n");
  -        }        
  +        }
   
           return result.toString();
       }
   
       // this methods are called during serialization
       private void writeObject(java.io.ObjectOutputStream stream)
  -        throws java.io.IOException
  +            throws java.io.IOException
       {
           stream.defaultWriteObject();
       }
   
       private void readObject(java.io.ObjectInputStream stream)
  -        throws java.io.IOException, ClassNotFoundException
  +            throws java.io.IOException, ClassNotFoundException
       {
           stream.defaultReadObject();
  -        populateDefaults();
       }
  -
   
   }
  
  
  
  1.3       +32 -33    jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/XmlGroup.java
  
  Index: XmlGroup.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/services/intake/xmlmodel/XmlGroup.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XmlGroup.java	9 Oct 2001 14:14:30 -0000	1.2
  +++ XmlGroup.java	3 Jan 2003 07:20:44 -0000	1.3
  @@ -25,13 +25,13 @@
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
    *
  - * 4. The names "Apache" and "Apache Software Foundation" and 
  - *    "Apache Turbine" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission. For 
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache Turbine" 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",
  - *    "Apache Turbine", nor may "Apache" appear in their name, without 
  + *    "Apache Turbine", nor may "Apache" appear in their name, without
    *    prior written permission of the Apache Software Foundation.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  @@ -54,9 +54,11 @@
    * <http://www.apache.org/>.
    */
   
  +import java.io.Serializable;
   import java.util.ArrayList;
   import java.util.Iterator;
   import java.util.List;
  +
   import org.xml.sax.Attributes;
   
   /**
  @@ -66,7 +68,7 @@
    * @version $Id$
    */
   public class XmlGroup
  -    implements java.io.Serializable
  +        implements Serializable
   {
       private List fields;
       private List mapToObjects;
  @@ -88,14 +90,14 @@
       /**
        * Load the input group object from an xml tag.
        */
  -    public void loadFromXML (Attributes attrib)
  +    public void loadFromXML(Attributes attrib)
       {
           groupName = attrib.getValue("name");
           key = attrib.getValue("key");
           poolCapacity = attrib.getValue("pool-capacity");
  -        
  +
           String objName = attrib.getValue("mapToObject");
  -        if ( objName != null && objName.length() != 0 ) 
  +        if (objName != null && objName.length() != 0)
           {
               defaultMapToObject = objName;
           }
  @@ -133,7 +135,6 @@
           key = newKey;
       }
   
  -
       /**
        * The maximum number of classes specific to this group
        * allowed at one time.
  @@ -142,11 +143,11 @@
        */
       public String getPoolCapacity()
       {
  -        if ( poolCapacity == null ) 
  +        if (poolCapacity == null)
           {
               return "128";
           }
  -        
  +
           return poolCapacity;
       }
   
  @@ -173,30 +174,30 @@
   
           // if this field has an object defined for mapping,
           // add it to the list
  -        if ( field.getMapToObject() != null ) 
  +        if (field.getMapToObject() != null)
           {
               boolean isNewObject = true;
  -            for ( int i=0; i<mapToObjects.size(); i++ ) 
  +            for (int i = 0; i < mapToObjects.size(); i++)
               {
  -                if ( mapToObjects.get(i).equals(field.getMapToObject()) ) 
  +                if (mapToObjects.get(i).equals(field.getMapToObject()))
                   {
                       isNewObject = false;
                       break;
                   }
               }
  -            if ( isNewObject ) 
  +            if (isNewObject)
               {
                   mapToObjects.add(field.getMapToObject());
               }
           }
           // if a mapToProperty exists, set the object to this group's default
  -        else if( field.getMapToProperty() != null
  -                 && !"".equals(field.getMapToProperty())
  -                 && defaultMapToObject != null )
  +        else if (field.getMapToProperty() != null
  +                && !"".equals(field.getMapToProperty())
  +                && defaultMapToObject != null)
           {
               field.setMapToObject(defaultMapToObject);
           }
  -        
  +
           fields.add(field);
       }
   
  @@ -216,7 +217,6 @@
           return fields.size();
       }
   
  -
       /**
        * Returns a Specified field.
        * @return Return a XmlField object or null if it does not exist.
  @@ -225,7 +225,7 @@
       {
           String curName;
   
  -        for (Iterator iter = fields.iterator() ; iter.hasNext() ;)
  +        for (Iterator iter = fields.iterator(); iter.hasNext();)
           {
               XmlField field = (XmlField) iter.next();
               curName = field.getRawName();
  @@ -242,7 +242,7 @@
        */
       public boolean containsField(XmlField field)
       {
  -        return fields.contains (field);
  +        return fields.contains(field);
       }
   
       /**
  @@ -250,7 +250,7 @@
        */
       public boolean containsField(String name)
       {
  -        return (getField (name) != null);
  +        return (getField(name) != null);
       }
   
       public List getMapToObjects()
  @@ -264,8 +264,8 @@
       public void setAppData(AppData parent)
       {
           this.parent = parent;
  -        if (defaultMapToObject != null ) 
  -        {            
  +        if (defaultMapToObject != null)
  +        {
               defaultMapToObject = parent.getBasePackage() + defaultMapToObject;
               mapToObjects.add(defaultMapToObject);
           }
  @@ -284,11 +284,10 @@
        */
       public String getVariable()
       {
  -        String firstChar = getName().substring(0,1).toLowerCase();
  +        String firstChar = getName().substring(0, 1).toLowerCase();
           return firstChar + getName().substring(1);
       }
   
  -
       /**
        * Creates a string representation of this input group. This
        * is an xml representation.
  @@ -297,19 +296,19 @@
       {
           StringBuffer result = new StringBuffer();
   
  -        result.append ("<group name=\"").append(getName());
  -        result.append(" key=\""+key+"\"");
  +        result.append("<group name=\"").append(getName());
  +        result.append(" key=\"" + key + "\"");
           result.append(">\n");
   
           if (fields != null)
           {
  -            for (Iterator iter = fields.iterator() ; iter.hasNext() ;)
  +            for (Iterator iter = fields.iterator(); iter.hasNext();)
               {
                   result.append(iter.next());
               }
  -        }        
  +        }
   
  -        result.append ("</group>\n");
  +        result.append("</group>\n");
   
           return result.toString();
       }
  
  
  

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